1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-14 07:13:37 +00:00
Files
MeshAgent/Debug/serviceManager.js
2018-01-12 11:50:04 -08:00

243 lines
9.8 KiB
JavaScript

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).IntVal)
{
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).IntVal
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).IntVal
return (j);
}
function serviceManager()
{
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.proxy2 = this.GM.CreateNativeProxy('Kernel32.dll');
this.proxy2.CreateMethod('GetLastError');
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.CreateVariable(4);
var servicesReturned = this.GM.CreateVariable(4);
var resumeHandle = this.GM.CreateVariable(4);
//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, 'PtrSize = ' + dbName._size);
var ptrSize = dbName._size;
var blockSize = 36 + (2 * ptrSize);
console.log('blockSize', blockSize);
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 == 0) { throw ('could not open ServiceManager'); }
var h = this.proxy.OpenServiceA(handle, serviceName, 0x0004 | 0x0020 | 0x0010 | 0x00010000);
if (h != 0)
{
var success = this.proxy.QueryServiceStatusEx(h, 0, 0, 0, bytesNeeded);
var status = this.GM.CreateVariable(bytesNeeded.IntVal);
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);
}
this.installService = function(options)
{
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
if (handle == 0) { throw ('error opening SCManager'); }
var serviceName = this.GM.CreateVariable(options.name);
var displayName = this.GM.CreateVariable(options.displayName);
var allAccess = 0x000F01FF;
var serviceType;
var servicePath = this.GM.CreateVariable(options.servicePath);
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 == 0) { this.proxy.CloseServiceHandle(handle); throw ('Error Creating Service'); }
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));
}
this.uninstallService = function(name)
{
var service = this.getService(name);
if(service.status.state == 'STOPPED')
{
if (this.proxy.DeleteService(service._service) == 0) { throw ('Uninstall Service for: ' + name + ', failed with error: ' + this.proxy2.GetLastError()); }
}
else
{
throw ('Cannot uninstall service: ' + name + ', because it is: ' + service.status.state);
}
}
}
module.exports = serviceManager;