mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-27 16:02:16 +03:00
Clean up.
This commit is contained in:
parent
21699caa71
commit
6451d451d3
@ -1,163 +0,0 @@
|
||||
/*
|
||||
Copyright 2018-2019 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 GM = require('_GenericMarshal');
|
||||
|
||||
// Used on Windows and Linux to get information about running processes
|
||||
function processManager() {
|
||||
this._ObjectID = 'process-manager'; // Used for debugging, allows you to get the object type at runtime.
|
||||
|
||||
// Setup the platform specific calls.
|
||||
switch (process.platform)
|
||||
{
|
||||
case 'win32':
|
||||
this._kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||
this._kernel32.CreateMethod('GetLastError');
|
||||
this._kernel32.CreateMethod('CreateToolhelp32Snapshot');
|
||||
this._kernel32.CreateMethod('Process32First');
|
||||
this._kernel32.CreateMethod('Process32Next');
|
||||
break;
|
||||
case 'linux':
|
||||
case 'darwin':
|
||||
this._childProcess = require('child_process');
|
||||
break;
|
||||
default:
|
||||
throw (process.platform + ' not supported');
|
||||
break;
|
||||
}
|
||||
this.enumerateProcesses = function enumerateProcesses()
|
||||
{
|
||||
var promise = require('promise');
|
||||
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||
this.getProcesses(function (ps, prom) { prom._res(ps); }, ret);
|
||||
return (ret);
|
||||
}
|
||||
// Return a object of: pid -> process information.
|
||||
this.getProcesses = function getProcesses(callback)
|
||||
{
|
||||
switch(process.platform)
|
||||
{
|
||||
default:
|
||||
throw ('Enumerating processes on ' + process.platform + ' not supported');
|
||||
break;
|
||||
case 'win32': // Windows processes
|
||||
var retVal = {};
|
||||
var h = this._kernel32.CreateToolhelp32Snapshot(2, 0);
|
||||
var info = GM.CreateVariable(304);
|
||||
info.toBuffer().writeUInt32LE(304, 0);
|
||||
var nextProcess = this._kernel32.Process32First(h, info);
|
||||
while (nextProcess.Val)
|
||||
{
|
||||
retVal[info.Deref(8, 4).toBuffer().readUInt32LE(0)] = { pid: info.Deref(8, 4).toBuffer().readUInt32LE(0), cmd: info.Deref(GM.PointerSize == 4 ? 36 : 44, 260).String };
|
||||
nextProcess = this._kernel32.Process32Next(h, info);
|
||||
}
|
||||
if (callback) { callback.apply(this, [retVal]); }
|
||||
break;
|
||||
case 'linux': // Linux processes
|
||||
if (!this._psp) { this._psp = {}; }
|
||||
var p = this._childProcess.execFile("/bin/ps", ["ps", "-uxa"], { type: this._childProcess.SpawnTypes.TERM });
|
||||
this._psp[p.pid] = p;
|
||||
p.Parent = this;
|
||||
p.ps = '';
|
||||
p.callback = callback;
|
||||
p.args = [];
|
||||
for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); }
|
||||
p.on('exit', function onGetProcesses()
|
||||
{
|
||||
delete this.Parent._psp[this.pid];
|
||||
var retVal = {}, lines = this.ps.split('\x0D\x0A'), key = {}, keyi = 0;
|
||||
for (var i in lines)
|
||||
{
|
||||
var tokens = lines[i].split(' ');
|
||||
var tokenList = [];
|
||||
for(var x in tokens)
|
||||
{
|
||||
if (i == 0 && tokens[x]) { key[tokens[x]] = keyi++; }
|
||||
if (i > 0 && tokens[x]) { tokenList.push(tokens[x]);}
|
||||
}
|
||||
if (i > 0) {
|
||||
if (tokenList[key.PID]) { retVal[tokenList[key.PID]] = { pid: key.PID, user: tokenList[key.USER], cmd: tokenList[key.COMMAND] }; }
|
||||
}
|
||||
}
|
||||
if (this.callback)
|
||||
{
|
||||
this.args.unshift(retVal);
|
||||
this.callback.apply(this.parent, this.args);
|
||||
}
|
||||
});
|
||||
p.stdout.on('data', function (chunk) { this.parent.ps += chunk.toString(); });
|
||||
break;
|
||||
case 'darwin':
|
||||
var promise = require('promise');
|
||||
var p = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||
p.pm = this;
|
||||
p.callback = callback;
|
||||
p.args = [];
|
||||
for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); }
|
||||
p.child = this._childProcess.execFile("/bin/ps", ["ps", "-xa"]);
|
||||
p.child.promise = p;
|
||||
p.child.stdout.ps = '';
|
||||
p.child.stdout.on('data', function (chunk) { this.ps += chunk.toString(); });
|
||||
p.child.on('exit', function ()
|
||||
{
|
||||
var lines = this.stdout.ps.split('\n');
|
||||
var pidX = lines[0].split('PID')[0].length + 3;
|
||||
var cmdX = lines[0].split('CMD')[0].length;
|
||||
var ret = {};
|
||||
for (var i = 1; i < lines.length; ++i)
|
||||
{
|
||||
if (lines[i].length > 0)
|
||||
{
|
||||
ret[lines[i].substring(0, pidX).trim()] = { pid: lines[i].substring(0, pidX).trim(), cmd: lines[i].substring(cmdX) };
|
||||
}
|
||||
}
|
||||
this.promise._res(ret);
|
||||
});
|
||||
p.then(function (ps)
|
||||
{
|
||||
this.args.unshift(ps);
|
||||
this.callback.apply(this.pm, this.args);
|
||||
});
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Get information about a specific process on Linux
|
||||
this.getProcessInfo = function getProcessInfo(pid)
|
||||
{
|
||||
switch(process.platform)
|
||||
{
|
||||
default:
|
||||
throw ('getProcessInfo() not supported for ' + process.platform);
|
||||
break;
|
||||
case 'linux':
|
||||
var status = require('fs').readFileSync('/proc/' + pid + '/status');
|
||||
var info = {};
|
||||
var lines = status.toString().split('\n');
|
||||
for(var i in lines)
|
||||
{
|
||||
var tokens = lines[i].split(':');
|
||||
if (tokens.length > 1) { tokens[1] = tokens[1].trim(); }
|
||||
info[tokens[0]] = tokens[1];
|
||||
}
|
||||
return (info);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = new processManager();
|
@ -1,178 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 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 promise = require('promise');
|
||||
|
||||
function nativeAddModule(name)
|
||||
{
|
||||
var value = getJSModule(name);
|
||||
var ret = "duk_peval_string_noresult(ctx, \"addModule('" + name + "', Buffer.from('" + Buffer.from(value).toString('base64') + "', 'base64').toString());\");";
|
||||
module.exports(ret);
|
||||
}
|
||||
|
||||
function lin_readtext()
|
||||
{
|
||||
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||
try
|
||||
{
|
||||
require('monitor-info')
|
||||
}
|
||||
catch(exc)
|
||||
{
|
||||
ret._rej(exc);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
var X11 = require('monitor-info')._X11;
|
||||
if (!X11)
|
||||
{
|
||||
ret._rej('X11 required for Clipboard Manipulation');
|
||||
}
|
||||
else
|
||||
{
|
||||
var SelectionNotify = 31;
|
||||
var AnyPropertyType = 0;
|
||||
var GM = require('monitor-info')._gm;
|
||||
|
||||
ret._getInfoPromise = require('monitor-info').getInfo();
|
||||
ret._getInfoPromise._masterPromise = ret;
|
||||
ret._getInfoPromise.then(function (mon)
|
||||
{
|
||||
if (mon.length > 0)
|
||||
{
|
||||
var white = X11.XWhitePixel(mon[0].display, mon[0].screenId).Val;
|
||||
|
||||
this._masterPromise.CLIPID = X11.XInternAtom(mon[0].display, GM.CreateVariable('CLIPBOARD'), 0);
|
||||
this._masterPromise.FMTID = X11.XInternAtom(mon[0].display, GM.CreateVariable('UTF8_STRING'), 0);
|
||||
this._masterPromise.PROPID = X11.XInternAtom(mon[0].display, GM.CreateVariable('XSEL_DATA'), 0);
|
||||
this._masterPromise.INCRID = X11.XInternAtom(mon[0].display, GM.CreateVariable('INCR'), 0);
|
||||
this._masterPromise.ROOTWIN = X11.XRootWindow(mon[0].display, mon[0].screenId);
|
||||
this._masterPromise.FAKEWIN = X11.XCreateSimpleWindow(mon[0].display, this._masterPromise.ROOTWIN, 0, 0, mon[0].right, 5, 0, white, white);
|
||||
|
||||
X11.XSync(mon[0].display, 0);
|
||||
X11.XConvertSelection(mon[0].display, this._masterPromise.CLIPID, this._masterPromise.FMTID, this._masterPromise.PROPID, this._masterPromise.FAKEWIN, 0);
|
||||
X11.XSync(mon[0].display, 0);
|
||||
|
||||
this._masterPromise.DescriptorEvent = require('DescriptorEvents').addDescriptor(X11.XConnectionNumber(mon[0].display).Val, { readset: true });
|
||||
this._masterPromise.DescriptorEvent._masterPromise = this._masterPromise;
|
||||
this._masterPromise.DescriptorEvent._display = mon[0].display;
|
||||
this._masterPromise.DescriptorEvent.on('readset', function (fd)
|
||||
{
|
||||
var XE = GM.CreateVariable(1024);
|
||||
while (X11.XPending(this._display).Val)
|
||||
{
|
||||
X11.XNextEventSync(this._display, XE);
|
||||
if(XE.Deref(0, 4).toBuffer().readUInt32LE() == SelectionNotify)
|
||||
{
|
||||
var id = GM.CreatePointer();
|
||||
var bits = GM.CreatePointer();
|
||||
var sz = GM.CreatePointer();
|
||||
var tail = GM.CreatePointer();
|
||||
var result = GM.CreatePointer();
|
||||
|
||||
X11.XGetWindowProperty(this._display, this._masterPromise.FAKEWIN, this._masterPromise.PROPID, 0, 65535, 0, AnyPropertyType, id, bits, sz, tail, result);
|
||||
this._masterPromise._res(result.Deref().String);
|
||||
X11.XFree(result.Deref());
|
||||
X11.XDestroyWindow(this._display, this._masterPromise.FAKEWIN);
|
||||
|
||||
this.removeDescriptor(fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
function lin_copytext()
|
||||
{
|
||||
}
|
||||
|
||||
function win_readtext()
|
||||
{
|
||||
var ret = '';
|
||||
var CF_TEXT = 1;
|
||||
var GM = require('_GenericMarshal');
|
||||
var user32 = GM.CreateNativeProxy('user32.dll');
|
||||
var kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||
kernel32.CreateMethod('GlobalAlloc');
|
||||
kernel32.CreateMethod('GlobalLock');
|
||||
kernel32.CreateMethod('GlobalUnlock');
|
||||
user32.CreateMethod('OpenClipboard');
|
||||
user32.CreateMethod('CloseClipboard');
|
||||
user32.CreateMethod('GetClipboardData');
|
||||
|
||||
user32.OpenClipboard(0);
|
||||
var h = user32.GetClipboardData(CF_TEXT);
|
||||
if(h.Val!=0)
|
||||
{
|
||||
var hbuffer = kernel32.GlobalLock(h);
|
||||
ret = hbuffer.String;
|
||||
kernel32.GlobalUnlock(h);
|
||||
}
|
||||
user32.CloseClipboard();
|
||||
|
||||
var p = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||
p._res(ret);
|
||||
return (p);
|
||||
}
|
||||
|
||||
function win_copytext(txt)
|
||||
{
|
||||
var GMEM_MOVEABLE = 0x0002;
|
||||
var CF_TEXT = 1;
|
||||
|
||||
var GM = require('_GenericMarshal');
|
||||
var user32 = GM.CreateNativeProxy('user32.dll');
|
||||
var kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||
kernel32.CreateMethod('GlobalAlloc');
|
||||
kernel32.CreateMethod('GlobalLock');
|
||||
kernel32.CreateMethod('GlobalUnlock');
|
||||
user32.CreateMethod('OpenClipboard');
|
||||
user32.CreateMethod('EmptyClipboard');
|
||||
user32.CreateMethod('CloseClipboard');
|
||||
user32.CreateMethod('SetClipboardData');
|
||||
|
||||
var h = kernel32.GlobalAlloc(GMEM_MOVEABLE, txt.length + 2);
|
||||
h.autoFree(false);
|
||||
var hbuffer = kernel32.GlobalLock(h);
|
||||
hbuffer.autoFree(false);
|
||||
var tmp = Buffer.alloc(txt.length + 1);
|
||||
Buffer.from(txt).copy(tmp);
|
||||
tmp.copy(hbuffer.Deref(0, txt.length + 1).toBuffer());
|
||||
kernel32.GlobalUnlock(h);
|
||||
|
||||
user32.OpenClipboard(0);
|
||||
user32.EmptyClipboard();
|
||||
user32.SetClipboardData(CF_TEXT, h);
|
||||
user32.CloseClipboard();
|
||||
}
|
||||
|
||||
switch(process.platform)
|
||||
{
|
||||
case 'win32':
|
||||
module.exports = win_copytext;
|
||||
module.exports.read = win_readtext;
|
||||
break;
|
||||
case 'linux':
|
||||
module.exports = lin_copytext;
|
||||
module.exports.read = lin_readtext;
|
||||
break;
|
||||
case 'darwin':
|
||||
break;
|
||||
}
|
||||
module.exports.nativeAddModule = nativeAddModule;
|
@ -1,313 +0,0 @@
|
||||
/*
|
||||
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 promise = require('promise');
|
||||
var PPosition = 4;
|
||||
var PSize = 8;
|
||||
var _NET_WM_STATE_REMOVE = 0; // remove/unset property
|
||||
var _NET_WM_STATE_ADD = 1; // add/set property
|
||||
var _NET_WM_STATE_TOGGLE = 2; // toggle property
|
||||
var SubstructureRedirectMask = (1 << 20);
|
||||
var SubstructureNotifyMask = (1 << 19);
|
||||
|
||||
function getLibInfo(libname)
|
||||
{
|
||||
if (process.platform != 'linux') { throw ('Only supported on linux'); }
|
||||
|
||||
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.stdin.write("ldconfig -p | grep '" + libname + ".so.'\nexit\n");
|
||||
child.waitExit();
|
||||
|
||||
var v = [];
|
||||
var lines = child.stdout.str.split('\n');
|
||||
for (var i in lines) {
|
||||
if (lines[i]) {
|
||||
var info = lines[i].split('=>');
|
||||
var pth = info[1].trim();
|
||||
var libinfo = info[0].trim().split(' ');
|
||||
var lib = libinfo[0];
|
||||
var plat = libinfo[1].substring(1, libinfo[1].length - 1).split(',');
|
||||
|
||||
if (lib.startsWith(libname + '.so.')) {
|
||||
v.push({ lib: lib, path: pth, info: plat });
|
||||
}
|
||||
}
|
||||
}
|
||||
return (v);
|
||||
}
|
||||
|
||||
function monitorinfo()
|
||||
{
|
||||
this._ObjectID = 'monitor-info';
|
||||
this._gm = require('_GenericMarshal');
|
||||
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this._user32 = this._gm.CreateNativeProxy('user32.dll');
|
||||
this._user32.CreateMethod('EnumDisplayMonitors');
|
||||
this._kernel32 = this._gm.CreateNativeProxy('kernel32.dll');
|
||||
this._kernel32.CreateMethod('GetLastError');
|
||||
|
||||
this.getInfo = function getInfo()
|
||||
{
|
||||
var info = this;
|
||||
return (new promise(function (resolver, rejector) {
|
||||
this._monitorinfo = { resolver: resolver, rejector: rejector, self: info, callback: info._gm.GetGenericGlobalCallback(4) };
|
||||
this._monitorinfo.callback.info = this._monitorinfo;
|
||||
this._monitorinfo.dwData = info._gm.ObjectToPtr(this._monitorinfo);
|
||||
|
||||
this._monitorinfo.callback.results = [];
|
||||
this._monitorinfo.callback.on('GlobalCallback', function OnMonitorInfo(hmon, hdc, r, user) {
|
||||
if (this.ObjectToPtr_Verify(this.info, user)) {
|
||||
var rb = r.Deref(0, 16).toBuffer();
|
||||
this.results.push({ left: rb.readInt32LE(0), top: rb.readInt32LE(4), right: rb.readInt32LE(8), bottom: rb.readInt32LE(12) });
|
||||
|
||||
var r = this.info.self._gm.CreateInteger();
|
||||
r.Val = 1;
|
||||
return (r);
|
||||
}
|
||||
});
|
||||
|
||||
if (info._user32.EnumDisplayMonitors(0, 0, this._monitorinfo.callback, this._monitorinfo.dwData).Val == 0) {
|
||||
rejector('LastError=' + info._kernel32.GetLastError().Val);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
resolver(this._monitorinfo.callback.results);
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
}
|
||||
else if(process.platform == 'linux')
|
||||
{
|
||||
// First thing we need to do, is determine where the X11 libraries are
|
||||
var askOS = false;
|
||||
try
|
||||
{
|
||||
if (require('user-sessions').isRoot()) { askOS = true; }
|
||||
}
|
||||
catch (e)
|
||||
{ }
|
||||
|
||||
if (askOS)
|
||||
{
|
||||
// Sufficient access rights to use ldconfig
|
||||
var x11info = getLibInfo('libX11');
|
||||
var xtstinfo = getLibInfo('libXtst');
|
||||
var xextinfo = getLibInfo('libXext');
|
||||
var ix;
|
||||
|
||||
for(ix in x11info)
|
||||
{
|
||||
try
|
||||
{
|
||||
this._gm.CreateNativeProxy(x11info[ix].path);
|
||||
Object.defineProperty(this, 'Location_X11LIB', { value: x11info[ix].path });
|
||||
break;
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
for (ix in xtstinfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
this._gm.CreateNativeProxy(xtstinfo[ix].path);
|
||||
Object.defineProperty(this, 'Location_X11TST', { value: xtstinfo[ix].path });
|
||||
break;
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
for (ix in xextinfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
this._gm.CreateNativeProxy(xextinfo[ix].path);
|
||||
Object.defineProperty(this, 'Location_X11EXT', { value: xextinfo[ix].path });
|
||||
break;
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not enough access rights to use ldconfig, so manually search
|
||||
var fs = require('fs');
|
||||
var files = fs.readdirSync('/usr/lib');
|
||||
var files2;
|
||||
|
||||
for (var i in files) {
|
||||
try {
|
||||
if (files[i].split('libX11.so.').length > 1 && files[i].split('.').length == 3) {
|
||||
Object.defineProperty(this, 'Location_X11LIB', { value: '/usr/lib/' + files[i] });
|
||||
}
|
||||
if (files[i].split('libXtst.so.').length > 1 && files[i].split('.').length == 3) {
|
||||
Object.defineProperty(this, 'Location_X11TST', { value: '/usr/lib/' + files[i] });
|
||||
}
|
||||
if (files[i].split('libXext.so.').length > 1 && files[i].split('.').length == 3) {
|
||||
Object.defineProperty(this, 'Location_X11EXT', { value: '/usr/lib/' + files[i] });
|
||||
}
|
||||
|
||||
if (files[i].split('-linux-').length > 1) {
|
||||
files2 = fs.readdirSync('/usr/lib/' + files[i]);
|
||||
for (j in files2) {
|
||||
if (files2[j].split('libX11.so.').length > 1 && files2[j].split('.').length == 3) {
|
||||
Object.defineProperty(this, 'Location_X11LIB', { value: '/usr/lib/' + files[i] + '/' + files2[j] });
|
||||
}
|
||||
if (files2[j].split('libXtst.so.').length > 1 && files2[j].split('.').length == 3) {
|
||||
Object.defineProperty(this, 'Location_X11TST', { value: '/usr/lib/' + files[i] + '/' + files2[j] });
|
||||
}
|
||||
if (files2[j].split('libXext.so.').length > 1 && files2[j].split('.').length == 3) {
|
||||
Object.defineProperty(this, 'Location_X11EXT', { value: '/usr/lib/' + files[i] + '/' + files2[j] });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ex) { }
|
||||
}
|
||||
}
|
||||
Object.defineProperty(this, 'kvm_x11_support', { value: (this.Location_X11LIB && this.Location_X11TST && this.Location_X11EXT)?true:false });
|
||||
|
||||
if (this.Location_X11LIB)
|
||||
{
|
||||
this._X11 = this._gm.CreateNativeProxy(this.Location_X11LIB);
|
||||
this._X11.CreateMethod('XChangeProperty');
|
||||
this._X11.CreateMethod('XCloseDisplay');
|
||||
this._X11.CreateMethod('XConnectionNumber');
|
||||
this._X11.CreateMethod('XConvertSelection');
|
||||
this._X11.CreateMethod('XCreateGC');
|
||||
this._X11.CreateMethod('XCreateWindow');
|
||||
this._X11.CreateMethod('XCreateSimpleWindow');
|
||||
this._X11.CreateMethod('XDefaultColormap');
|
||||
this._X11.CreateMethod('XDefaultScreen');
|
||||
this._X11.CreateMethod('XDestroyWindow');
|
||||
this._X11.CreateMethod('XDrawLine');
|
||||
this._X11.CreateMethod('XDisplayHeight');
|
||||
this._X11.CreateMethod('XDisplayWidth');
|
||||
this._X11.CreateMethod('XFetchName');
|
||||
this._X11.CreateMethod('XFlush');
|
||||
this._X11.CreateMethod('XFree');
|
||||
this._X11.CreateMethod('XCreateGC');
|
||||
this._X11.CreateMethod('XGetWindowProperty');
|
||||
this._X11.CreateMethod('XInternAtom');
|
||||
this._X11.CreateMethod('XMapWindow');
|
||||
this._X11.CreateMethod({ method: 'XNextEvent', threadDispatch: true });
|
||||
this._X11.CreateMethod({ method: 'XNextEvent', newName: 'XNextEventSync' });
|
||||
this._X11.CreateMethod('XOpenDisplay');
|
||||
this._X11.CreateMethod('XPending');
|
||||
this._X11.CreateMethod('XRootWindow');
|
||||
this._X11.CreateMethod('XSelectInput');
|
||||
this._X11.CreateMethod('XScreenCount');
|
||||
this._X11.CreateMethod('XScreenOfDisplay');
|
||||
this._X11.CreateMethod('XSelectInput');
|
||||
this._X11.CreateMethod('XSendEvent');
|
||||
this._X11.CreateMethod('XSetForeground');
|
||||
this._X11.CreateMethod('XSetFunction');
|
||||
this._X11.CreateMethod('XSetLineAttributes');
|
||||
this._X11.CreateMethod('XSetNormalHints');
|
||||
this._X11.CreateMethod('XSetSubwindowMode');
|
||||
this._X11.CreateMethod('XSync');
|
||||
this._X11.CreateMethod('XBlackPixel');
|
||||
this._X11.CreateMethod('XWhitePixel');
|
||||
}
|
||||
|
||||
this.isUnity = function isUnity()
|
||||
{
|
||||
return (process.env['XDG_CURRENT_DESKTOP'] == 'Unity');
|
||||
}
|
||||
|
||||
this.unDecorateWindow = function unDecorateWindow(display, window)
|
||||
{
|
||||
var MwmHints = this._gm.CreateVariable(40);
|
||||
var mwmHintsProperty = this._X11.XInternAtom(display, this._gm.CreateVariable('_MOTIF_WM_HINTS'), 0);
|
||||
MwmHints.Deref(0, 4).toBuffer().writeUInt32LE(1 << 1);
|
||||
this._X11.XChangeProperty(display, window, mwmHintsProperty, mwmHintsProperty, 32, 0, MwmHints, 5);
|
||||
}
|
||||
this.setWindowSizeHints = function setWindowSizeHints(display, window, x, y, width, height)
|
||||
{
|
||||
var sizeHints = this._gm.CreateVariable(80);
|
||||
sizeHints.Deref(0, 4).toBuffer().writeUInt32LE(PPosition | PSize);
|
||||
sizeHints.Deref(8, 4).toBuffer().writeUInt32LE(x);
|
||||
sizeHints.Deref(12, 4).toBuffer().writeUInt32LE(y);
|
||||
sizeHints.Deref(16, 4).toBuffer().writeUInt32LE(width);
|
||||
sizeHints.Deref(20, 4).toBuffer().writeUInt32LE(height);
|
||||
this._X11.XSetNormalHints(display, window, sizeHints);
|
||||
}
|
||||
this.setAlwaysOnTop = function setAlwaysOnTop(display, rootWindow, window)
|
||||
{
|
||||
var wmNetWmState = this._X11.XInternAtom(display, this._gm.CreateVariable('_NET_WM_STATE'), 1);
|
||||
var wmStateAbove = this._X11.XInternAtom(display, this._gm.CreateVariable('_NET_WM_STATE_ABOVE'), 1);
|
||||
|
||||
var xclient = this._gm.CreateVariable(96);
|
||||
xclient.Deref(0, 4).toBuffer().writeUInt32LE(33); // ClientMessage type
|
||||
xclient.Deref(48, 4).toBuffer().writeUInt32LE(32); // Format 32
|
||||
wmNetWmState.pointerBuffer().copy(xclient.Deref(40, 8).toBuffer()); // message_type
|
||||
xclient.Deref(56, 8).toBuffer().writeUInt32LE(_NET_WM_STATE_ADD); // data.l[0]
|
||||
wmStateAbove.pointerBuffer().copy(xclient.Deref(64, 8).toBuffer()); // data.l[1]
|
||||
|
||||
window.pointerBuffer().copy(xclient.Deref(32, 8).toBuffer()); // window
|
||||
this._X11.XSendEvent(display, rootWindow, 0, SubstructureRedirectMask | SubstructureNotifyMask, xclient);
|
||||
}
|
||||
this.hideWindowIcon = function hideWindowIcon(display, rootWindow, window)
|
||||
{
|
||||
var wmNetWmState = this._X11.XInternAtom(display, this._gm.CreateVariable('_NET_WM_STATE'), 1);
|
||||
var wmStateSkip = this._X11.XInternAtom(display, this._gm.CreateVariable('_NET_WM_STATE_SKIP_TASKBAR'), 1);
|
||||
|
||||
var xclient = this._gm.CreateVariable(96);
|
||||
xclient.Deref(0, 4).toBuffer().writeUInt32LE(33); // ClientMessage type
|
||||
xclient.Deref(48, 4).toBuffer().writeUInt32LE(32); // Format 32
|
||||
wmNetWmState.pointerBuffer().copy(xclient.Deref(40, 8).toBuffer()); // message_type
|
||||
xclient.Deref(56, 8).toBuffer().writeUInt32LE(_NET_WM_STATE_ADD); // data.l[0]
|
||||
wmStateSkip.pointerBuffer().copy(xclient.Deref(64, 8).toBuffer()); // data.l[1]
|
||||
|
||||
window.pointerBuffer().copy(xclient.Deref(32, 8).toBuffer()); // window
|
||||
this._X11.XSendEvent(display, rootWindow, 0, SubstructureRedirectMask | SubstructureNotifyMask, xclient);
|
||||
}
|
||||
|
||||
this.getInfo = function getInfo()
|
||||
{
|
||||
var info = this;
|
||||
return (new promise(function (resolver, rejector)
|
||||
{
|
||||
var display = info._X11.XOpenDisplay(info._gm.CreateVariable(':0'));
|
||||
var screenCount = info._X11.XScreenCount(display).Val;
|
||||
var ret = [];
|
||||
for(var i=0;i<screenCount;++i)
|
||||
{
|
||||
var screen = info._X11.XScreenOfDisplay(display, i);
|
||||
ret.push({ left: 0, top: 0, right: info._X11.XDisplayWidth(display, i).Val, bottom: info._X11.XDisplayHeight(display, i).Val, screen: screen, screenId: i, display: display });
|
||||
}
|
||||
resolver(ret);
|
||||
}));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw (process.platform + ' not supported');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new monitorinfo();
|
||||
|
||||
|
||||
|
@ -1,163 +0,0 @@
|
||||
/*
|
||||
Copyright 2018-2019 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 GM = require('_GenericMarshal');
|
||||
|
||||
// Used on Windows and Linux to get information about running processes
|
||||
function processManager() {
|
||||
this._ObjectID = 'process-manager'; // Used for debugging, allows you to get the object type at runtime.
|
||||
|
||||
// Setup the platform specific calls.
|
||||
switch (process.platform)
|
||||
{
|
||||
case 'win32':
|
||||
this._kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||
this._kernel32.CreateMethod('GetLastError');
|
||||
this._kernel32.CreateMethod('CreateToolhelp32Snapshot');
|
||||
this._kernel32.CreateMethod('Process32First');
|
||||
this._kernel32.CreateMethod('Process32Next');
|
||||
break;
|
||||
case 'linux':
|
||||
case 'darwin':
|
||||
this._childProcess = require('child_process');
|
||||
break;
|
||||
default:
|
||||
throw (process.platform + ' not supported');
|
||||
break;
|
||||
}
|
||||
this.enumerateProcesses = function enumerateProcesses()
|
||||
{
|
||||
var promise = require('promise');
|
||||
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||
this.getProcesses(function (ps, prom) { prom._res(ps); }, ret);
|
||||
return (ret);
|
||||
}
|
||||
// Return a object of: pid -> process information.
|
||||
this.getProcesses = function getProcesses(callback)
|
||||
{
|
||||
switch(process.platform)
|
||||
{
|
||||
default:
|
||||
throw ('Enumerating processes on ' + process.platform + ' not supported');
|
||||
break;
|
||||
case 'win32': // Windows processes
|
||||
var retVal = {};
|
||||
var h = this._kernel32.CreateToolhelp32Snapshot(2, 0);
|
||||
var info = GM.CreateVariable(304);
|
||||
info.toBuffer().writeUInt32LE(304, 0);
|
||||
var nextProcess = this._kernel32.Process32First(h, info);
|
||||
while (nextProcess.Val)
|
||||
{
|
||||
retVal[info.Deref(8, 4).toBuffer().readUInt32LE(0)] = { pid: info.Deref(8, 4).toBuffer().readUInt32LE(0), cmd: info.Deref(GM.PointerSize == 4 ? 36 : 44, 260).String };
|
||||
nextProcess = this._kernel32.Process32Next(h, info);
|
||||
}
|
||||
if (callback) { callback.apply(this, [retVal]); }
|
||||
break;
|
||||
case 'linux': // Linux processes
|
||||
if (!this._psp) { this._psp = {}; }
|
||||
var p = this._childProcess.execFile("/bin/ps", ["ps", "-uxa"], { type: this._childProcess.SpawnTypes.TERM });
|
||||
this._psp[p.pid] = p;
|
||||
p.Parent = this;
|
||||
p.ps = '';
|
||||
p.callback = callback;
|
||||
p.args = [];
|
||||
for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); }
|
||||
p.on('exit', function onGetProcesses()
|
||||
{
|
||||
delete this.Parent._psp[this.pid];
|
||||
var retVal = {}, lines = this.ps.split('\x0D\x0A'), key = {}, keyi = 0;
|
||||
for (var i in lines)
|
||||
{
|
||||
var tokens = lines[i].split(' ');
|
||||
var tokenList = [];
|
||||
for(var x in tokens)
|
||||
{
|
||||
if (i == 0 && tokens[x]) { key[tokens[x]] = keyi++; }
|
||||
if (i > 0 && tokens[x]) { tokenList.push(tokens[x]);}
|
||||
}
|
||||
if (i > 0) {
|
||||
if (tokenList[key.PID]) { retVal[tokenList[key.PID]] = { pid: key.PID, user: tokenList[key.USER], cmd: tokenList[key.COMMAND] }; }
|
||||
}
|
||||
}
|
||||
if (this.callback)
|
||||
{
|
||||
this.args.unshift(retVal);
|
||||
this.callback.apply(this.parent, this.args);
|
||||
}
|
||||
});
|
||||
p.stdout.on('data', function (chunk) { this.parent.ps += chunk.toString(); });
|
||||
break;
|
||||
case 'darwin':
|
||||
var promise = require('promise');
|
||||
var p = new promise(function (res, rej) { this._res = res; this._rej = rej; });
|
||||
p.pm = this;
|
||||
p.callback = callback;
|
||||
p.args = [];
|
||||
for (var i = 1; i < arguments.length; ++i) { p.args.push(arguments[i]); }
|
||||
p.child = this._childProcess.execFile("/bin/ps", ["ps", "-xa"]);
|
||||
p.child.promise = p;
|
||||
p.child.stdout.ps = '';
|
||||
p.child.stdout.on('data', function (chunk) { this.ps += chunk.toString(); });
|
||||
p.child.on('exit', function ()
|
||||
{
|
||||
var lines = this.stdout.ps.split('\n');
|
||||
var pidX = lines[0].split('PID')[0].length + 3;
|
||||
var cmdX = lines[0].split('CMD')[0].length;
|
||||
var ret = {};
|
||||
for (var i = 1; i < lines.length; ++i)
|
||||
{
|
||||
if (lines[i].length > 0)
|
||||
{
|
||||
ret[lines[i].substring(0, pidX).trim()] = { pid: lines[i].substring(0, pidX).trim(), cmd: lines[i].substring(cmdX) };
|
||||
}
|
||||
}
|
||||
this.promise._res(ret);
|
||||
});
|
||||
p.then(function (ps)
|
||||
{
|
||||
this.args.unshift(ps);
|
||||
this.callback.apply(this.pm, this.args);
|
||||
});
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Get information about a specific process on Linux
|
||||
this.getProcessInfo = function getProcessInfo(pid)
|
||||
{
|
||||
switch(process.platform)
|
||||
{
|
||||
default:
|
||||
throw ('getProcessInfo() not supported for ' + process.platform);
|
||||
break;
|
||||
case 'linux':
|
||||
var status = require('fs').readFileSync('/proc/' + pid + '/status');
|
||||
var info = {};
|
||||
var lines = status.toString().split('\n');
|
||||
for(var i in lines)
|
||||
{
|
||||
var tokens = lines[i].split(':');
|
||||
if (tokens.length > 1) { tokens[1] = tokens[1].trim(); }
|
||||
info[tokens[0]] = tokens[1];
|
||||
}
|
||||
return (info);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = new processManager();
|
@ -1,497 +0,0 @@
|
||||
/*
|
||||
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 parseServiceStatus(token)
|
||||
{
|
||||
var j = {};
|
||||
var serviceType = token.Deref(0, 4).IntVal;
|
||||
j.isFileSystemDriver = ((serviceType & 0x00000002) == 0x00000002);
|
||||
j.isKernelDriver = ((serviceType & 0x00000001) == 0x00000001);
|
||||
j.isSharedProcess = ((serviceType & 0x00000020) == 0x00000020);
|
||||
j.isOwnProcess = ((serviceType & 0x00000010) == 0x00000010);
|
||||
j.isInteractive = ((serviceType & 0x00000100) == 0x00000100);
|
||||
switch (token.Deref((1 * 4), 4).toBuffer().readUInt32LE())
|
||||
{
|
||||
case 0x00000005:
|
||||
j.state = 'CONTINUE_PENDING';
|
||||
break;
|
||||
case 0x00000006:
|
||||
j.state = 'PAUSE_PENDING';
|
||||
break;
|
||||
case 0x00000007:
|
||||
j.state = 'PAUSED';
|
||||
break;
|
||||
case 0x00000004:
|
||||
j.state = 'RUNNING';
|
||||
break;
|
||||
case 0x00000002:
|
||||
j.state = 'START_PENDING';
|
||||
break;
|
||||
case 0x00000003:
|
||||
j.state = 'STOP_PENDING';
|
||||
break;
|
||||
case 0x00000001:
|
||||
j.state = 'STOPPED';
|
||||
break;
|
||||
}
|
||||
var controlsAccepted = token.Deref((2 * 4), 4).toBuffer().readUInt32LE();
|
||||
j.controlsAccepted = [];
|
||||
if ((controlsAccepted & 0x00000010) == 0x00000010)
|
||||
{
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDADD');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDREMOVE');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDENABLE');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDDISABLE');
|
||||
}
|
||||
if ((controlsAccepted & 0x00000008) == 0x00000008) { j.controlsAccepted.push('SERVICE_CONTROL_PARAMCHANGE'); }
|
||||
if ((controlsAccepted & 0x00000002) == 0x00000002) { j.controlsAccepted.push('SERVICE_CONTROL_PAUSE'); j.controlsAccepted.push('SERVICE_CONTROL_CONTINUE'); }
|
||||
if ((controlsAccepted & 0x00000100) == 0x00000100) { j.controlsAccepted.push('SERVICE_CONTROL_PRESHUTDOWN'); }
|
||||
if ((controlsAccepted & 0x00000004) == 0x00000004) { j.controlsAccepted.push('SERVICE_CONTROL_SHUTDOWN'); }
|
||||
if ((controlsAccepted & 0x00000001) == 0x00000001) { j.controlsAccepted.push('SERVICE_CONTROL_STOP'); }
|
||||
if ((controlsAccepted & 0x00000020) == 0x00000020) { j.controlsAccepted.push('SERVICE_CONTROL_HARDWAREPROFILECHANGE'); }
|
||||
if ((controlsAccepted & 0x00000040) == 0x00000040) { j.controlsAccepted.push('SERVICE_CONTROL_POWEREVENT'); }
|
||||
if ((controlsAccepted & 0x00000080) == 0x00000080) { j.controlsAccepted.push('SERVICE_CONTROL_SESSIONCHANGE'); }
|
||||
j.pid = token.Deref((7 * 4), 4).toBuffer().readUInt32LE();
|
||||
return (j);
|
||||
}
|
||||
|
||||
function serviceManager()
|
||||
{
|
||||
this._ObjectID = 'service-manager';
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this.GM = require('_GenericMarshal');
|
||||
this.proxy = this.GM.CreateNativeProxy('Advapi32.dll');
|
||||
this.proxy.CreateMethod('OpenSCManagerA');
|
||||
this.proxy.CreateMethod('EnumServicesStatusExA');
|
||||
this.proxy.CreateMethod('OpenServiceA');
|
||||
this.proxy.CreateMethod('QueryServiceStatusEx');
|
||||
this.proxy.CreateMethod('ControlService');
|
||||
this.proxy.CreateMethod('StartServiceA');
|
||||
this.proxy.CreateMethod('CloseServiceHandle');
|
||||
this.proxy.CreateMethod('CreateServiceA');
|
||||
this.proxy.CreateMethod('ChangeServiceConfig2A');
|
||||
this.proxy.CreateMethod('DeleteService');
|
||||
this.proxy.CreateMethod('AllocateAndInitializeSid');
|
||||
this.proxy.CreateMethod('CheckTokenMembership');
|
||||
this.proxy.CreateMethod('FreeSid');
|
||||
|
||||
this.proxy2 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||
this.proxy2.CreateMethod('GetLastError');
|
||||
|
||||
this.isAdmin = function isAdmin() {
|
||||
var NTAuthority = this.GM.CreateVariable(6);
|
||||
NTAuthority.toBuffer().writeInt8(5, 5);
|
||||
var AdministratorsGroup = this.GM.CreatePointer();
|
||||
var admin = false;
|
||||
|
||||
if (this.proxy.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
|
||||
{
|
||||
var member = this.GM.CreateInteger();
|
||||
if (this.proxy.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
|
||||
{
|
||||
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
||||
}
|
||||
this.proxy.FreeSid(AdministratorsGroup.Deref());
|
||||
}
|
||||
return admin;
|
||||
};
|
||||
this.getProgramFolder = function getProgramFolder()
|
||||
{
|
||||
if (require('os').arch() == 'x64')
|
||||
{
|
||||
// 64 bit Windows
|
||||
if (this.GM.PointerSize == 4)
|
||||
{
|
||||
return process.env['ProgramFiles(x86)']; // 32 Bit App
|
||||
}
|
||||
return process.env['ProgramFiles']; // 64 bit App
|
||||
}
|
||||
|
||||
// 32 bit Windows
|
||||
return process.env['ProgramFiles'];
|
||||
};
|
||||
this.getServiceFolder = function getServiceFolder() { return this.getProgramFolder() + '\\mesh'; };
|
||||
|
||||
this.enumerateService = function () {
|
||||
var machineName = this.GM.CreatePointer();
|
||||
var dbName = this.GM.CreatePointer();
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004);
|
||||
|
||||
var bytesNeeded = this.GM.CreatePointer();
|
||||
var servicesReturned = this.GM.CreatePointer();
|
||||
var resumeHandle = this.GM.CreatePointer();
|
||||
//var services = this.proxy.CreateVariable(262144);
|
||||
var success = this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, 0x00, 0x00, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||
if (bytesNeeded.IntVal <= 0) {
|
||||
throw ('error enumerating services');
|
||||
}
|
||||
var sz = bytesNeeded.IntVal;
|
||||
var services = this.GM.CreateVariable(sz);
|
||||
this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, services, sz, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||
console.log("servicesReturned", servicesReturned.IntVal);
|
||||
|
||||
var ptrSize = dbName._size;
|
||||
var blockSize = 36 + (2 * ptrSize);
|
||||
blockSize += ((ptrSize - (blockSize % ptrSize)) % ptrSize);
|
||||
var retVal = [];
|
||||
for (var i = 0; i < servicesReturned.IntVal; ++i) {
|
||||
var token = services.Deref(i * blockSize, blockSize);
|
||||
var j = {};
|
||||
j.name = token.Deref(0, ptrSize).Deref().String;
|
||||
j.displayName = token.Deref(ptrSize, ptrSize).Deref().String;
|
||||
j.status = parseServiceStatus(token.Deref(2 * ptrSize, 36));
|
||||
retVal.push(j);
|
||||
}
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
return (retVal);
|
||||
}
|
||||
this.getService = function (name) {
|
||||
var serviceName = this.GM.CreateVariable(name);
|
||||
var ptr = this.GM.CreatePointer();
|
||||
var bytesNeeded = this.GM.CreateVariable(ptr._size);
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004 | 0x0020 | 0x0010);
|
||||
if (handle.Val == 0) { throw ('could not open ServiceManager'); }
|
||||
var h = this.proxy.OpenServiceA(handle, serviceName, 0x0004 | 0x0020 | 0x0010 | 0x00010000);
|
||||
if (h.Val != 0) {
|
||||
var success = this.proxy.QueryServiceStatusEx(h, 0, 0, 0, bytesNeeded);
|
||||
var status = this.GM.CreateVariable(bytesNeeded.toBuffer().readUInt32LE());
|
||||
success = this.proxy.QueryServiceStatusEx(h, 0, status, status._size, bytesNeeded);
|
||||
if (success != 0) {
|
||||
retVal = {};
|
||||
retVal.status = parseServiceStatus(status);
|
||||
retVal._scm = handle;
|
||||
retVal._service = h;
|
||||
retVal._GM = this.GM;
|
||||
retVal._proxy = this.proxy;
|
||||
require('events').inherits(retVal);
|
||||
retVal.on('~', function () { this._proxy.CloseServiceHandle(this); this._proxy.CloseServiceHandle(this._scm); });
|
||||
retVal.name = name;
|
||||
retVal.stop = function () {
|
||||
if (this.status.state == 'RUNNING') {
|
||||
var newstate = this._GM.CreateVariable(36);
|
||||
var success = this._proxy.ControlService(this._service, 0x00000001, newstate);
|
||||
if (success == 0) {
|
||||
throw (this.name + '.stop() failed');
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw ('cannot call ' + this.name + '.stop(), when current state is: ' + this.status.state);
|
||||
}
|
||||
}
|
||||
retVal.start = function () {
|
||||
if (this.status.state == 'STOPPED') {
|
||||
var success = this._proxy.StartServiceA(this._service, 0, 0);
|
||||
if (success == 0) {
|
||||
throw (this.name + '.start() failed');
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw ('cannot call ' + this.name + '.start(), when current state is: ' + this.status.state);
|
||||
}
|
||||
}
|
||||
return (retVal);
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
throw ('could not find service: ' + name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.isAdmin = function isAdmin()
|
||||
{
|
||||
return (require('user-sessions').isRoot());
|
||||
}
|
||||
}
|
||||
this.installService = function installService(options)
|
||||
{
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Installing as Service, requires admin'); }
|
||||
|
||||
// Before we start, we need to copy the binary to the right place
|
||||
var folder = this.getServiceFolder();
|
||||
if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); }
|
||||
require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '.exe');
|
||||
options.servicePath = folder + '\\' + options.name + '.exe';
|
||||
|
||||
var servicePath = this.GM.CreateVariable('"' + options.servicePath + '"');
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
|
||||
if (handle.Val == 0) { throw ('error opening SCManager'); }
|
||||
var serviceName = this.GM.CreateVariable(options.name);
|
||||
var displayName = this.GM.CreateVariable(options.name);
|
||||
var allAccess = 0x000F01FF;
|
||||
var serviceType;
|
||||
|
||||
|
||||
switch (options.startType) {
|
||||
case 'BOOT_START':
|
||||
serviceType = 0x00;
|
||||
break;
|
||||
case 'SYSTEM_START':
|
||||
serviceType = 0x01;
|
||||
break;
|
||||
case 'AUTO_START':
|
||||
serviceType = 0x02;
|
||||
break;
|
||||
case 'DEMAND_START':
|
||||
serviceType = 0x03;
|
||||
break;
|
||||
default:
|
||||
serviceType = 0x04; // Disabled
|
||||
break;
|
||||
}
|
||||
|
||||
var h = this.proxy.CreateServiceA(handle, serviceName, displayName, allAccess, 0x10 | 0x100, serviceType, 0, servicePath, 0, 0, 0, 0, 0);
|
||||
if (h.Val == 0) { this.proxy.CloseServiceHandle(handle); throw ('Error Creating Service: ' + this.proxy2.GetLastError().Val); }
|
||||
if (options.description) {
|
||||
console.log(options.description);
|
||||
|
||||
var dscPtr = this.GM.CreatePointer();
|
||||
dscPtr.Val = this.GM.CreateVariable(options.description);
|
||||
|
||||
if (this.proxy.ChangeServiceConfig2A(h, 1, dscPtr) == 0) {
|
||||
this.proxy.CloseServiceHandle(h);
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
throw ('Unable to set description');
|
||||
}
|
||||
}
|
||||
this.proxy.CloseServiceHandle(h);
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
return (this.getService(options.name));
|
||||
}
|
||||
if(process.platform == 'linux')
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||
|
||||
switch (this.getServiceType())
|
||||
{
|
||||
case 'init':
|
||||
require('fs').copyFileSync(options.servicePath, '/etc/init.d/' + options.name);
|
||||
console.log('copying ' + options.servicePath);
|
||||
var m = require('fs').statSync('/etc/init.d/' + options.name).mode;
|
||||
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||
require('fs').chmodSync('/etc/init.d/' + options.name, m);
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update._moduleName = options.name;
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('update-rc.d ' + options.name + ' defaults\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
//update-rc.d meshagent defaults # creates symlinks for rc.d
|
||||
//service meshagent start
|
||||
|
||||
this._update.waitExit();
|
||||
|
||||
break;
|
||||
case 'systemd':
|
||||
var serviceDescription = options.description ? options.description : 'MeshCentral Agent';
|
||||
if (!require('fs').existsSync('/usr/local/mesh')) { require('fs').mkdirSync('/usr/local/mesh'); }
|
||||
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh/' + options.name);
|
||||
var m = require('fs').statSync('/usr/local/mesh/' + options.name).mode;
|
||||
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||
require('fs').chmodSync('/usr/local/mesh/' + options.name, m);
|
||||
require('fs').writeFileSync('/lib/systemd/system/' + options.name + '.service', '[Unit]\nDescription=' + serviceDescription + '\n[Service]\nExecStart=/usr/local/mesh/' + options.name + '\nStandardOutput=null\nRestart=always\nRestartSec=3\n[Install]\nWantedBy=multi-user.target\nAlias=' + options.name + '.service\n', { flags: 'w' });
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update._moduleName = options.name;
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('systemctl enable ' + options.name + '.service\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
this._update.waitExit();
|
||||
break;
|
||||
default: // unknown platform service type
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(process.platform == 'darwin')
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||
|
||||
// Mac OS
|
||||
var stdoutpath = (options.stdout ? ('<key>StandardOutPath</key>\n<string>' + options.stdout + '</string>') : '');
|
||||
var autoStart = (options.startType == 'AUTO_START' ? '<true/>' : '<false/>');
|
||||
var params = ' <key>ProgramArguments</key>\n';
|
||||
params += ' <array>\n';
|
||||
params += (' <string>/usr/local/mesh_services/' + options.name + '/' + options.name + '</string>\n');
|
||||
if(options.parameters)
|
||||
{
|
||||
for(var itm in options.parameters)
|
||||
{
|
||||
params += (' <string>' + options.parameters[itm] + '</string>\n');
|
||||
}
|
||||
}
|
||||
params += ' </array>\n';
|
||||
|
||||
var plist = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
||||
plist += '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n';
|
||||
plist += '<plist version="1.0">\n';
|
||||
plist += ' <dict>\n';
|
||||
plist += ' <key>Label</key>\n';
|
||||
plist += (' <string>' + options.name + '</string>\n');
|
||||
plist += (params + '\n');
|
||||
plist += ' <key>WorkingDirectory</key>\n';
|
||||
plist += (' <string>/usr/local/mesh_services/' + options.name + '</string>\n');
|
||||
plist += (stdoutpath + '\n');
|
||||
plist += ' <key>RunAtLoad</key>\n';
|
||||
plist += (autoStart + '\n');
|
||||
plist += ' </dict>\n';
|
||||
plist += '</plist>';
|
||||
|
||||
if (!require('fs').existsSync('/usr/local/mesh_services')) { require('fs').mkdirSync('/usr/local/mesh_services'); }
|
||||
if (!require('fs').existsSync('/Library/LaunchDaemons/' + options.name + '.plist'))
|
||||
{
|
||||
if (!require('fs').existsSync('/usr/local/mesh_services/' + options.name)) { require('fs').mkdirSync('/usr/local/mesh_services/' + options.name); }
|
||||
if (options.binary)
|
||||
{
|
||||
require('fs').writeFileSync('/usr/local/mesh_services/' + options.name + '/' + options.name, options.binary);
|
||||
}
|
||||
else
|
||||
{
|
||||
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh_services/' + options.name + '/' + options.name);
|
||||
}
|
||||
require('fs').writeFileSync('/Library/LaunchDaemons/' + options.name + '.plist', plist);
|
||||
var m = require('fs').statSync('/usr/local/mesh_services/' + options.name + '/' + options.name).mode;
|
||||
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||
require('fs').chmodSync('/usr/local/mesh_services/' + options.name + '/' + options.name, m);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ('Service: ' + options.name + ' already exists');
|
||||
}
|
||||
}
|
||||
}
|
||||
this.uninstallService = function uninstallService(name)
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Uninstalling a service, requires admin'); }
|
||||
|
||||
if (typeof (name) == 'object') { name = name.name; }
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
var service = this.getService(name);
|
||||
if (service.status.state == undefined || service.status.state == 'STOPPED')
|
||||
{
|
||||
if (this.proxy.DeleteService(service._service) == 0)
|
||||
{
|
||||
throw ('Uninstall Service for: ' + name + ', failed with error: ' + this.proxy2.GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync(this.getServiceFolder() + '\\' + name + '.exe');
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ('Cannot uninstall service: ' + name + ', because it is: ' + service.status.state);
|
||||
}
|
||||
}
|
||||
else if(process.platform == 'linux')
|
||||
{
|
||||
switch (this.getServiceType())
|
||||
{
|
||||
case 'init':
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('service ' + name + ' stop\n');
|
||||
this._update.stdin.write('update-rc.d -f ' + name + ' remove\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
this._update.waitExit();
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync('/etc/init.d/' + name);
|
||||
console.log(name + ' uninstalled');
|
||||
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
console.log(name + ' could not be uninstalled', e)
|
||||
}
|
||||
break;
|
||||
case 'systemd':
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('systemctl stop ' + name + '.service\n');
|
||||
this._update.stdin.write('systemctl disable ' + name + '.service\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
this._update.waitExit();
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync('/usr/local/mesh/' + name);
|
||||
require('fs').unlinkSync('/lib/systemd/system/' + name + '.service');
|
||||
console.log(name + ' uninstalled');
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
console.log(name + ' could not be uninstalled', e)
|
||||
}
|
||||
break;
|
||||
default: // unknown platform service type
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(process.platform == 'darwin')
|
||||
{
|
||||
if (require('fs').existsSync('/Library/LaunchDaemons/' + name + '.plist'))
|
||||
{
|
||||
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
child.stdout.on('data', function (chunk) { });
|
||||
child.stdin.write('launchctl stop ' + name + '\n');
|
||||
child.stdin.write('launchctl unload /Library/LaunchDaemons/' + name + '.plist\n');
|
||||
child.stdin.write('exit\n');
|
||||
child.waitExit();
|
||||
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync('/usr/local/mesh_services/' + name + '/' + name);
|
||||
require('fs').unlinkSync('/Library/LaunchDaemons/' + name + '.plist');
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
throw ('Error uninstalling service: ' + name + ' => ' + e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
require('fs').rmdirSync('/usr/local/mesh_services/' + name);
|
||||
}
|
||||
catch(e)
|
||||
{}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ('Service: ' + name + ' does not exist');
|
||||
}
|
||||
}
|
||||
}
|
||||
if(process.platform == 'linux')
|
||||
{
|
||||
this.getServiceType = function getServiceType()
|
||||
{
|
||||
return (require('process-manager').getProcessInfo(1).Name);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = serviceManager;
|
@ -1,750 +0,0 @@
|
||||
/*
|
||||
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 NOTIFY_FOR_THIS_SESSION = 0;
|
||||
var NOTIFY_FOR_ALL_SESSIONS = 1;
|
||||
var WM_WTSSESSION_CHANGE = 0x02B1;
|
||||
var WM_POWERBROADCAST = 0x218;
|
||||
var PBT_POWERSETTINGCHANGE = 0x8013;
|
||||
var PBT_APMSUSPEND = 0x4;
|
||||
var PBT_APMRESUMESUSPEND = 0x7;
|
||||
var PBT_APMRESUMEAUTOMATIC = 0x12;
|
||||
var PBT_APMPOWERSTATUSCHANGE = 0xA;
|
||||
|
||||
var WTS_CONSOLE_CONNECT = (0x1);
|
||||
var WTS_CONSOLE_DISCONNECT = (0x2);
|
||||
var WTS_REMOTE_CONNECT = (0x3);
|
||||
var WTS_REMOTE_DISCONNECT = (0x4);
|
||||
var WTS_SESSION_LOGON = (0x5);
|
||||
var WTS_SESSION_LOGOFF = (0x6);
|
||||
var WTS_SESSION_LOCK = (0x7);
|
||||
var WTS_SESSION_UNLOCK = (0x8);
|
||||
var WTS_SESSION_REMOTE_CONTROL = (0x9);
|
||||
var WTS_SESSION_CREATE = (0xA);
|
||||
var WTS_SESSION_TERMINATE = (0xB);
|
||||
|
||||
var GUID_ACDC_POWER_SOURCE;
|
||||
var GUID_BATTERY_PERCENTAGE_REMAINING;
|
||||
var GUID_CONSOLE_DISPLAY_STATE;
|
||||
|
||||
function UserSessions()
|
||||
{
|
||||
this._ObjectID = 'user-sessions';
|
||||
require('events').EventEmitter.call(this, true)
|
||||
.createEvent('changed')
|
||||
.createEvent('locked')
|
||||
.createEvent('unlocked');
|
||||
|
||||
this.enumerateUsers = function enumerateUsers()
|
||||
{
|
||||
var promise = require('promise');
|
||||
var p = new promise(function (res, rej)
|
||||
{
|
||||
this.__resolver = res;
|
||||
this.__rejector = rej;
|
||||
});
|
||||
p.__handler = function __handler(users)
|
||||
{
|
||||
p.__resolver(users);
|
||||
};
|
||||
try
|
||||
{
|
||||
this.Current(p.__handler);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
p.__rejector(e);
|
||||
}
|
||||
p.parent = this;
|
||||
return (p);
|
||||
}
|
||||
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this._serviceHooked = false;
|
||||
this._marshal = require('_GenericMarshal');
|
||||
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||
this._kernel32.CreateMethod('GetLastError');
|
||||
|
||||
try
|
||||
{
|
||||
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
||||
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
||||
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
||||
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
||||
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
||||
this._wts.CreateMethod('WTSFreeMemory');
|
||||
}
|
||||
catch(exc)
|
||||
{
|
||||
}
|
||||
|
||||
this._advapi = this._marshal.CreateNativeProxy('Advapi32.dll');
|
||||
this._advapi.CreateMethod('AllocateAndInitializeSid');
|
||||
this._advapi.CreateMethod('CheckTokenMembership');
|
||||
this._advapi.CreateMethod('FreeSid');
|
||||
|
||||
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
|
||||
this._user32.CreateMethod({ method: 'RegisterPowerSettingNotification', threadDispatch: 1});
|
||||
this._user32.CreateMethod('UnregisterPowerSettingNotification');
|
||||
this._rpcrt = this._marshal.CreateNativeProxy('Rpcrt4.dll');
|
||||
this._rpcrt.CreateMethod('UuidFromStringA');
|
||||
this._rpcrt.StringToUUID = function StringToUUID(guid)
|
||||
{
|
||||
var retVal = StringToUUID.us._marshal.CreateVariable(16);
|
||||
if(StringToUUID.us._rpcrt.UuidFromStringA(StringToUUID.us._marshal.CreateVariable(guid), retVal).Val == 0)
|
||||
{
|
||||
return (retVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ('Could not convert string to UUID');
|
||||
}
|
||||
}
|
||||
this._rpcrt.StringToUUID.us = this;
|
||||
|
||||
GUID_ACDC_POWER_SOURCE = this._rpcrt.StringToUUID('5d3e9a59-e9D5-4b00-a6bd-ff34ff516548');
|
||||
GUID_BATTERY_PERCENTAGE_REMAINING = this._rpcrt.StringToUUID('a7ad8041-b45a-4cae-87a3-eecbb468a9e1');
|
||||
GUID_CONSOLE_DISPLAY_STATE = this._rpcrt.StringToUUID('6fe69556-704a-47a0-8f24-c28d936fda47');
|
||||
|
||||
this.SessionStates = ['Active', 'Connected', 'ConnectQuery', 'Shadow', 'Disconnected', 'Idle', 'Listening', 'Reset', 'Down', 'Init'];
|
||||
this.InfoClass =
|
||||
{
|
||||
'WTSInitialProgram': 0,
|
||||
'WTSApplicationName': 1,
|
||||
'WTSWorkingDirectory': 2,
|
||||
'WTSOEMId': 3,
|
||||
'WTSSessionId': 4,
|
||||
'WTSUserName': 5,
|
||||
'WTSWinStationName': 6,
|
||||
'WTSDomainName': 7,
|
||||
'WTSConnectState': 8,
|
||||
'WTSClientBuildNumber': 9,
|
||||
'WTSClientName': 10,
|
||||
'WTSClientDirectory': 11,
|
||||
'WTSClientProductId': 12,
|
||||
'WTSClientHardwareId': 13,
|
||||
'WTSClientAddress': 14,
|
||||
'WTSClientDisplay': 15,
|
||||
'WTSClientProtocolType': 16,
|
||||
'WTSIdleTime': 17,
|
||||
'WTSLogonTime': 18,
|
||||
'WTSIncomingBytes': 19,
|
||||
'WTSOutgoingBytes': 20,
|
||||
'WTSIncomingFrames': 21,
|
||||
'WTSOutgoingFrames': 22,
|
||||
'WTSClientInfo': 23,
|
||||
'WTSSessionInfo': 24,
|
||||
'WTSSessionInfoEx': 25,
|
||||
'WTSConfigInfo': 26,
|
||||
'WTSValidationInfo': 27,
|
||||
'WTSSessionAddressV4': 28,
|
||||
'WTSIsRemoteSession': 29
|
||||
};
|
||||
|
||||
this.isRoot = function isRoot()
|
||||
{
|
||||
var NTAuthority = this._marshal.CreateVariable(6);
|
||||
NTAuthority.toBuffer().writeInt8(5, 5);
|
||||
|
||||
var AdministratorsGroup = this._marshal.CreatePointer();
|
||||
var admin = false;
|
||||
|
||||
if (this._advapi.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
|
||||
{
|
||||
var member = this._marshal.CreateInteger();
|
||||
if (this._advapi.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
|
||||
{
|
||||
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
||||
}
|
||||
this._advapi.FreeSid(AdministratorsGroup.Deref());
|
||||
}
|
||||
return admin;
|
||||
}
|
||||
|
||||
this.getSessionAttribute = function getSessionAttribute(sessionId, attr)
|
||||
{
|
||||
var buffer = this._marshal.CreatePointer();
|
||||
var bytesReturned = this._marshal.CreateVariable(4);
|
||||
|
||||
if (this._wts.WTSQuerySessionInformationA(0, sessionId, attr, buffer, bytesReturned).Val == 0)
|
||||
{
|
||||
throw ('Error calling WTSQuerySessionInformation: ' + this._kernel32.GetLastError.Val);
|
||||
}
|
||||
|
||||
var retVal = buffer.Deref().String;
|
||||
|
||||
this._wts.WTSFreeMemory(buffer.Deref());
|
||||
return (retVal);
|
||||
};
|
||||
|
||||
this.Current = function Current(cb)
|
||||
{
|
||||
var retVal = {};
|
||||
var pinfo = this._marshal.CreatePointer();
|
||||
var count = this._marshal.CreateVariable(4);
|
||||
if (this._wts.WTSEnumerateSessionsA(0, 0, 1, pinfo, count).Val == 0)
|
||||
{
|
||||
throw ('Error calling WTSEnumerateSessionsA: ' + this._kernel32.GetLastError().Val);
|
||||
}
|
||||
|
||||
for (var i = 0; i < count.toBuffer().readUInt32LE() ; ++i)
|
||||
{
|
||||
var info = pinfo.Deref().Deref(i * (this._marshal.PointerSize == 4 ? 12 : 24), this._marshal.PointerSize == 4 ? 12 : 24);
|
||||
var j = { SessionId: info.toBuffer().readUInt32LE() };
|
||||
j.StationName = info.Deref(this._marshal.PointerSize == 4 ? 4 : 8, this._marshal.PointerSize).Deref().String;
|
||||
j.State = this.SessionStates[info.Deref(this._marshal.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE()];
|
||||
if (j.State == 'Active') {
|
||||
j.Username = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSUserName);
|
||||
j.Domain = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSDomainName);
|
||||
}
|
||||
retVal[j.SessionId] = j;
|
||||
}
|
||||
|
||||
this._wts.WTSFreeMemory(pinfo.Deref());
|
||||
|
||||
Object.defineProperty(retVal, 'Active', { value: showActiveOnly(retVal) });
|
||||
if (cb) { cb(retVal); }
|
||||
return (retVal);
|
||||
};
|
||||
|
||||
|
||||
// We need to spin up a message pump, and fetch a window handle
|
||||
var message_pump = require('win-message-pump');
|
||||
this._messagepump = new message_pump({ filter: WM_WTSSESSION_CHANGE }); this._messagepump.parent = this;
|
||||
this._messagepump.on('exit', function (code) { this.parent._wts.WTSUnRegisterSessionNotification(this.parent.hwnd); });
|
||||
this._messagepump.on('hwnd', function (h)
|
||||
{
|
||||
this.parent.hwnd = h;
|
||||
|
||||
// We need to yield, and do this in the next event loop pass, becuase we don't want to call 'RegisterPowerSettingNotification'
|
||||
// from the messagepump 'thread', because we are actually on the microstack thread, such that the message pump thread, is holding
|
||||
// on a semaphore for us to return. If we call now, we may deadlock on Windows 7, becuase it will try to notify immediately
|
||||
this.immediate = setImmediate(function (self)
|
||||
{
|
||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||
if (self.parent._wts) { self.parent._wts.WTSRegisterSessionNotification(self.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS); }
|
||||
self.parent._user32.ACDC_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
||||
self.parent._user32.BATT_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
||||
self.parent._user32.DISP_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0);
|
||||
//console.log(self.parent._user32.ACDC_H.Val, self.parent._user32.BATT_H.Val, self.parent._user32.DISP_H.Val);
|
||||
}, this);
|
||||
});
|
||||
this._messagepump.on('message', function (msg)
|
||||
{
|
||||
switch(msg.message)
|
||||
{
|
||||
case WM_WTSSESSION_CHANGE:
|
||||
switch(msg.wparam)
|
||||
{
|
||||
case WTS_SESSION_LOCK:
|
||||
this.parent.enumerateUsers().then(function (users)
|
||||
{
|
||||
if (users[msg.lparam]) { this.parent.emit('locked', users[msg.lparam]); }
|
||||
});
|
||||
break;
|
||||
case WTS_SESSION_UNLOCK:
|
||||
this.parent.enumerateUsers().then(function (users)
|
||||
{
|
||||
if (users[msg.lparam]) { this.parent.emit('unlocked', users[msg.lparam]); }
|
||||
});
|
||||
break;
|
||||
case WTS_SESSION_LOGON:
|
||||
case WTS_SESSION_LOGOFF:
|
||||
this.parent.emit('changed');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_POWERBROADCAST:
|
||||
switch(msg.wparam)
|
||||
{
|
||||
default:
|
||||
console.log('WM_POWERBROADCAST [UNKNOWN wparam]: ' + msg.wparam);
|
||||
break;
|
||||
case PBT_APMSUSPEND:
|
||||
require('power-monitor').emit('sx', 'SLEEP');
|
||||
break;
|
||||
case PBT_APMRESUMEAUTOMATIC:
|
||||
require('power-monitor').emit('sx', 'RESUME_NON_INTERACTIVE');
|
||||
break;
|
||||
case PBT_APMRESUMESUSPEND:
|
||||
require('power-monitor').emit('sx', 'RESUME_INTERACTIVE');
|
||||
break;
|
||||
case PBT_APMPOWERSTATUSCHANGE:
|
||||
require('power-monitor').emit('changed');
|
||||
break;
|
||||
case PBT_POWERSETTINGCHANGE:
|
||||
var lparam = this.parent._marshal.CreatePointer(Buffer.from(msg.lparam_hex, 'hex'));
|
||||
var data = lparam.Deref(20, lparam.Deref(16, 4).toBuffer().readUInt32LE(0)).toBuffer();
|
||||
switch(lparam.Deref(0, 16).toBuffer().toString('hex'))
|
||||
{
|
||||
case GUID_ACDC_POWER_SOURCE.Deref(0, 16).toBuffer().toString('hex'):
|
||||
switch(data.readUInt32LE(0))
|
||||
{
|
||||
case 0:
|
||||
require('power-monitor').emit('acdc', 'AC');
|
||||
break;
|
||||
case 1:
|
||||
require('power-monitor').emit('acdc', 'BATTERY');
|
||||
break;
|
||||
case 2:
|
||||
require('power-monitor').emit('acdc', 'HOT');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GUID_BATTERY_PERCENTAGE_REMAINING.Deref(0, 16).toBuffer().toString('hex'):
|
||||
require('power-monitor').emit('batteryLevel', data.readUInt32LE(0));
|
||||
break;
|
||||
case GUID_CONSOLE_DISPLAY_STATE.Deref(0, 16).toBuffer().toString('hex'):
|
||||
switch(data.readUInt32LE(0))
|
||||
{
|
||||
case 0:
|
||||
require('power-monitor').emit('display', 'OFF');
|
||||
break;
|
||||
case 1:
|
||||
require('power-monitor').emit('display', 'ON');
|
||||
break;
|
||||
case 2:
|
||||
require('power-monitor').emit('display', 'DIMMED');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(process.platform == 'linux')
|
||||
{
|
||||
var dbus = require('linux-dbus');
|
||||
this._linuxWatcher = require('fs').watch('/var/run/utmp');
|
||||
this._linuxWatcher.user_session = this;
|
||||
this._linuxWatcher.on('change', function (a, b)
|
||||
{
|
||||
this.user_session.emit('changed');
|
||||
});
|
||||
this._users = function _users()
|
||||
{
|
||||
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||
child.waitExit();
|
||||
|
||||
var lines = child.stdout.str.split('\n');
|
||||
var ret = {}, tokens;
|
||||
for (var ln in lines)
|
||||
{
|
||||
tokens = lines[ln].split(':');
|
||||
if (tokens[0]) { ret[tokens[0]] = tokens[1]; }
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
this._uids = function _uids() {
|
||||
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||
child.waitExit();
|
||||
|
||||
var lines = child.stdout.str.split('\n');
|
||||
var ret = {}, tokens;
|
||||
for (var ln in lines) {
|
||||
tokens = lines[ln].split(':');
|
||||
if (tokens[0]) { ret[tokens[1]] = tokens[0]; }
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
this.Self = function Self()
|
||||
{
|
||||
var promise = require('promise');
|
||||
var p = new promise(function (res, rej)
|
||||
{
|
||||
this.__resolver = res; this.__rejector = rej;
|
||||
this.__child = require('child_process').execFile('/usr/bin/id', ['id', '-u']);
|
||||
this.__child.promise = this;
|
||||
this.__child.stdout._txt = '';
|
||||
this.__child.stdout.on('data', function (chunk) { this._txt += chunk.toString(); });
|
||||
this.__child.on('exit', function (code)
|
||||
{
|
||||
try
|
||||
{
|
||||
parseInt(this.stdout._txt);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
this.promise.__rejector('invalid uid');
|
||||
return;
|
||||
}
|
||||
|
||||
var id = parseInt(this.stdout._txt);
|
||||
this.promise.__resolver(id);
|
||||
});
|
||||
});
|
||||
return (p);
|
||||
};
|
||||
this.Current = function Current(cb)
|
||||
{
|
||||
var retVal = {};
|
||||
retVal._ObjectID = 'UserSession'
|
||||
Object.defineProperty(retVal, '_callback', { value: cb });
|
||||
Object.defineProperty(retVal, '_child', { value: 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 = [];
|
||||
var users = {};
|
||||
|
||||
for(var i in lines)
|
||||
{
|
||||
if (lines[i])
|
||||
{
|
||||
var tokens = getTokens(lines[i]);
|
||||
var s = { Username: tokens[0], SessionId: tokens[1] }
|
||||
if (tokens[3].includes('still logged in'))
|
||||
{
|
||||
s.State = 'Active';
|
||||
}
|
||||
else
|
||||
{
|
||||
s.LastActive = tokens[3];
|
||||
}
|
||||
|
||||
sessions.push(s);
|
||||
}
|
||||
}
|
||||
sessions.pop();
|
||||
|
||||
|
||||
var usernames = {};
|
||||
var promises = [];
|
||||
|
||||
for (var i in sessions)
|
||||
{
|
||||
if (sessions[i].Username != 'reboot')
|
||||
{
|
||||
users[sessions[i].SessionId] = sessions[i];
|
||||
if(usernames[sessions[i].Username] == null)
|
||||
{
|
||||
usernames[sessions[i].Username] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
require('promise');
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||
if (this.Parent._callback) { this.Parent._callback.call(this.Parent, users); }
|
||||
return;
|
||||
}
|
||||
|
||||
var promise = require('promise');
|
||||
for (var n in usernames)
|
||||
{
|
||||
var p = new promise(function (res, rej)
|
||||
{
|
||||
this.__username = n;
|
||||
this.__resolver = res; this.__rejector = rej;
|
||||
this.__child = require('child_process').execFile('/usr/bin/id', ['id', '-u', n]);
|
||||
this.__child.promise = this;
|
||||
this.__child.stdout._txt = '';
|
||||
this.__child.stdout.on('data', function (chunk) { this._txt += chunk.toString(); });
|
||||
this.__child.on('exit', function (code)
|
||||
{
|
||||
try
|
||||
{
|
||||
parseInt(this.stdout._txt);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
this.promise.__rejector('invalid uid');
|
||||
return;
|
||||
}
|
||||
|
||||
var id = parseInt(this.stdout._txt);
|
||||
this.promise.__resolver(id);
|
||||
});
|
||||
});
|
||||
promises.push(p);
|
||||
}
|
||||
promise.all(promises).then(function (plist)
|
||||
{
|
||||
// Done
|
||||
var table = {};
|
||||
for(var i in plist)
|
||||
{
|
||||
table[plist[i].__username] = plist[i]._internal.completedArgs[0];
|
||||
}
|
||||
for(var i in users)
|
||||
{
|
||||
users[i].uid = table[users[i].Username];
|
||||
}
|
||||
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||
if (retVal._callback) { retVal._callback.call(retVal, users); }
|
||||
}, function (reason)
|
||||
{
|
||||
// Failed
|
||||
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||
if (retVal._callback) { retVal._callback.call(retVal, users); }
|
||||
});
|
||||
});
|
||||
retVal._child.stdout.Parent = retVal._child;
|
||||
retVal._child.stdout.on('data', function (chunk) { this.Parent._txt += chunk.toString(); });
|
||||
|
||||
return (retVal);
|
||||
}
|
||||
this._recheckLoggedInUsers = function _recheckLoggedInUsers()
|
||||
{
|
||||
this.enumerateUsers().then(function (u)
|
||||
{
|
||||
|
||||
if (u.Active.length > 0)
|
||||
{
|
||||
// There is already a user logged in, so we can monitor DBUS for lock/unlock
|
||||
if (this.parent._linux_lock_watcher != null && this.parent._linux_lock_watcher.uid != u.Active[0].uid)
|
||||
{
|
||||
delete this.parent._linux_lock_watcher;
|
||||
}
|
||||
this.parent._linux_lock_watcher = new dbus(process.env['XDG_CURRENT_DESKTOP'] == 'Unity' ? 'com.ubuntu.Upstart0_6' : 'org.gnome.ScreenSaver', u.Active[0].uid);
|
||||
this.parent._linux_lock_watcher.user_session = this.parent;
|
||||
this.parent._linux_lock_watcher.on('signal', function (s)
|
||||
{
|
||||
var p = this.user_session.enumerateUsers();
|
||||
p.signalData = s.data[0];
|
||||
p.then(function (u)
|
||||
{
|
||||
switch (this.signalData)
|
||||
{
|
||||
case true:
|
||||
case 'desktop-lock':
|
||||
this.parent.emit('locked', u.Active[0]);
|
||||
break;
|
||||
case false:
|
||||
case 'desktop-unlock':
|
||||
this.parent.emit('unlocked', u.Active[0]);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (this.parent._linux_lock_watcher != null)
|
||||
{
|
||||
delete this.parent._linux_lock_watcher;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
this.on('changed', this._recheckLoggedInUsers); // For linux Lock/Unlock monitoring, we need to watch for LogOn/LogOff, and keep track of the UID.
|
||||
|
||||
|
||||
// First step, is to see if there is a user logged in:
|
||||
this._recheckLoggedInUsers();
|
||||
}
|
||||
else if(process.platform == 'darwin')
|
||||
{
|
||||
this._users = function ()
|
||||
{
|
||||
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.stdin.write('exit\n');
|
||||
child.waitExit();
|
||||
|
||||
var lines = child.stdout.str.split('\n');
|
||||
var tokens, i;
|
||||
var users = {};
|
||||
|
||||
for (i = 0; i < lines.length; ++i) {
|
||||
tokens = lines[i].split(' ');
|
||||
if (tokens[0]) { users[tokens[0]] = tokens[tokens.length - 1]; }
|
||||
}
|
||||
|
||||
return (users);
|
||||
}
|
||||
this._uids = function () {
|
||||
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.stdin.write('exit\n');
|
||||
child.waitExit();
|
||||
|
||||
var lines = child.stdout.str.split('\n');
|
||||
var tokens, i;
|
||||
var users = {};
|
||||
|
||||
for (i = 0; i < lines.length; ++i) {
|
||||
tokens = lines[i].split(' ');
|
||||
if (tokens[0]) { users[tokens[tokens.length - 1]] = tokens[0]; }
|
||||
}
|
||||
|
||||
return (users);
|
||||
}
|
||||
this._idTable = function()
|
||||
{
|
||||
var table = {};
|
||||
var child = require('child_process').execFile('/usr/bin/id', ['id']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.waitExit();
|
||||
|
||||
var lines = child.stdout.str.split('\n')[0].split(' ');
|
||||
for (var i = 0; i < lines.length; ++i) {
|
||||
var types = lines[i].split('=');
|
||||
var tokens = types[1].split(',');
|
||||
table[types[0]] = {};
|
||||
|
||||
for (var j in tokens) {
|
||||
var idarr = tokens[j].split('(');
|
||||
var id = idarr[0];
|
||||
var name = idarr[1].substring(0, idarr[1].length - 1).trim();
|
||||
table[types[0]][name] = id;
|
||||
table[types[0]][id] = name;
|
||||
}
|
||||
}
|
||||
return (table);
|
||||
}
|
||||
this.Current = function (cb)
|
||||
{
|
||||
var users = {};
|
||||
var table = this._idTable();
|
||||
var child = require('child_process').execFile('/usr/bin/last', ['last']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.waitExit();
|
||||
|
||||
var lines = child.stdout.str.split('\n');
|
||||
for (var i = 0; i < lines.length && lines[i].length > 0; ++i)
|
||||
{
|
||||
if (!users[lines[i].split(' ')[0]])
|
||||
{
|
||||
try
|
||||
{
|
||||
users[lines[i].split(' ')[0]] = { Username: lines[i].split(' ')[0], State: lines[i].split('still logged in').length > 1 ? 'Active' : 'Inactive', uid: table.uid[lines[i].split(' ')[0]] };
|
||||
}
|
||||
catch(e)
|
||||
{}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(users[lines[i].split(' ')[0]].State != 'Active' && lines[i].split('still logged in').length > 1)
|
||||
{
|
||||
users[lines[i].split(' ')[0]].State = 'Active';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
||||
if (cb) { cb.call(this, users); }
|
||||
}
|
||||
}
|
||||
|
||||
if(process.platform == 'linux' || process.platform == 'darwin')
|
||||
{
|
||||
this._self = function _self()
|
||||
{
|
||||
var child = require('child_process').execFile('/usr/bin/id', ['id', '-u']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.waitExit();
|
||||
return (parseInt(child.stdout.str));
|
||||
}
|
||||
this.isRoot = function isRoot()
|
||||
{
|
||||
return (this._self() == 0);
|
||||
}
|
||||
this.consoleUid = function consoleUid()
|
||||
{
|
||||
var checkstr = process.platform == 'darwin' ? 'console' : ((process.env['DISPLAY'])?process.env['DISPLAY']:':0')
|
||||
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
child.stdout.str = '';
|
||||
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||
child.stdin.write('who\nexit\n');
|
||||
child.waitExit();
|
||||
|
||||
var lines = child.stdout.str.split('\n');
|
||||
var tokens, i, j;
|
||||
for (i in lines)
|
||||
{
|
||||
tokens = lines[i].split(' ');
|
||||
for (j = 1; j < tokens.length; ++j)
|
||||
{
|
||||
if (tokens[j].length > 0)
|
||||
{
|
||||
return (parseInt(this._users()[tokens[0]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw ('nobody logged into console');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
function showActiveOnly(source)
|
||||
{
|
||||
var retVal = [];
|
||||
var unique = {};
|
||||
var usernames = [];
|
||||
var tmp;
|
||||
|
||||
for (var i in source)
|
||||
{
|
||||
if (source[i].State == 'Active')
|
||||
{
|
||||
retVal.push(source[i]);
|
||||
tmp = (source[i].Domain ? (source[i].Domain + '\\') : '') + source[i].Username;
|
||||
if (!unique[tmp]) { unique[tmp] = tmp;}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i in unique)
|
||||
{
|
||||
usernames.push(i);
|
||||
}
|
||||
|
||||
Object.defineProperty(retVal, 'usernames', { value: usernames });
|
||||
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, (i=str.substring(i).indexOf(' ') + i)));
|
||||
while (str[++i] == ' ');
|
||||
columns.push(str.substring(i, (i=str.substring(i).indexOf(' ') + i)));
|
||||
while (str[++i] == ' ');
|
||||
var status = str.substring(i).trim();
|
||||
columns.push(status);
|
||||
|
||||
return (columns);
|
||||
}
|
||||
|
||||
module.exports = new UserSessions();
|
@ -1,124 +0,0 @@
|
||||
/*
|
||||
Copyright 2018-2019 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;
|
||||
|
||||
var GM = require('_GenericMarshal');
|
||||
|
||||
function WindowsMessagePump(options)
|
||||
{
|
||||
this._ObjectID = 'win-message-pump';
|
||||
this._options = options;
|
||||
var emitterUtils = require('events').inherits(this);
|
||||
emitterUtils.createEvent('hwnd');
|
||||
emitterUtils.createEvent('error');
|
||||
emitterUtils.createEvent('message');
|
||||
emitterUtils.createEvent('exit');
|
||||
|
||||
this._msg = GM.CreateVariable(GM.PointerSize == 4 ? 28 : 48);
|
||||
this._kernel32 = GM.CreateNativeProxy('Kernel32.dll');
|
||||
this._kernel32.mp = this;
|
||||
this._kernel32.CreateMethod('GetLastError');
|
||||
this._kernel32.CreateMethod('GetModuleHandleA');
|
||||
|
||||
this._user32 = GM.CreateNativeProxy('User32.dll');
|
||||
this._user32.mp = this;
|
||||
this._user32.CreateMethod('GetMessageA');
|
||||
this._user32.CreateMethod('CreateWindowExA');
|
||||
this._user32.CreateMethod('TranslateMessage');
|
||||
this._user32.CreateMethod('DispatchMessageA');
|
||||
this._user32.CreateMethod('RegisterClassExA');
|
||||
this._user32.CreateMethod('DefWindowProcA');
|
||||
this._user32.CreateMethod('PostMessageA');
|
||||
|
||||
|
||||
this.wndclass = GM.CreateVariable(GM.PointerSize == 4 ? 48 : 80);
|
||||
this.wndclass.mp = this;
|
||||
this.wndclass.hinstance = this._kernel32.GetModuleHandleA(0);
|
||||
this.wndclass.cname = GM.CreateVariable('MainWWWClass');
|
||||
this.wndclass.wndproc = GM.GetGenericGlobalCallback(4);
|
||||
this.wndclass.wndproc.mp = this;
|
||||
this.wndclass.toBuffer().writeUInt32LE(this.wndclass._size);
|
||||
this.wndclass.cname.pointerBuffer().copy(this.wndclass.Deref(GM.PointerSize == 4 ? 40 : 64, GM.PointerSize).toBuffer());
|
||||
this.wndclass.wndproc.pointerBuffer().copy(this.wndclass.Deref(8, GM.PointerSize).toBuffer());
|
||||
this.wndclass.hinstance.pointerBuffer().copy(this.wndclass.Deref(GM.PointerSize == 4 ? 20 : 24, GM.PointerSize).toBuffer());
|
||||
this.wndclass.wndproc.on('GlobalCallback', function onWndProc(xhwnd, xmsg, wparam, lparam)
|
||||
{
|
||||
if (this.mp._hwnd != null && this.mp._hwnd.Val == xhwnd.Val)
|
||||
{
|
||||
// This is for us
|
||||
this.mp.emit('message', { message: xmsg.Val, wparam: wparam.Val, lparam: lparam.Val, lparam_hex: lparam.pointerBuffer().toString('hex') });
|
||||
return (this.mp._user32.DefWindowProcA(xhwnd, xmsg, wparam, lparam));
|
||||
}
|
||||
else if(this.mp._hwnd == null && this.CallingThread() == this.mp._user32.RegisterClassExA.async.threadId())
|
||||
{
|
||||
// This message was generated from our CreateWindowExA method
|
||||
return (this.mp._user32.DefWindowProcA(xhwnd, xmsg, wparam, lparam));
|
||||
}
|
||||
});
|
||||
|
||||
this._user32.RegisterClassExA.async(this.wndclass).then(function ()
|
||||
{
|
||||
this.nativeProxy.CreateWindowExA.async(this.nativeProxy.RegisterClassExA.async, 0x00000088, this.nativeProxy.mp.wndclass.cname, 0, 0x00800000, 0, 0, 100, 100, 0, 0, 0, 0)
|
||||
.then(function(h)
|
||||
{
|
||||
if (h.Val == 0)
|
||||
{
|
||||
// Error creating hidden window
|
||||
this.nativeProxy.mp.emit('error', 'Error creating hidden window');
|
||||
}
|
||||
else
|
||||
{
|
||||
this.nativeProxy.mp._hwnd = h;
|
||||
this.nativeProxy.mp.emit('hwnd', h);
|
||||
this.nativeProxy.mp._startPump();
|
||||
}
|
||||
});
|
||||
});
|
||||
this._startPump = function _startPump()
|
||||
{
|
||||
this._user32.GetMessageA.async(this._user32.RegisterClassExA.async, this._msg, this._hwnd, 0, 0).then(function (r)
|
||||
{
|
||||
if(r.Val > 0)
|
||||
{
|
||||
this.nativeProxy.TranslateMessage.async(this.nativeProxy.RegisterClassExA.async, this.nativeProxy.mp._msg).then(function ()
|
||||
{
|
||||
this.nativeProxy.DispatchMessageA.async(this.nativeProxy.RegisterClassExA.async, this.nativeProxy.mp._msg).then(function ()
|
||||
{
|
||||
this.nativeProxy.mp._startPump();
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// We got a 'QUIT' message
|
||||
delete this.nativeProxy.mp._hwnd;
|
||||
this.nativeProxy.mp.emit('exit', 0);
|
||||
}
|
||||
}, function (err) { this.nativeProxy.mp.stop(); });
|
||||
}
|
||||
|
||||
this.stop = function stop()
|
||||
{
|
||||
if (this._hwnd)
|
||||
{
|
||||
this._user32.PostMessageA(this._hwnd, WM_QUIT, 0, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = WindowsMessagePump;
|
@ -1,218 +0,0 @@
|
||||
/*
|
||||
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_ENUMERATE_SUB_KEYS = 0x0008;
|
||||
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 = 'win-registry';
|
||||
this._marshal = require('_GenericMarshal');
|
||||
this._AdvApi = this._marshal.CreateNativeProxy('Advapi32.dll');
|
||||
this._AdvApi.CreateMethod('RegCreateKeyExA');
|
||||
this._AdvApi.CreateMethod('RegEnumKeyExA');
|
||||
this._AdvApi.CreateMethod('RegEnumValueA');
|
||||
this._AdvApi.CreateMethod('RegOpenKeyExA');
|
||||
this._AdvApi.CreateMethod('RegQueryInfoKeyA');
|
||||
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 err;
|
||||
var h = this._marshal.CreatePointer();
|
||||
var len = this._marshal.CreateVariable(4);
|
||||
var valType = this._marshal.CreateVariable(4);
|
||||
var HK = this._marshal.CreatePointer(hkey);
|
||||
var retVal = null;
|
||||
if (key) { key = this._marshal.CreateVariable(key); }
|
||||
if (!path) { path = ''; }
|
||||
|
||||
|
||||
if ((err = this._AdvApi.RegOpenKeyExA(HK, this._marshal.CreateVariable(path), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, h).Val) != 0)
|
||||
{
|
||||
throw ('Opening Registry Key: ' + path + ' => Returned Error: ' + err);
|
||||
}
|
||||
|
||||
if ((path == '' && !key) || !key)
|
||||
{
|
||||
var result = { subkeys: [], values: [] };
|
||||
|
||||
// Enumerate keys
|
||||
var achClass = this._marshal.CreateVariable(1024);
|
||||
var achKey = this._marshal.CreateVariable(1024);
|
||||
var achValue = this._marshal.CreateVariable(32768);
|
||||
var achValueSize = this._marshal.CreateVariable(4);
|
||||
var nameSize = this._marshal.CreateVariable(4);
|
||||
var achClassSize = this._marshal.CreateVariable(4); achClassSize.toBuffer().writeUInt32LE(1024);
|
||||
var numSubKeys = this._marshal.CreateVariable(4);
|
||||
var numValues = this._marshal.CreateVariable(4);
|
||||
var longestSubkeySize = this._marshal.CreateVariable(4);
|
||||
var longestClassString = this._marshal.CreateVariable(4);
|
||||
var longestValueName = this._marshal.CreateVariable(4);
|
||||
var longestValueData = this._marshal.CreateVariable(4);
|
||||
var securityDescriptor = this._marshal.CreateVariable(4);
|
||||
var lastWriteTime = this._marshal.CreateVariable(8);
|
||||
|
||||
retVal = this._AdvApi.RegQueryInfoKeyA(h.Deref(), achClass, achClassSize, 0,
|
||||
numSubKeys, longestSubkeySize, longestClassString, numValues,
|
||||
longestValueName, longestValueData, securityDescriptor, lastWriteTime);
|
||||
if (retVal.Val != 0) { throw ('RegQueryInfoKeyA() returned error: ' + retVal.Val); }
|
||||
for(var i = 0; i < numSubKeys.toBuffer().readUInt32LE(); ++i)
|
||||
{
|
||||
nameSize.toBuffer().writeUInt32LE(1024);
|
||||
retVal = this._AdvApi.RegEnumKeyExA(h.Deref(), i, achKey, nameSize, 0, 0, 0, lastWriteTime);
|
||||
if(retVal.Val == 0)
|
||||
{
|
||||
result.subkeys.push(achKey.String);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < numValues.toBuffer().readUInt32LE() ; ++i)
|
||||
{
|
||||
achValueSize.toBuffer().writeUInt32LE(32768);
|
||||
if(this._AdvApi.RegEnumValueA(h.Deref(), i, achValue, achValueSize, 0, 0, 0, 0).Val == 0)
|
||||
{
|
||||
result.values.push(achValue.String);
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
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();
|
||||
|
Loading…
Reference in New Issue
Block a user