New toast notifications
This commit is contained in:
parent
b6b2706d19
commit
bd82453c3b
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -18,7 +18,7 @@ function createMeshCore(agent) {
|
||||||
var obj = {};
|
var obj = {};
|
||||||
|
|
||||||
// MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
|
// MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
|
||||||
obj.meshCoreInfo = "MeshCore v4";
|
obj.meshCoreInfo = "MeshCore v5";
|
||||||
obj.meshCoreCapabilities = 14; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
|
obj.meshCoreCapabilities = 14; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
|
||||||
var meshServerConnectionState = 0;
|
var meshServerConnectionState = 0;
|
||||||
var tunnels = {};
|
var tunnels = {};
|
||||||
|
@ -402,6 +402,11 @@ function createMeshCore(agent) {
|
||||||
getIpLocationData(function (location) { mesh.SendCommand({ "action": "iplocation", "type": "publicip", "value": location }); });
|
getIpLocationData(function (location) { mesh.SendCommand({ "action": "iplocation", "type": "publicip", "value": location }); });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'toast': {
|
||||||
|
// Display a toast message
|
||||||
|
if (data.title && data.msg) { require('toaster').Toast(data.title, data.msg); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,7 +526,6 @@ function createMeshCore(agent) {
|
||||||
|
|
||||||
// Clean up WebSocket
|
// Clean up WebSocket
|
||||||
this.removeAllListeners('data');
|
this.removeAllListeners('data');
|
||||||
delete this;
|
|
||||||
}
|
}
|
||||||
function onTunnelSendOk() { sendConsoleText("Tunnel #" + this.index + " SendOK.", this.sessionid); }
|
function onTunnelSendOk() { sendConsoleText("Tunnel #" + this.index + " SendOK.", this.sessionid); }
|
||||||
function onTunnelData(data) {
|
function onTunnelData(data) {
|
||||||
|
@ -571,19 +575,28 @@ function createMeshCore(agent) {
|
||||||
this.on('data', onTunnelControlData);
|
this.on('data', onTunnelControlData);
|
||||||
//this.write('MeshCore Terminal Hello');
|
//this.write('MeshCore Terminal Hello');
|
||||||
if (process.platform != 'win32') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nclear\n"); }
|
if (process.platform != 'win32') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nclear\n"); }
|
||||||
} else if (this.httprequest.protocol == 2) {
|
} else if (this.httprequest.protocol == 2)
|
||||||
|
{
|
||||||
// Remote desktop using native pipes
|
// Remote desktop using native pipes
|
||||||
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(), tunnel: this };
|
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(), tunnel: this };
|
||||||
this.httprequest.desktop.kvm.parent = this.httprequest.desktop;
|
this.httprequest.desktop.kvm.parent = this.httprequest.desktop;
|
||||||
this.desktop = this.httprequest.desktop;
|
this.desktop = this.httprequest.desktop;
|
||||||
|
|
||||||
|
// Display a toast message
|
||||||
|
//require('toaster').Toast('MeshCentral', 'Remote Desktop Control Started.');
|
||||||
|
|
||||||
this.end = function () {
|
this.end = function () {
|
||||||
--this.desktop.kvm.connectionCount;
|
--this.desktop.kvm.connectionCount;
|
||||||
this.unpipe(this.httprequest.desktop.kvm);
|
this.unpipe(this.httprequest.desktop.kvm);
|
||||||
this.httprequest.desktop.kvm.unpipe(this);
|
this.httprequest.desktop.kvm.unpipe(this);
|
||||||
if (this.desktop.kvm.connectionCount == 0) { this.httprequest.desktop.kvm.end(); }
|
if (this.desktop.kvm.connectionCount == 0) {
|
||||||
|
// Display a toast message
|
||||||
|
//require('toaster').Toast('MeshCentral', 'Remote Desktop Control Ended.');
|
||||||
|
this.httprequest.desktop.kvm.end();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
|
if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
|
||||||
this.pipe(this.httprequest.desktop.kvm, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. (****************)
|
this.pipe(this.httprequest.desktop.kvm, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
|
||||||
this.httprequest.desktop.kvm.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
this.httprequest.desktop.kvm.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||||
this.removeAllListeners('data');
|
this.removeAllListeners('data');
|
||||||
this.on('data', onTunnelControlData);
|
this.on('data', onTunnelControlData);
|
||||||
|
@ -839,7 +852,12 @@ function createMeshCore(agent) {
|
||||||
var response = null;
|
var response = null;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case 'help': { // Displays available commands
|
case 'help': { // Displays available commands
|
||||||
response = 'Available commands: help, info, args, print, type, dbget, dbset, dbcompact, eval, parseuri, httpget,\r\nwslist, wsconnect, wssend, wsclose, notify, ls, ps, kill, amt, netinfo, location, power, wakeonlan, scanwifi,\r\nscanamt, setdebug, smbios, rawsmbios.';
|
response = 'aaaAvailable commands: help, info, args, print, type, dbget, dbset, dbcompact, eval, parseuri, httpget,\r\nwslist, wsconnect, wssend, wsclose, notify, ls, ps, kill, amt, netinfo, location, power, wakeonlan, scanwifi,\r\nscanamt, setdebug, smbios, rawsmbios, toast.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'toast': {
|
||||||
|
require('toaster').Toast('MeshCentral', args['_'][0]);
|
||||||
|
response = 'ok';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'setdebug': {
|
case 'setdebug': {
|
||||||
|
|
|
@ -5,15 +5,16 @@ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// JavaScript source code
|
||||||
var GM = require('_GenericMarshal');
|
var GM = require('_GenericMarshal');
|
||||||
|
|
||||||
function processManager() {
|
function processManager() {
|
||||||
|
@ -34,12 +35,16 @@ function processManager() {
|
||||||
}
|
}
|
||||||
this.getProcesses = function getProcesses(callback) {
|
this.getProcesses = function getProcesses(callback) {
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
|
default:
|
||||||
|
throw ('Enumerating processes on ' + process.platform + ' not supported');
|
||||||
case 'win32':
|
case 'win32':
|
||||||
var h = this._kernel32.CreateToolhelp32Snapshot(2, 0), info = GM.CreateVariable(304), retVal = {};
|
var retVal = [];
|
||||||
|
var h = this._kernel32.CreateToolhelp32Snapshot(2, 0);
|
||||||
|
var info = GM.CreateVariable(304);
|
||||||
info.toBuffer().writeUInt32LE(304, 0);
|
info.toBuffer().writeUInt32LE(304, 0);
|
||||||
var nextProcess = this._kernel32.Process32First(h, info);
|
var nextProcess = this._kernel32.Process32First(h, info);
|
||||||
while (nextProcess.Val) {
|
while (nextProcess.Val) {
|
||||||
retVal[info.Deref(8, 4).toBuffer().readUInt32LE(0)] = { cmd: info.Deref(GM.PointerSize == 4 ? 36 : 44, 260).String };
|
retVal.push({ pid: info.Deref(8, 4).toBuffer().readUInt32LE(0), cmd: info.Deref(GM.PointerSize == 4 ? 36 : 44, 260).String });
|
||||||
nextProcess = this._kernel32.Process32Next(h, info);
|
nextProcess = this._kernel32.Process32Next(h, info);
|
||||||
}
|
}
|
||||||
if (callback) { callback.apply(this, [retVal]); }
|
if (callback) { callback.apply(this, [retVal]); }
|
||||||
|
@ -55,15 +60,16 @@ function processManager() {
|
||||||
for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); }
|
for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); }
|
||||||
p.on('exit', function onGetProcesses() {
|
p.on('exit', function onGetProcesses() {
|
||||||
delete this.Parent._psp[this.pid];
|
delete this.Parent._psp[this.pid];
|
||||||
var retVal = {}, lines = this.ps.split('\x0D\x0A'), key = {}, keyi = 0;
|
var retVal = [], lines = this.ps.split('\x0D\x0A'), key = {}, keyi = 0;
|
||||||
for (var i in lines) {
|
for (var i in lines) {
|
||||||
var tokens = lines[i].split(' '), tokenList = [];
|
var tokens = lines[i].split(' ');
|
||||||
|
var tokenList = [];
|
||||||
for (var x in tokens) {
|
for (var x in tokens) {
|
||||||
if (i == 0 && tokens[x]) { key[tokens[x]] = keyi++; }
|
if (i == 0 && tokens[x]) { key[tokens[x]] = keyi++; }
|
||||||
if (i > 0 && tokens[x]) { tokenList.push(tokens[x]); }
|
if (i > 0 && tokens[x]) { tokenList.push(tokens[x]); }
|
||||||
}
|
}
|
||||||
if ((i > 0) && (tokenList[key.PID])) {
|
if ((i > 0) && (tokenList[key.PID])) {
|
||||||
retVal[tokenList[key.PID]] = { user: tokenList[key.USER], cmd: tokenList[key.COMMAND] };
|
retVal.push({ pid: tokenList[key.PID], user: tokenList[key.USER], cmd: tokenList[key.COMMAND] });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.callback) {
|
if (this.callback) {
|
||||||
|
@ -73,22 +79,20 @@ function processManager() {
|
||||||
});
|
});
|
||||||
p.stdout.on('data', function (chunk) { this.parent.ps += chunk.toString(); });
|
p.stdout.on('data', function (chunk) { this.parent.ps += chunk.toString(); });
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
throw ('Enumerating processes on ' + process.platform + ' not supported');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.getProcessInfo = function getProcessInfo(pid) {
|
this.getProcessInfo = function getProcessInfo(pid) {
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
|
default:
|
||||||
|
throw ('getProcessInfo() not supported for ' + process.platform);
|
||||||
case 'linux':
|
case 'linux':
|
||||||
var status = require('fs').readFileSync('/proc/' + pid + '/status'), lines = status.toString().split('\n'), info = {};
|
var status = require('fs').readFileSync('/proc/' + pid + '/status'), info = {}, lines = status.toString().split('\n');
|
||||||
for (var i in lines) {
|
for (var i in lines) {
|
||||||
var tokens = lines[i].split(':');
|
var tokens = lines[i].split(':');
|
||||||
if (tokens.length > 1) { tokens[1] = tokens[1].trim(); }
|
if (tokens.length > 1) { tokens[1] = tokens[1].trim(); }
|
||||||
info[tokens[0]] = tokens[1];
|
info[tokens[0]] = tokens[1];
|
||||||
}
|
}
|
||||||
return info;
|
return (info);
|
||||||
default:
|
|
||||||
throw ('getProcessInfo() not supported for ' + process.platform);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var toasters = {};
|
||||||
|
|
||||||
|
function Toaster()
|
||||||
|
{
|
||||||
|
this._ObjectID = 'Toaster';
|
||||||
|
this.Toast = function Toast(title, caption)
|
||||||
|
{
|
||||||
|
if (process.platform != 'win32') return;
|
||||||
|
|
||||||
|
var retVal = {};
|
||||||
|
var emitter = require('events').inherits(retVal);
|
||||||
|
emitter.createEvent('Clicked');
|
||||||
|
emitter.createEvent('Dismissed');
|
||||||
|
|
||||||
|
var session = require('user-sessions').Current();
|
||||||
|
for (var i in session)
|
||||||
|
{
|
||||||
|
console.log(session[i]);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
console.log('Attempting Toast Mechanism 1');
|
||||||
|
retVal._child = require('ScriptContainer').Create({ processIsolation: true, sessionId: session.connected[0].SessionId });
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
console.log('Attempting Toast Mechanism 2');
|
||||||
|
retVal._child = require('ScriptContainer').Create({ processIsolation: true });
|
||||||
|
}
|
||||||
|
retVal._child.parent = retVal;
|
||||||
|
|
||||||
|
retVal._child.on('exit', function (code) { this.parent.emit('Dismissed'); delete this.parent._child; });
|
||||||
|
retVal._child.addModule('win-console', getJSModule('win-console'));
|
||||||
|
retVal._child.addModule('win-messagepump', getJSModule('win-messagepump'));
|
||||||
|
|
||||||
|
var str = "\
|
||||||
|
try{\
|
||||||
|
var toast = require('win-console');\
|
||||||
|
var balloon = toast.SetTrayIcon({ szInfo: '" + caption + "', szInfoTitle: '" + title + "', balloonOnly: true });\
|
||||||
|
balloon.on('ToastDismissed', function(){process.exit();});\
|
||||||
|
}\
|
||||||
|
catch(e)\
|
||||||
|
{\
|
||||||
|
require('ScriptContainer').send(e);\
|
||||||
|
}\
|
||||||
|
require('ScriptContainer').send('done');\
|
||||||
|
";
|
||||||
|
retVal._child.ExecuteString(str);
|
||||||
|
toasters[retVal._hashCode()] = retVal;
|
||||||
|
retVal.on('Dismissed', function () { delete toasters[this._hashCode()]; });
|
||||||
|
console.log('Returning');
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new Toaster();
|
|
@ -1,4 +1,18 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
function UserSessions()
|
function UserSessions()
|
||||||
{
|
{
|
||||||
|
@ -87,6 +101,8 @@ function UserSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
this._wts.WTSFreeMemory(pinfo.Deref());
|
this._wts.WTSFreeMemory(pinfo.Deref());
|
||||||
|
|
||||||
|
Object.defineProperty(retVal, 'connected', { value: showActiveOnly(retVal) });
|
||||||
return (retVal);
|
return (retVal);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -94,9 +110,58 @@ function UserSessions()
|
||||||
{
|
{
|
||||||
this.Current = function Current()
|
this.Current = function Current()
|
||||||
{
|
{
|
||||||
return ({});
|
var retVal = {};
|
||||||
|
var emitterUtils = require('events').inherits(retVal);
|
||||||
|
emitterUtils.createEvent('logon');
|
||||||
|
|
||||||
|
retVal._child = require('child_process').execFile('/usr/bin/last', ['last', '-f', '/var/run/utmp']);
|
||||||
|
retVal._child.Parent = retVal;
|
||||||
|
retVal._child._txt = '';
|
||||||
|
retVal._child.on('exit', function (code)
|
||||||
|
{
|
||||||
|
var lines = this._txt.split('\n');
|
||||||
|
var sessions = [];
|
||||||
|
for(var i in lines)
|
||||||
|
{
|
||||||
|
if (lines[i])
|
||||||
|
{
|
||||||
|
console.log(getTokens(lines[i]));
|
||||||
|
var user = lines[i].substring(0, lines[i].indexOf(' '));
|
||||||
|
sessions.push(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sessions.pop();
|
||||||
|
console.log(sessions);
|
||||||
|
});
|
||||||
|
retVal._child.stdout.Parent = retVal._child;
|
||||||
|
retVal._child.stdout.on('data', function (chunk) { this.Parent._txt += chunk.toString(); });
|
||||||
|
|
||||||
|
return (retVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function showActiveOnly(source)
|
||||||
|
{
|
||||||
|
var retVal = [];
|
||||||
|
for (var i in source)
|
||||||
|
{
|
||||||
|
if (source[i].State == 'Active' || source[i].State == 'Connected')
|
||||||
|
{
|
||||||
|
retVal.push(source[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
|
}
|
||||||
|
function getTokens(str)
|
||||||
|
{
|
||||||
|
var columns = [];
|
||||||
|
var i;
|
||||||
|
|
||||||
|
columns.push(str.substring(0, (i=str.indexOf(' '))));
|
||||||
|
while (str[++i] == ' ');
|
||||||
|
columns.push(str.substring(i, str.substring(i).indexOf(' ') + i));
|
||||||
|
|
||||||
|
return (columns);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = new UserSessions();
|
module.exports = new UserSessions();
|
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
function _Scan()
|
function _Scan()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,22 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
var MemoryStream = require('MemoryStream');
|
var MemoryStream = require('MemoryStream');
|
||||||
var WindowsChildScript = 'var parent = require("ScriptContainer");var Wireless = require("wifi-scanner-windows");Wireless.on("Scan", function (ap) { parent.send(ap); });Wireless.Scan();';
|
var WindowsChildScript = 'var parent = require("ScriptContainer");var Wireless = require("wifi-scanner-windows");Wireless.on("Scan", function (ap) { parent.send(ap); });Wireless.Scan();';
|
||||||
|
|
||||||
|
|
||||||
function AccessPoint(_ssid, _bssid, _lq)
|
function AccessPoint(_ssid, _bssid, _lq)
|
||||||
{
|
{
|
||||||
this.ssid = _ssid;
|
this.ssid = _ssid;
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var TrayIconFlags =
|
||||||
|
{
|
||||||
|
NIF_MESSAGE: 0x00000001,
|
||||||
|
NIF_ICON: 0x00000002,
|
||||||
|
NIF_TIP: 0x00000004,
|
||||||
|
NIF_STATE: 0x00000008,
|
||||||
|
NIF_INFO: 0x00000010,
|
||||||
|
NIF_GUID: 0x00000020,
|
||||||
|
NIF_REALTIME: 0x00000040,
|
||||||
|
NIF_SHOWTIP: 0x00000080,
|
||||||
|
|
||||||
|
NIM_ADD: 0x00000000,
|
||||||
|
NIM_MODIFY: 0x00000001,
|
||||||
|
NIM_DELETE: 0x00000002,
|
||||||
|
NIM_SETFOCUS: 0x00000003,
|
||||||
|
NIM_SETVERSION: 0x00000004
|
||||||
|
};
|
||||||
|
var NOTIFYICON_VERSION_4 = 4;
|
||||||
|
var MessageTypes = { WM_APP: 0x8000, WM_USER: 0x0400 };
|
||||||
|
function WindowsConsole()
|
||||||
|
{
|
||||||
|
if (process.platform == 'win32')
|
||||||
|
{
|
||||||
|
this._ObjectID = 'WindowsConsole';
|
||||||
|
this._Marshal = require('_GenericMarshal');
|
||||||
|
this._kernel32 = this._Marshal.CreateNativeProxy("kernel32.dll");
|
||||||
|
this._user32 = this._Marshal.CreateNativeProxy("user32.dll");
|
||||||
|
this._kernel32.CreateMethod("GetConsoleWindow");
|
||||||
|
this._kernel32.CreateMethod('GetCurrentThread');
|
||||||
|
this._user32.CreateMethod("ShowWindow");
|
||||||
|
this._user32.CreateMethod("LoadImageA");
|
||||||
|
this._user32.CreateMethod({ method: 'GetMessageA', threadDispatch: 1 });
|
||||||
|
this._shell32 = this._Marshal.CreateNativeProxy('Shell32.dll');
|
||||||
|
this._shell32.CreateMethod('Shell_NotifyIconA');
|
||||||
|
|
||||||
|
this._handle = this._kernel32.GetConsoleWindow();
|
||||||
|
this.minimize = function () {
|
||||||
|
this._user32.ShowWindow(this._handle, 6);
|
||||||
|
};
|
||||||
|
this.restore = function () {
|
||||||
|
this._user32.ShowWindow(this._handle, 9);
|
||||||
|
};
|
||||||
|
this.hide = function () {
|
||||||
|
this._user32.ShowWindow(this._handle, 0);
|
||||||
|
};
|
||||||
|
this.show = function () {
|
||||||
|
this._user32.ShowWindow(this._handle, 5);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
this._loadicon = function (imagePath) {
|
||||||
|
var h = this._user32.LoadImageA(0, this._Marshal.CreateVariable(imagePath), 1, 0, 0, 0x00000010 | 0x00008000 | 0x00000040); // LR_LOADFROMFILE | LR_SHARED | LR_DEFAULTSIZE
|
||||||
|
return (h);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.SetTrayIcon = function SetTrayIcon(options)
|
||||||
|
{
|
||||||
|
var data = this._Marshal.CreateVariable(this._Marshal.PointerSize == 4 ? 508 : 528);
|
||||||
|
//console.log('struct size = ' + data._size);
|
||||||
|
//console.log('TryIcon, WM_MESSAGE filter = ' + options.filter);
|
||||||
|
data.toBuffer().writeUInt32LE(data._size, 0);
|
||||||
|
|
||||||
|
var trayType = TrayIconFlags.NIF_TIP | TrayIconFlags.NIF_MESSAGE
|
||||||
|
options.filter = MessageTypes.WM_APP + 1;
|
||||||
|
data.Deref(this._Marshal.PointerSize == 4 ? 16 : 24, 4).toBuffer().writeUInt32LE(options.filter);
|
||||||
|
|
||||||
|
if (!options.noBalloon) { trayType |= TrayIconFlags.NIF_INFO; }
|
||||||
|
|
||||||
|
if (options.icon)
|
||||||
|
{
|
||||||
|
trayType |= TrayIconFlags.NIF_ICON;
|
||||||
|
var hIcon = data.Deref(this._Marshal.PointerSize == 4 ? 20 : 32, this._Marshal.PointerSize);
|
||||||
|
options.icon.pointerBuffer().copy(hIcon.toBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Deref(this._Marshal.PointerSize * 2, 4).toBuffer().writeUInt32LE(1);
|
||||||
|
data.Deref(this._Marshal.PointerSize == 4 ? 12 : 20, 4).toBuffer().writeUInt32LE(trayType);
|
||||||
|
data.Deref(this._Marshal.PointerSize == 4 ? 416 : 432, 4).toBuffer().writeUInt32LE(NOTIFYICON_VERSION_4);
|
||||||
|
|
||||||
|
var szTip = data.Deref(this._Marshal.PointerSize == 4 ? 24 : 40, 128);
|
||||||
|
var szInfo = data.Deref(this._Marshal.PointerSize == 4 ? 160 : 176, 256);
|
||||||
|
var szInfoTitle = data.Deref(this._Marshal.PointerSize == 4 ? 420 : 436, 64);
|
||||||
|
|
||||||
|
if (options.szTip) { Buffer.from(options.szTip).copy(szTip.toBuffer()); }
|
||||||
|
if (options.szInfo) { Buffer.from(options.szInfo).copy(szInfo.toBuffer()); }
|
||||||
|
if (options.szInfoTitle) { Buffer.from(options.szInfoTitle).copy(szInfoTitle.toBuffer()); }
|
||||||
|
|
||||||
|
|
||||||
|
var MessagePump = require('win-messagepump');
|
||||||
|
retVal = { _ObjectID: 'WindowsConsole.TrayIcon', MessagePump: new MessagePump(options) };
|
||||||
|
var retValEvents = require('events').inherits(retVal);
|
||||||
|
retValEvents.createEvent('ToastClicked');
|
||||||
|
retValEvents.createEvent('IconHover');
|
||||||
|
retValEvents.createEvent('ToastDismissed');
|
||||||
|
retVal.Options = options;
|
||||||
|
retVal.MessagePump.TrayIcon = retVal;
|
||||||
|
retVal.MessagePump.NotifyData = data;
|
||||||
|
retVal.MessagePump.WindowsConsole = this;
|
||||||
|
retVal.MessagePump.on('exit', function onExit(code) { console.log('Pump Exited'); if (this.TrayIcon) { this.TrayIcon.remove(); } });
|
||||||
|
retVal.MessagePump.on('hwnd', function onHwnd(h)
|
||||||
|
{
|
||||||
|
//console.log('Got HWND');
|
||||||
|
options.hwnd = h;
|
||||||
|
h.pointerBuffer().copy(this.NotifyData.Deref(this.WindowsConsole._Marshal.PointerSize, this.WindowsConsole._Marshal.PointerSize).toBuffer());
|
||||||
|
|
||||||
|
if(this.WindowsConsole._shell32.Shell_NotifyIconA(TrayIconFlags.NIM_ADD, this.NotifyData).Val == 0)
|
||||||
|
{
|
||||||
|
// Something went wrong
|
||||||
|
}
|
||||||
|
});
|
||||||
|
retVal.MessagePump.on('message', function onWindowsMessage(msg)
|
||||||
|
{
|
||||||
|
if(msg.message == this.TrayIcon.Options.filter)
|
||||||
|
{
|
||||||
|
var handled = false;
|
||||||
|
if (msg.wparam == 1 && msg.lparam == 1029)
|
||||||
|
{
|
||||||
|
this.TrayIcon.emit('ToastClicked');
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
if (msg.wparam == 1 && msg.lparam == 512)
|
||||||
|
{
|
||||||
|
this.TrayIcon.emit('IconHover');
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
if (this.TrayIcon.Options.balloonOnly && msg.wparam == 1 && (msg.lparam == 1028 || msg.lparam == 1029))
|
||||||
|
{
|
||||||
|
this.TrayIcon.emit('ToastDismissed');
|
||||||
|
this.TrayIcon.remove();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
if (!handled) { console.log(msg); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
retVal.remove = function remove()
|
||||||
|
{
|
||||||
|
this.MessagePump.WindowsConsole._shell32.Shell_NotifyIconA(TrayIconFlags.NIM_DELETE, this.MessagePump.NotifyData);
|
||||||
|
this.MessagePump.stop();
|
||||||
|
delete this.MessagePump.TrayIcon;
|
||||||
|
delete this.MessagePump;
|
||||||
|
};
|
||||||
|
return (retVal);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new WindowsConsole();
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var WH_CALLWNDPROC = 4;
|
||||||
|
var WM_QUIT = 0x0012;
|
||||||
|
|
||||||
|
function WindowsMessagePump(options)
|
||||||
|
{
|
||||||
|
this._ObjectID = 'WindowsMessagePump';
|
||||||
|
this._options = options;
|
||||||
|
var emitterUtils = require('events').inherits(this);
|
||||||
|
emitterUtils.createEvent('hwnd');
|
||||||
|
emitterUtils.createEvent('error');
|
||||||
|
emitterUtils.createEvent('message');
|
||||||
|
emitterUtils.createEvent('exit');
|
||||||
|
|
||||||
|
this._child = require('ScriptContainer').Create({ processIsolation: 0 });
|
||||||
|
this._child.MessagePump = this;
|
||||||
|
this._child.prependListener('~', function _childFinalizer() { this.MessagePump.emit('exit', 0); console.log('calling stop'); this.MessagePump.stop(); });
|
||||||
|
this._child.once('exit', function onExit(code) { this.MessagePump.emit('exit', code); });
|
||||||
|
this._child.once('ready', function onReady()
|
||||||
|
{
|
||||||
|
console.log('child ready');
|
||||||
|
var execString =
|
||||||
|
"var m = require('_GenericMarshal');\
|
||||||
|
var h = null;\
|
||||||
|
var k = m.CreateNativeProxy('Kernel32.dll');\
|
||||||
|
k.CreateMethod('GetLastError');\
|
||||||
|
k.CreateMethod('GetModuleHandleA');\
|
||||||
|
var u = m.CreateNativeProxy('User32.dll');\
|
||||||
|
u.CreateMethod('GetMessageA');\
|
||||||
|
u.CreateMethod('CreateWindowExA');\
|
||||||
|
u.CreateMethod('TranslateMessage');\
|
||||||
|
u.CreateMethod('DispatchMessageA');\
|
||||||
|
u.CreateMethod('RegisterClassExA');\
|
||||||
|
u.CreateMethod('DefWindowProcA');\
|
||||||
|
var wndclass = m.CreateVariable(m.PointerSize == 4 ? 48 : 80);\
|
||||||
|
wndclass.hinstance = k.GetModuleHandleA(0);\
|
||||||
|
wndclass.cname = m.CreateVariable('MainWWWClass');\
|
||||||
|
wndclass.wndproc = m.GetGenericGlobalCallback(4);\
|
||||||
|
wndclass.toBuffer().writeUInt32LE(wndclass._size);\
|
||||||
|
wndclass.cname.pointerBuffer().copy(wndclass.Deref(m.PointerSize == 4 ? 40 : 64, m.PointerSize).toBuffer());\
|
||||||
|
wndclass.wndproc.pointerBuffer().copy(wndclass.Deref(8, m.PointerSize).toBuffer());\
|
||||||
|
wndclass.hinstance.pointerBuffer().copy(wndclass.Deref(m.PointerSize == 4 ? 20 : 24, m.PointerSize).toBuffer());\
|
||||||
|
wndclass.wndproc.on('GlobalCallback', function onWndProc(xhwnd, xmsg, wparam, lparam)\
|
||||||
|
{\
|
||||||
|
if(h==null || h.Val == xhwnd.Val)\
|
||||||
|
{\
|
||||||
|
require('ScriptContainer').send({message: xmsg.Val, wparam: wparam.Val, lparam: lparam.Val});\
|
||||||
|
var retVal = u.DefWindowProcA(xhwnd, xmsg, wparam, lparam);\
|
||||||
|
return(retVal);\
|
||||||
|
}\
|
||||||
|
});\
|
||||||
|
u.RegisterClassExA(wndclass);\
|
||||||
|
h = u.CreateWindowExA(0x00000088, wndclass.cname, 0, 0x00800000, 0, 0, 100, 100, 0, 0, 0, 0);\
|
||||||
|
if(h.Val == 0)\
|
||||||
|
{\
|
||||||
|
require('ScriptContainer').send({error: 'Error Creating Hidden Window'});\
|
||||||
|
process.exit();\
|
||||||
|
}\
|
||||||
|
require('ScriptContainer').send({hwnd: h.pointerBuffer().toString('hex')});\
|
||||||
|
require('ScriptContainer').on('data', function onData(jmsg)\
|
||||||
|
{\
|
||||||
|
if(jmsg.listen)\
|
||||||
|
{\
|
||||||
|
var msg = m.CreateVariable(m.PointerSize == 4 ? 28 : 48);\
|
||||||
|
while(u.GetMessageA(msg, h, 0, 0).Val>0)\
|
||||||
|
{\
|
||||||
|
u.TranslateMessage(msg);\
|
||||||
|
u.DispatchMessageA(msg);\
|
||||||
|
}\
|
||||||
|
process.exit();\
|
||||||
|
}\
|
||||||
|
});";
|
||||||
|
|
||||||
|
this.ExecuteString(execString);
|
||||||
|
});
|
||||||
|
this._child.on('data', function onChildData(msg)
|
||||||
|
{
|
||||||
|
if (msg.hwnd)
|
||||||
|
{
|
||||||
|
var m = require('_GenericMarshal');
|
||||||
|
this._hwnd = m.CreatePointer(Buffer.from(msg.hwnd, 'hex'));
|
||||||
|
this.MessagePump.emit('hwnd', this._hwnd);
|
||||||
|
this.send({ listen: this.MessagePump._options.filter });
|
||||||
|
}
|
||||||
|
else if(msg.message)
|
||||||
|
{
|
||||||
|
this.MessagePump.emit('message', msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log('Received: ', msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.stop = function stop()
|
||||||
|
{
|
||||||
|
if(this._child && this._child._hwnd)
|
||||||
|
{
|
||||||
|
console.log('posting WM_QUIT');
|
||||||
|
var marshal = require('_GenericMarshal');
|
||||||
|
var User32 = marshal.CreateNativeProxy('User32.dll');
|
||||||
|
User32.CreateMethod('PostMessageA');
|
||||||
|
User32.PostMessageA(this._child._hwnd, WM_QUIT, 0, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = WindowsMessagePump;
|
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var KEY_QUERY_VALUE = 0x0001;
|
||||||
|
var KEY_WRITE = 0x20006;
|
||||||
|
|
||||||
|
var KEY_DATA_TYPES =
|
||||||
|
{
|
||||||
|
REG_NONE: 0,
|
||||||
|
REG_SZ: 1,
|
||||||
|
REG_EXPAND_SZ: 2,
|
||||||
|
REG_BINARY: 3,
|
||||||
|
REG_DWORD: 4,
|
||||||
|
REG_DWORD_BIG_ENDIAN: 5,
|
||||||
|
REG_LINK: 6,
|
||||||
|
REG_MULTI_SZ: 7,
|
||||||
|
REG_RESOURCE_LIST: 8,
|
||||||
|
REG_FULL_RESOURCE_DESCRIPTOR: 9,
|
||||||
|
REG_RESOURCE_REQUIREMENTS_LIST: 10,
|
||||||
|
REG_QWORD: 11
|
||||||
|
};
|
||||||
|
|
||||||
|
function windows_registry()
|
||||||
|
{
|
||||||
|
this._ObjectId = 'windows_registry';
|
||||||
|
this._marshal = require('_GenericMarshal');
|
||||||
|
this._AdvApi = this._marshal.CreateNativeProxy('Advapi32.dll');
|
||||||
|
this._AdvApi.CreateMethod('RegCreateKeyExA');
|
||||||
|
this._AdvApi.CreateMethod('RegOpenKeyExA');
|
||||||
|
this._AdvApi.CreateMethod('RegQueryValueExA');
|
||||||
|
this._AdvApi.CreateMethod('RegCloseKey');
|
||||||
|
this._AdvApi.CreateMethod('RegDeleteKeyA');
|
||||||
|
this._AdvApi.CreateMethod('RegDeleteValueA');
|
||||||
|
this._AdvApi.CreateMethod('RegSetValueExA');
|
||||||
|
this.HKEY = { Root: Buffer.from('80000000', 'hex').swap32(), CurrentUser: Buffer.from('80000001', 'hex').swap32(), LocalMachine: Buffer.from('80000002', 'hex').swap32(), Users: Buffer.from('80000003', 'hex').swap32() };
|
||||||
|
|
||||||
|
this.QueryKey = function QueryKey(hkey, path, key)
|
||||||
|
{
|
||||||
|
var h = this._marshal.CreatePointer();
|
||||||
|
var len = this._marshal.CreateVariable(4);
|
||||||
|
var valType = this._marshal.CreateVariable(4);
|
||||||
|
key = this._marshal.CreateVariable(key);
|
||||||
|
var HK = this._marshal.CreatePointer(hkey);
|
||||||
|
var retVal = null;
|
||||||
|
|
||||||
|
if (this._AdvApi.RegOpenKeyExA(HK, this._marshal.CreateVariable(path), 0, KEY_QUERY_VALUE, h).Val != 0)
|
||||||
|
{
|
||||||
|
throw ('Error Opening Registry Key: ' + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this._AdvApi.RegQueryValueExA(h.Deref(), key, 0, 0, 0, len).Val == 0)
|
||||||
|
{
|
||||||
|
var data = this._marshal.CreateVariable(len.toBuffer().readUInt32LE());
|
||||||
|
if (this._AdvApi.RegQueryValueExA(h.Deref(), key, 0, valType, data, len).Val == 0)
|
||||||
|
{
|
||||||
|
switch(valType.toBuffer().readUInt32LE())
|
||||||
|
{
|
||||||
|
case KEY_DATA_TYPES.REG_DWORD:
|
||||||
|
retVal = data.toBuffer().readUInt32LE();
|
||||||
|
break;
|
||||||
|
case KEY_DATA_TYPES.REG_DWORD_BIG_ENDIAN:
|
||||||
|
retVal = data.toBuffer().readUInt32BE();
|
||||||
|
break;
|
||||||
|
case KEY_DATA_TYPES.REG_SZ:
|
||||||
|
retVal = data.String;
|
||||||
|
break;
|
||||||
|
case KEY_DATA_TYPES.REG_BINARY:
|
||||||
|
default:
|
||||||
|
retVal = data.toBuffer();
|
||||||
|
retVal._data = data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
throw ('Not Found');
|
||||||
|
}
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
this.WriteKey = function WriteKey(hkey, path, key, value)
|
||||||
|
{
|
||||||
|
var result;
|
||||||
|
var h = this._marshal.CreatePointer();
|
||||||
|
|
||||||
|
if (this._AdvApi.RegCreateKeyExA(this._marshal.CreatePointer(hkey), this._marshal.CreateVariable(path), 0, 0, 0, KEY_WRITE, 0, h, 0).Val != 0)
|
||||||
|
{
|
||||||
|
throw ('Error Opening Registry Key: ' + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
var data;
|
||||||
|
var dataType;
|
||||||
|
|
||||||
|
switch(typeof(value))
|
||||||
|
{
|
||||||
|
case 'boolean':
|
||||||
|
dataType = KEY_DATA_TYPES.REG_DWORD;
|
||||||
|
data = this._marshal.CreateVariable(4);
|
||||||
|
data.toBuffer().writeUInt32LE(value ? 1 : 0);
|
||||||
|
break;
|
||||||
|
case 'number':
|
||||||
|
dataType = KEY_DATA_TYPES.REG_DWORD;
|
||||||
|
data = this._marshal.CreateVariable(4);
|
||||||
|
data.toBuffer().writeUInt32LE(value);
|
||||||
|
break;
|
||||||
|
case 'string':
|
||||||
|
dataType = KEY_DATA_TYPES.REG_SZ;
|
||||||
|
data = this._marshal.CreateVariable(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dataType = KEY_DATA_TYPES.REG_BINARY;
|
||||||
|
data = this._marshal.CreateVariable(value.length);
|
||||||
|
value.copy(data.toBuffer());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this._AdvApi.RegSetValueExA(h.Deref(), this._marshal.CreateVariable(key), 0, dataType, data, data._size).Val != 0)
|
||||||
|
{
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
throw ('Error writing reg key: ' + key);
|
||||||
|
}
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
};
|
||||||
|
this.DeleteKey = function DeleteKey(hkey, path, key)
|
||||||
|
{
|
||||||
|
if(!key)
|
||||||
|
{
|
||||||
|
if(this._AdvApi.RegDeleteKeyA(this._marshal.CreatePointer(hkey), this._marshal.CreateVariable(path)).Val != 0)
|
||||||
|
{
|
||||||
|
throw ('Error Deleting Key: ' + path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var h = this._marshal.CreatePointer();
|
||||||
|
var result;
|
||||||
|
if (this._AdvApi.RegOpenKeyExA(this._marshal.CreatePointer(hkey), this._marshal.CreateVariable(path), 0, KEY_QUERY_VALUE | KEY_WRITE, h).Val != 0)
|
||||||
|
{
|
||||||
|
throw ('Error Opening Registry Key: ' + path);
|
||||||
|
}
|
||||||
|
if ((result = this._AdvApi.RegDeleteValueA(h.Deref(), this._marshal.CreateVariable(key)).Val) != 0)
|
||||||
|
{
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
throw ('Error[' + result + '] Deleting Key: ' + path + '.' + key);
|
||||||
|
}
|
||||||
|
this._AdvApi.RegCloseKey(h.Deref());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new windows_registry();
|
||||||
|
|
|
@ -75,7 +75,7 @@ module.exports.CreateLetsEncrypt = function (parent) {
|
||||||
func(certs);
|
func(certs);
|
||||||
|
|
||||||
// Check if the Let's Encrypt certificate needs to be renewed.
|
// Check if the Let's Encrypt certificate needs to be renewed.
|
||||||
setTimeout(obj.checkRenewCertificate, 300000); // Check in 5 minutes.
|
setTimeout(obj.checkRenewCertificate, 60000); // Check in 1 minute.
|
||||||
setInterval(obj.checkRenewCertificate, 86400000); // Check again in 24 hours and every 24 hours.
|
setInterval(obj.checkRenewCertificate, 86400000); // Check again in 24 hours and every 24 hours.
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -111,7 +111,7 @@ module.exports.CreateLetsEncrypt = function (parent) {
|
||||||
if (obj.leResults == null) { return; }
|
if (obj.leResults == null) { return; }
|
||||||
// TODO: Only renew on one of the peers if multi-peers are active.
|
// TODO: Only renew on one of the peers if multi-peers are active.
|
||||||
// Check if we need to renew the certificate
|
// Check if we need to renew the certificate
|
||||||
obj.le.renew({ duplicate: false }, obj.leResults).then(function (xresults) {
|
obj.le.renew({ duplicate: false, domains: obj.leDomains, email: obj.parent.config.letsencrypt.email }, obj.leResults).then(function (xresults) {
|
||||||
obj.parent.performServerCertUpdate(); // Reset the server, TODO: Reset all peers
|
obj.parent.performServerCertUpdate(); // Reset the server, TODO: Reset all peers
|
||||||
}, function (err) { }); // If we can't renew, ignore.
|
}, function (err) { }); // If we can't renew, ignore.
|
||||||
}
|
}
|
||||||
|
|
34
meshuser.js
34
meshuser.js
|
@ -873,6 +873,40 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'toast':
|
||||||
|
{
|
||||||
|
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||||
|
if (obj.common.validateString(command.title, 1, 512) == false) break; // Check title
|
||||||
|
if (obj.common.validateString(command.msg, 1, 4096) == false) break; // Check message
|
||||||
|
for (var i in command.nodeids) {
|
||||||
|
var nodeid = command.nodeids[i], powerActions = 0;
|
||||||
|
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||||
|
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||||
|
// Get the device
|
||||||
|
obj.db.Get(nodeid, function (err, nodes) {
|
||||||
|
if (nodes.length != 1) return;
|
||||||
|
var node = nodes[0];
|
||||||
|
|
||||||
|
// Get the mesh for this device
|
||||||
|
var mesh = obj.parent.meshes[node.meshid];
|
||||||
|
if (mesh) {
|
||||||
|
|
||||||
|
// Check if this user has rights to do this
|
||||||
|
if (mesh.links[user._id] != null && ((mesh.links[user._id].rights & 8) != 0)) { // "Remote Control permission"
|
||||||
|
|
||||||
|
// Get this device
|
||||||
|
var agent = obj.parent.wsagents[node._id];
|
||||||
|
if (agent != null) {
|
||||||
|
// Send the power command
|
||||||
|
agent.send(JSON.stringify({ action: 'toast', title: command.title, msg: command.msg }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'getnetworkinfo':
|
case 'getnetworkinfo':
|
||||||
{
|
{
|
||||||
// Argument validation
|
// Argument validation
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.1.6-q",
|
"version": "0.1.6-s",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
|
@ -81,9 +81,6 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the WebRTC connection, should be called if a problem occurs during WebRTC setup.
|
|
||||||
obj.xxCloseWebRTC = function () { obj.Stop(); }
|
|
||||||
|
|
||||||
obj.xxOnMessage = function (e) {
|
obj.xxOnMessage = function (e) {
|
||||||
//if (obj.debugmode == 1) { console.log('Recv', e.data); }
|
//if (obj.debugmode == 1) { console.log('Recv', e.data); }
|
||||||
//console.log('Recv', e.data, obj.State);
|
//console.log('Recv', e.data, obj.State);
|
||||||
|
@ -111,7 +108,8 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||||
}
|
}
|
||||||
obj.webrtc.oniceconnectionstatechange = function () {
|
obj.webrtc.oniceconnectionstatechange = function () {
|
||||||
if (obj.webrtc != null) {
|
if (obj.webrtc != null) {
|
||||||
if ((obj.webrtc.iceConnectionState == 'disconnected') || (obj.webrtc.iceConnectionState == 'failed')) { obj.xxCloseWebRTC(); }
|
if (obj.webrtc.iceConnectionState == 'disconnected') { obj.Stop(); }
|
||||||
|
else if (obj.webrtc.iceConnectionState == 'failed') { obj.xxCloseWebRTC(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
obj.webrtc.createOffer(function (offer) {
|
obj.webrtc.createOffer(function (offer) {
|
||||||
|
@ -206,13 +204,18 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||||
if (obj.onStateChanged != null) obj.onStateChanged(obj, obj.State);
|
if (obj.onStateChanged != null) obj.onStateChanged(obj, obj.State);
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.Stop = function (x) {
|
// Close the WebRTC connection, should be called if a problem occurs during WebRTC setup.
|
||||||
if (obj.debugmode == 1) { console.log('stop', x); }
|
obj.xxCloseWebRTC = function () {
|
||||||
|
|
||||||
// Close WebRTC
|
|
||||||
if (obj.webchannel != null) { try { obj.webchannel.close(); } catch (e) { } obj.webchannel = null; }
|
if (obj.webchannel != null) { try { obj.webchannel.close(); } catch (e) { } obj.webchannel = null; }
|
||||||
if (obj.webrtc != null) { try { obj.webrtc.close(); } catch (e) { } obj.webrtc = null; }
|
if (obj.webrtc != null) { try { obj.webrtc.close(); } catch (e) { } obj.webrtc = null; }
|
||||||
obj.webRtcActive = false;
|
obj.webRtcActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.Stop = function (x) {
|
||||||
|
if (obj.debugmode == 1) { console.log('stop', x); }
|
||||||
|
|
||||||
|
// Clean up WebRTC
|
||||||
|
obj.xxCloseWebRTC();
|
||||||
|
|
||||||
//obj.debug("Agent Redir Socket Stopped");
|
//obj.debug("Agent Redir Socket Stopped");
|
||||||
obj.connectstate = -1;
|
obj.connectstate = -1;
|
||||||
|
|
|
@ -572,6 +572,7 @@
|
||||||
<div id=p16events style="max-height:600px;overflow-y:scroll"></div>
|
<div id=p16events style="max-height:600px;overflow-y:scroll"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id=p20 style=display:none>
|
<div id=p20 style=display:none>
|
||||||
|
<img id=MainMeshImage src="images/mesh-200.png" style=border-width:0px;height:200px;width:200px;float:right>
|
||||||
<h1><span id=p20meshName></span> - General</h1>
|
<h1><span id=p20meshName></span> - General</h1>
|
||||||
<p id=p20info></p>
|
<p id=p20info></p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2848,6 +2849,7 @@
|
||||||
// Show action button, only show if we have permissions 4, 8, 64
|
// Show action button, only show if we have permissions 4, 8, 64
|
||||||
if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
|
if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
|
||||||
x += '<input type=button value=Notes title="View notes about this device" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
|
x += '<input type=button value=Notes title="View notes about this device" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
|
||||||
|
if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast title="Display a text message of the remote device" onclick=deviceToastFunction() />'; }
|
||||||
QH('p10html', x);
|
QH('p10html', x);
|
||||||
|
|
||||||
// Show node last 7 days timeline
|
// Show node last 7 days timeline
|
||||||
|
@ -2939,7 +2941,17 @@
|
||||||
|
|
||||||
function showNotesEx(buttons, tag) { meshserver.send({ action: 'setNotes', id: decodeURIComponent(tag), notes: encodeURIComponent(Q('d2devNotes').value) }); }
|
function showNotesEx(buttons, tag) { meshserver.send({ action: 'setNotes', id: decodeURIComponent(tag), notes: encodeURIComponent(Q('d2devNotes').value) }); }
|
||||||
|
|
||||||
|
function deviceToastFunction() {
|
||||||
|
if (xxdialogMode) return;
|
||||||
|
setDialogMode(2, "Device Toast", 3, deviceToastFunctionEx, '<textarea id=d2devToast style=width:100%;height:80px;resize:none;overflow-y:scroll></textarea>');
|
||||||
|
}
|
||||||
|
|
||||||
|
function deviceToastFunctionEx() {
|
||||||
|
meshserver.send({ action: 'toast', nodeids: [ currentNode._id ], title: 'MeshCentral', msg: Q('d2devToast').value });
|
||||||
|
}
|
||||||
|
|
||||||
function deviceActionFunction() {
|
function deviceActionFunction() {
|
||||||
|
if (xxdialogMode) return;
|
||||||
var meshrights = meshes[currentNode.meshid].links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
|
var meshrights = meshes[currentNode.meshid].links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
|
||||||
var x = "Select an operation to perform on this device.<br /><br />";
|
var x = "Select an operation to perform on this device.<br /><br />";
|
||||||
var y = '<select id=d2deviceop style=float:right;width:250px>';
|
var y = '<select id=d2deviceop style=float:right;width:250px>';
|
||||||
|
@ -4542,7 +4554,7 @@
|
||||||
|
|
||||||
x += '<br><input type=button value=Notes title="View notes about this mesh" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />';
|
x += '<br><input type=button value=Notes title="View notes about this mesh" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />';
|
||||||
|
|
||||||
x += '<br><br>';
|
x += '<br style=clear:both><br>';
|
||||||
var currentMeshLinks = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()];
|
var currentMeshLinks = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()];
|
||||||
if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a onclick=p20showAddMeshUserDialog() style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> Add User</a>'; }
|
if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a onclick=p20showAddMeshUserDialog() style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> Add User</a>'; }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue