mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-14 07:13:37 +00:00
243 lines
9.8 KiB
JavaScript
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; |