mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-03-09 15:40:18 +00:00
New MeshAgent, new border blinking feature.
This commit is contained in:
parent
c531b64643
commit
1b3255e844
35 changed files with 7423 additions and 177 deletions
|
@ -1,24 +1,61 @@
|
|||
/*
|
||||
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 SERVICE_WIN32 = 0x00000010 | 0x00000020;
|
||||
var SERVICE_STATE = { STOPPED: 0x00000001, SERVICE_START_PENDING: 0x00000002, SERVICE_STOP_PENDING: 0x00000003, RUNNING: 0x00000004 };
|
||||
var SERVICE_ACCEPT = { SERVICE_ACCEPT_STOP: 0x00000001, SERVICE_ACCEPT_SHUTDOWN: 0x00000004 };
|
||||
var SERVICE_CONTROL = { SERVICE_CONTROL_SHUTDOWN: 0x00000005, SERVICE_CONTROL_STOP: 0x00000001 };
|
||||
var SERVICE_ACCEPT = { SERVICE_ACCEPT_STOP: 0x00000001, SERVICE_ACCEPT_SHUTDOWN: 0x00000004, SERVICE_ACCEPT_POWEREVENT: 0x00000040, SERVICE_ACCEPT_SESSIONCHANGE: 0x00000080 };
|
||||
|
||||
var SERVICE_CONTROL = { SERVICE_CONTROL_SHUTDOWN: 0x00000005, SERVICE_CONTROL_STOP: 0x00000001, SERVICE_CONTROL_POWEREVENT: 0x0000000D, SERVICE_CONTROL_SESSIONCHANGE: 0x0000000E};
|
||||
var SESSION_CHANGE_TYPE =
|
||||
{
|
||||
WTS_CONSOLE_CONNECT: 0x1,
|
||||
WTS_CONSOLE_DISCONNECT: 0x2,
|
||||
WTS_REMOTE_CONNECT: 0x3,
|
||||
WTS_REMOTE_DISCONNECT: 0x4,
|
||||
WTS_SESSION_LOGON: 0x5,
|
||||
WTS_SESSION_LOGOFF: 0x6,
|
||||
WTS_SESSION_LOCK: 0x7,
|
||||
WTS_SESSION_UNLOCK: 0x8,
|
||||
WTS_SESSION_REMOTE_CONTROL: 0x9,
|
||||
WTS_SESSION_CREATE: 0xa,
|
||||
WTS_SESSION_TERMINATE: 0xb
|
||||
};
|
||||
|
||||
|
||||
var NO_ERROR = 0;
|
||||
|
||||
var serviceManager = require('serviceManager');
|
||||
var serviceManager = require('service-manager');
|
||||
|
||||
function serviceHost(serviceName) {
|
||||
this._ObjectID = 'serviceHost';
|
||||
function serviceHost(serviceName)
|
||||
{
|
||||
this._ObjectID = 'service-host';
|
||||
var emitterUtils = require('events').inherits(this);
|
||||
emitterUtils.createEvent('serviceStart');
|
||||
emitterUtils.createEvent('serviceStop');
|
||||
emitterUtils.createEvent('normalStart');
|
||||
emitterUtils.createEvent('session');
|
||||
emitterUtils.createEvent('powerStateChange');
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this.GM = require('_GenericMarshal');
|
||||
this.Advapi = this.GM.CreateNativeProxy('Advapi32.dll');
|
||||
this.Advapi.CreateMethod({ method: 'StartServiceCtrlDispatcherA', threadDispatch: 1 });
|
||||
this.Advapi.CreateMethod('RegisterServiceCtrlHandlerA');
|
||||
this.Advapi.CreateMethod('RegisterServiceCtrlHandlerExA');
|
||||
this.Advapi.CreateMethod('SetServiceStatus');
|
||||
this.Kernel32 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||
this.Kernel32.CreateMethod('GetLastError');
|
||||
|
@ -31,7 +68,8 @@ function serviceHost(serviceName) {
|
|||
this._ServiceMain = this.GM.GetGenericGlobalCallback(2);
|
||||
this._ServiceMain.Parent = this;
|
||||
this._ServiceMain.GM = this.GM;
|
||||
this._ServiceMain.on('GlobalCallback', function onGlobalCallback(argc, argv) {
|
||||
this._ServiceMain.on('GlobalCallback', function onGlobalCallback(argc, argv)
|
||||
{
|
||||
//ToDo: Check to make sure this is for us
|
||||
|
||||
this.Parent._ServiceStatus = this.GM.CreateVariable(28);
|
||||
|
@ -48,8 +86,9 @@ function serviceHost(serviceName) {
|
|||
// Initialise service status
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_WIN32);
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_STATE.SERVICE_STOPPED, 4);
|
||||
this.Parent._ServiceStatusHandle = this.Parent.Advapi.RegisterServiceCtrlHandlerA(this.Parent._ServiceName, this.Parent._ServiceControlHandler);
|
||||
if (this.Parent._ServiceStatusHandle.Val == 0) {
|
||||
this.Parent._ServiceStatusHandle = this.Parent.Advapi.RegisterServiceCtrlHandlerExA(this.Parent._ServiceName, this.Parent._ServiceControlHandler, this.Parent.GM.StashObject(this.Parent._ServiceControlHandler));
|
||||
if(this.Parent._ServiceStatusHandle.Val == 0)
|
||||
{
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
@ -59,11 +98,12 @@ function serviceHost(serviceName) {
|
|||
|
||||
// Service running
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_STATE.RUNNING, 4);
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_ACCEPT.SERVICE_ACCEPT_STOP, 8);
|
||||
this.Parent._ServiceStatus.toBuffer().writeUInt32LE(SERVICE_ACCEPT.SERVICE_ACCEPT_STOP | SERVICE_ACCEPT.SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT.SERVICE_ACCEPT_SESSIONCHANGE, 8);
|
||||
this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
|
||||
|
||||
this.Parent.Ole32.CoInitializeEx(0, 2);
|
||||
this.Parent.on('~', function OnServiceHostFinalizer() {
|
||||
this.Parent.on('~', function OnServiceHostFinalizer()
|
||||
{
|
||||
var GM = require('_GenericMarshal');
|
||||
var Advapi = GM.CreateNativeProxy('Advapi32.dll');
|
||||
Advapi.CreateMethod('SetServiceStatus');
|
||||
|
@ -82,22 +122,39 @@ function serviceHost(serviceName) {
|
|||
|
||||
this.Ole32.CoUninitialize();
|
||||
});
|
||||
|
||||
this.Parent.emit('serviceStart');
|
||||
});
|
||||
this._ServiceControlHandler = this.GM.GetGenericGlobalCallback(1);
|
||||
this._ServiceControlHandler = this.GM.GetGenericGlobalCallback(4);
|
||||
this._ServiceControlHandler.Parent = this;
|
||||
this._ServiceControlHandler.GM = this.GM;
|
||||
this._ServiceControlHandler.on('GlobalCallback', function onServiceControlHandler(code) {
|
||||
switch (code.Val) {
|
||||
case SERVICE_CONTROL.SERVICE_CONTROL_SHUTDOWN:
|
||||
case SERVICE_CONTROL.SERVICE_CONTROL_STOP:
|
||||
this.Parent.emit('serviceStop');
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this._ServiceControlHandler.on('GlobalCallback', function onServiceControlHandler(code, eventType, eventData, context)
|
||||
{
|
||||
var j = this.Parent.GM.UnstashObject(context);
|
||||
if (j != null && j == this)
|
||||
{
|
||||
switch (code.Val)
|
||||
{
|
||||
case SERVICE_CONTROL.SERVICE_CONTROL_SHUTDOWN:
|
||||
case SERVICE_CONTROL.SERVICE_CONTROL_STOP:
|
||||
this.Parent.emit('serviceStop');
|
||||
return;
|
||||
case SERVICE_CONTROL.SERVICE_CONTROL_SESSIONCHANGE:
|
||||
var sessionId = eventData.Deref(4, 4).toBuffer().readUInt32LE();
|
||||
switch(eventType.Val)
|
||||
{
|
||||
case SESSION_CHANGE_TYPE.WTS_SESSION_LOGON:
|
||||
case SESSION_CHANGE_TYPE.WTS_SESSION_LOGOFF:
|
||||
require('user-sessions').emit('changed');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
|
||||
this.Parent.Advapi.SetServiceStatus(this.Parent._ServiceStatusHandle, this.Parent._ServiceStatus);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -106,42 +163,54 @@ function serviceHost(serviceName) {
|
|||
{
|
||||
throw ('Must specify either ServiceName or Options');
|
||||
}
|
||||
if (!this._ServiceOptions.servicePath) {
|
||||
if (!this._ServiceOptions.servicePath)
|
||||
{
|
||||
this._ServiceOptions.servicePath = process.execPath;
|
||||
}
|
||||
|
||||
this.run = function run() {
|
||||
|
||||
this.run = function run()
|
||||
{
|
||||
var serviceOperation = 0;
|
||||
|
||||
for (var i = 0; i < process.argv.length; ++i) {
|
||||
switch (process.argv[i].toLowerCase()) {
|
||||
case 'install':
|
||||
for(var i = 0; i<process.argv.length; ++i)
|
||||
{
|
||||
switch(process.argv[i])
|
||||
{
|
||||
case '-install':
|
||||
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||
try {
|
||||
try
|
||||
{
|
||||
this._svcManager.installService(this._ServiceOptions);
|
||||
} catch (e) {
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.log(e);
|
||||
process.exit();
|
||||
}
|
||||
if (process.platform == 'win32') {
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
// Only do this on Windows, becuase Linux is async... It'll complete later
|
||||
console.log(this._ServiceOptions.name + ' installed.');
|
||||
console.log(this._ServiceOptions.name + ' installed');
|
||||
process.exit();
|
||||
}
|
||||
i = process.argv.length;
|
||||
serviceOperation = 1;
|
||||
break;
|
||||
case 'uninstall':
|
||||
case '-uninstall':
|
||||
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||
try {
|
||||
try
|
||||
{
|
||||
this._svcManager.uninstallService(this._ServiceOptions);
|
||||
} catch (e) {
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.log(e);
|
||||
process.exit();
|
||||
}
|
||||
if (process.platform == 'win32') {
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
// Only do this on Windows, becuase Linux is async... It'll complete later
|
||||
console.log(this._ServiceOptions.name + ' uninstalled.');
|
||||
console.log(this._ServiceOptions.name + ' uninstalled');
|
||||
process.exit();
|
||||
}
|
||||
i = process.argv.length;
|
||||
|
@ -149,48 +218,59 @@ function serviceHost(serviceName) {
|
|||
break;
|
||||
case 'start':
|
||||
case '-d':
|
||||
if (process.platform != 'win32') { break; }
|
||||
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||
this._svcManager.getService(this._ServiceOptions.name).start();
|
||||
console.log(this._ServiceOptions.name + ' starting.');
|
||||
console.log(this._ServiceOptions.name + ' starting...');
|
||||
process.exit();
|
||||
break;
|
||||
case 'stop':
|
||||
case '-s':
|
||||
if (process.platform != 'win32') { break; }
|
||||
if (!this._svcManager) { this._svcManager = new serviceManager(); }
|
||||
this._svcManager.getService(this._ServiceOptions.name).stop();
|
||||
console.log(this._ServiceOptions.name + ' stopping.');
|
||||
console.log(this._ServiceOptions.name + ' stopping...');
|
||||
process.exit();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
var serviceTable = this.GM.CreateVariable(4 * this.GM.PointerSize);
|
||||
this._ServiceName.pointerBuffer().copy(serviceTable.toBuffer());
|
||||
this._ServiceMain.pointerBuffer().copy(serviceTable.toBuffer(), this.GM.PointerSize);
|
||||
this._sscd = this.Advapi.StartServiceCtrlDispatcherA(serviceTable);
|
||||
this._sscd.parent = this;
|
||||
this._sscd.on('done', function OnStartServiceCtrlDispatcherA(retVal) {
|
||||
if (retVal.Val == 0) { this.parent.emit('normalStart'); }
|
||||
if (retVal.Val == 0)
|
||||
{
|
||||
this.parent.emit('normalStart');
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var moduleName = this._ServiceOptions ? this._ServiceOptions.name : process.execPath.substring(1 + process.execPath.lastIndexOf('/'));
|
||||
|
||||
for (var i = 0; i < process.argv.length; ++i) {
|
||||
switch (process.argv[i].toLowerCase()) {
|
||||
for (var i = 0; i < process.argv.length; ++i)
|
||||
{
|
||||
switch(process.argv[i])
|
||||
{
|
||||
case 'start':
|
||||
case '-d':
|
||||
var child = require('child_process').execFile(process.execPath, [moduleName], { type: require('child_process').SpawnTypes.DETACHED });
|
||||
var pstream = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
pstream = require('fs').createWriteStream('/var/run/' + moduleName + '.pid', { flags: 'w' });
|
||||
}
|
||||
catch (e) {
|
||||
catch(e)
|
||||
{
|
||||
}
|
||||
if (pstream == null) {
|
||||
if (pstream == null)
|
||||
{
|
||||
pstream = require('fs').createWriteStream('.' + moduleName + '.pid', { flags: 'w' });
|
||||
}
|
||||
pstream.end(child.pid.toString());
|
||||
|
@ -201,26 +281,33 @@ function serviceHost(serviceName) {
|
|||
case 'stop':
|
||||
case '-s':
|
||||
var pid = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
||||
require('fs').unlinkSync('/var/run/' + moduleName + '.pid');
|
||||
}
|
||||
catch (e) {
|
||||
catch(e)
|
||||
{
|
||||
}
|
||||
if (pid == null) {
|
||||
try {
|
||||
if(pid == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
||||
require('fs').unlinkSync('.' + moduleName + '.pid');
|
||||
}
|
||||
catch (e) {
|
||||
catch(e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (pid) {
|
||||
if(pid)
|
||||
{
|
||||
process.kill(pid);
|
||||
console.log(moduleName + ' stopped');
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
console.log(moduleName + ' not running');
|
||||
}
|
||||
process.exit();
|
||||
|
@ -228,30 +315,56 @@ function serviceHost(serviceName) {
|
|||
}
|
||||
}
|
||||
|
||||
if (serviceOperation == 0) {
|
||||
if(serviceOperation == 0)
|
||||
{
|
||||
// This is non-windows, so we need to check how this binary was started to determine if this was a service start
|
||||
|
||||
// Start by checking if we were started with start/stop
|
||||
var pid = null;
|
||||
try { pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' })); } catch (e) { }
|
||||
if (pid == null) { try { pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' })); } catch (e) { } }
|
||||
|
||||
if (pid != null && pid == process.pid) {
|
||||
try
|
||||
{
|
||||
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
}
|
||||
if (pid == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (pid != null && pid == process.pid)
|
||||
{
|
||||
this.emit('serviceStart');
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Now we need to check if we were started with systemd
|
||||
if (require('processManager').getProcessInfo(1).Name == 'systemd') {
|
||||
if (require('process-manager').getProcessInfo(1).Name == 'systemd')
|
||||
{
|
||||
this._checkpid = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._checkpid.result = '';
|
||||
this._checkpid.parent = this;
|
||||
this._checkpid.on('exit', function onCheckPIDExit() {
|
||||
this._checkpid.on('exit', function onCheckPIDExit()
|
||||
{
|
||||
var lines = this.result.split('\r\n');
|
||||
for (i in lines) {
|
||||
if (lines[i].startsWith(' Main PID:')) {
|
||||
for (i in lines)
|
||||
{
|
||||
if(lines[i].startsWith(' Main PID:'))
|
||||
{
|
||||
var tokens = lines[i].split(' ');
|
||||
if (parseInt(tokens[3]) == process.pid) {
|
||||
if (parseInt(tokens[3]) == process.pid)
|
||||
{
|
||||
this.parent.emit('serviceStart');
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
this.parent.emit('normalStart');
|
||||
}
|
||||
delete this.parent._checkpid;
|
||||
|
@ -265,7 +378,8 @@ function serviceHost(serviceName) {
|
|||
this._checkpid.stdin.write("systemctl status " + moduleName + " | grep 'Main PID:'\n");
|
||||
this._checkpid.stdin.write('exit\n');
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// This isn't even a systemd platform, so this couldn't have been a service start
|
||||
this.emit('normalStart');
|
||||
}
|
|
@ -1,6 +1,21 @@
|
|||
/*
|
||||
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
|
||||
|
||||
function parseServiceStatus(token) {
|
||||
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);
|
||||
|
@ -8,7 +23,8 @@ function parseServiceStatus(token) {
|
|||
j.isSharedProcess = ((serviceType & 0x00000020) == 0x00000020);
|
||||
j.isOwnProcess = ((serviceType & 0x00000010) == 0x00000010);
|
||||
j.isInteractive = ((serviceType & 0x00000100) == 0x00000100);
|
||||
switch (token.Deref((1 * 4), 4).toBuffer().readUInt32LE()) {
|
||||
switch (token.Deref((1 * 4), 4).toBuffer().readUInt32LE())
|
||||
{
|
||||
case 0x00000005:
|
||||
j.state = 'CONTINUE_PENDING';
|
||||
break;
|
||||
|
@ -33,7 +49,8 @@ function parseServiceStatus(token) {
|
|||
}
|
||||
var controlsAccepted = token.Deref((2 * 4), 4).toBuffer().readUInt32LE();
|
||||
j.controlsAccepted = [];
|
||||
if ((controlsAccepted & 0x00000010) == 0x00000010) {
|
||||
if ((controlsAccepted & 0x00000010) == 0x00000010)
|
||||
{
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDADD');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDREMOVE');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDENABLE');
|
||||
|
@ -51,8 +68,11 @@ function parseServiceStatus(token) {
|
|||
return (j);
|
||||
}
|
||||
|
||||
function serviceManager() {
|
||||
if (process.platform == 'win32') {
|
||||
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');
|
||||
|
@ -78,21 +98,40 @@ function serviceManager() {
|
|||
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) {
|
||||
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 (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') && (this.GM.PointerSize == 4)) { return process.env['ProgramFiles(x86)']; } // 64 bit Windows with 32 Bit App
|
||||
return process.env['ProgramFiles']; // All other cases: 32 bit Windows or 64 bit App
|
||||
};
|
||||
this.getServiceFolder = function getServiceFolder() {
|
||||
return getProgramFolder() + '\\Open Source\\MeshCmd';
|
||||
this.getServiceFolder = function getServiceFolder()
|
||||
{
|
||||
var destinationFolder = null;
|
||||
if (require('os').arch() == 'x64')
|
||||
{
|
||||
// 64 bit Windows
|
||||
if (this.GM.PointerSize == 4)
|
||||
{
|
||||
// 32 Bit App
|
||||
destinationFolder = process.env['ProgramFiles(x86)'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// 64 bit App
|
||||
destinationFolder = process.env['ProgramFiles'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 32 bit Windows
|
||||
destinationFolder = process.env['ProgramFiles'];
|
||||
}
|
||||
return (destinationFolder + '\\mesh');
|
||||
};
|
||||
|
||||
this.enumerateService = function () {
|
||||
|
@ -105,7 +144,9 @@ function serviceManager() {
|
|||
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'); }
|
||||
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);
|
||||
|
@ -131,7 +172,7 @@ function serviceManager() {
|
|||
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'); }
|
||||
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);
|
||||
|
@ -156,48 +197,51 @@ function serviceManager() {
|
|||
}
|
||||
}
|
||||
else {
|
||||
throw ('Cannot call ' + this.name + '.stop(), when current state is: ' + this.status.state);
|
||||
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);
|
||||
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 {
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
throw ('Could not find service: ' + name);
|
||||
throw ('could not find service: ' + name);
|
||||
}
|
||||
}
|
||||
this.installService = function installService(options) {
|
||||
if (process.platform == 'win32') {
|
||||
if (!this.isAdmin()) { throw ('Installing as Service, requires administrator permissions.'); }
|
||||
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.getProgramFolder() + '\\Open Source';
|
||||
if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); } // Create the "Open Source" folder
|
||||
folder += '\\MeshCmd';
|
||||
if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); } // Create the "MeshCmd" folder
|
||||
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';
|
||||
console.log('Installing to "' + options.servicePath + '"');
|
||||
|
||||
var servicePath = this.GM.CreateVariable('"' + options.servicePath + '"');
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
|
||||
if (handle.Val == 0) { throw ('Error opening SCManager'); }
|
||||
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':
|
||||
|
@ -235,11 +279,13 @@ function serviceManager() {
|
|||
this.proxy.CloseServiceHandle(handle);
|
||||
return (this.getService(options.name));
|
||||
}
|
||||
if (process.platform == 'linux') {
|
||||
switch (this.getServiceType()) {
|
||||
if(process.platform == 'linux')
|
||||
{
|
||||
switch (this.getServiceType())
|
||||
{
|
||||
case 'init':
|
||||
require('fs').copyFileSync(options.servicePath, '/etc/init.d/' + options.name);
|
||||
console.log('Copying ' + options.servicePath);
|
||||
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);
|
||||
|
@ -274,25 +320,40 @@ function serviceManager() {
|
|||
}
|
||||
}
|
||||
}
|
||||
this.uninstallService = function uninstallService(name) {
|
||||
this.uninstallService = function uninstallService(name)
|
||||
{
|
||||
if (typeof (name) == 'object') { name = name.name; }
|
||||
if (process.platform == 'win32') {
|
||||
if (!this.isAdmin()) { throw ('Uninstalling a service, requires administrator permissions.'); }
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Uninstalling a service, requires admin'); }
|
||||
|
||||
var service = this.getService(name);
|
||||
if (service.status.state == undefined || service.status.state == 'STOPPED') {
|
||||
if (this.proxy.DeleteService(service._service) == 0) {
|
||||
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
|
||||
{
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync(this.getServiceFolder() + '\\' + name + '.exe');
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
throw ('Cannot uninstall service: ' + name + ', because it is: ' + service.status.state);
|
||||
}
|
||||
}
|
||||
else if (process.platform == 'linux') {
|
||||
switch (this.getServiceType()) {
|
||||
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._svcname = name;
|
||||
|
@ -300,7 +361,11 @@ function serviceManager() {
|
|||
try {
|
||||
require('fs').unlinkSync('/etc/init.d/' + this._svcname);
|
||||
console.log(this._svcname + ' uninstalled');
|
||||
} catch (e) { console.log(this._svcname + ' could not be uninstalled'); }
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
console.log(this._svcname + ' could not be uninstalled')
|
||||
}
|
||||
process.exit();
|
||||
});
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
|
@ -316,7 +381,10 @@ function serviceManager() {
|
|||
require('fs').unlinkSync('/usr/local/mesh/' + this._svcname);
|
||||
require('fs').unlinkSync('/lib/systemd/system/' + this._svcname + '.service');
|
||||
console.log(this._svcname + ' uninstalled');
|
||||
} catch (e) { console.log(this._svcname + ' could not be uninstalled'); }
|
||||
}
|
||||
catch (e) {
|
||||
console.log(this._svcname + ' could not be uninstalled')
|
||||
}
|
||||
process.exit();
|
||||
});
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
|
@ -329,9 +397,11 @@ function serviceManager() {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (process.platform == 'linux') {
|
||||
this.getServiceType = function getServiceType() {
|
||||
return (require('processManager').getProcessInfo(1).Name);
|
||||
if(process.platform == 'linux')
|
||||
{
|
||||
this.getServiceType = function getServiceType()
|
||||
{
|
||||
return (require('process-manager').getProcessInfo(1).Name);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -16,9 +16,27 @@ limitations under the License.
|
|||
|
||||
function UserSessions()
|
||||
{
|
||||
this._ObjectID = 'UserSessions';
|
||||
this._ObjectID = 'user-sessions';
|
||||
require('events').EventEmitter.call(this, true).createEvent('changed');
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
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);
|
||||
};
|
||||
this.Current(p.__handler);
|
||||
return (p);
|
||||
}
|
||||
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this._marshal = require('_GenericMarshal');
|
||||
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||
this._kernel32.CreateMethod('GetLastError');
|
||||
|
@ -77,7 +95,7 @@ function UserSessions()
|
|||
return (retVal);
|
||||
};
|
||||
|
||||
this.Current = function Current()
|
||||
this.Current = function Current(cb)
|
||||
{
|
||||
var retVal = {};
|
||||
var pinfo = this._marshal.CreatePointer();
|
||||
|
@ -102,36 +120,152 @@ function UserSessions()
|
|||
|
||||
this._wts.WTSFreeMemory(pinfo.Deref());
|
||||
|
||||
Object.defineProperty(retVal, 'connected', { value: showActiveOnly(retVal) });
|
||||
Object.defineProperty(retVal, 'Active', { value: showActiveOnly(retVal) });
|
||||
if (cb) { cb(retVal); }
|
||||
return (retVal);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Current = function Current()
|
||||
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 = {};
|
||||
var emitterUtils = require('events').inherits(retVal);
|
||||
emitterUtils.createEvent('logon');
|
||||
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 = 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])
|
||||
{
|
||||
console.log(getTokens(lines[i]));
|
||||
var user = lines[i].substring(0, lines[i].indexOf(' '));
|
||||
sessions.push(user);
|
||||
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();
|
||||
console.log(sessions);
|
||||
|
||||
|
||||
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(); });
|
||||
|
@ -145,7 +279,7 @@ function showActiveOnly(source)
|
|||
var retVal = [];
|
||||
for (var i in source)
|
||||
{
|
||||
if (source[i].State == 'Active' || source[i].State == 'Connected')
|
||||
if (source[i].State == 'Active')
|
||||
{
|
||||
retVal.push(source[i]);
|
||||
}
|
||||
|
@ -159,8 +293,13 @@ function getTokens(str)
|
|||
|
||||
columns.push(str.substring(0, (i=str.indexOf(' '))));
|
||||
while (str[++i] == ' ');
|
||||
columns.push(str.substring(i, str.substring(i).indexOf(' ') + 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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue