1
0
Fork 0
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:
Ylian Saint-Hilaire 2018-08-29 18:47:22 -07:00
parent c531b64643
commit 1b3255e844
35 changed files with 7423 additions and 177 deletions

View file

@ -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');
}

View file

@ -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);
};
}
}

View file

@ -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);
}