mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-03-09 15:40:18 +00:00
New MeshAgents, lots of bug fixes.
This commit is contained in:
parent
3d14cf220d
commit
8dcd8938a6
32 changed files with 547 additions and 133 deletions
|
@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var MemoryStream = require('MemoryStream');
|
||||
var lme_id = 0; // Our next channel identifier
|
||||
var lme_port_offset = 0; // Debug: Set this to "-100" to bind to 16892 & 16893 and IN_ADDRANY. This is for LMS debugging.
|
||||
|
@ -38,6 +37,7 @@ var APF_CHANNEL_DATA = 94;
|
|||
var APF_CHANNEL_CLOSE = 97;
|
||||
var APF_PROTOCOLVERSION = 192;
|
||||
|
||||
|
||||
function lme_object() {
|
||||
this.ourId = ++lme_id;
|
||||
this.amtId = -1;
|
||||
|
@ -266,7 +266,7 @@ function lme_heci(options) {
|
|||
this.sockets[rChannelId].bufferedStream.emit('readable');
|
||||
}
|
||||
} else {
|
||||
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST');
|
||||
console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST');
|
||||
}
|
||||
break;
|
||||
case APF_CHANNEL_DATA:
|
||||
|
@ -379,14 +379,16 @@ function lme_heci(options) {
|
|||
buffer.writeUInt32BE(0xFFFFFFFF, 13); // Reserved
|
||||
this.write(buffer);
|
||||
|
||||
//var buffer = Buffer.alloc(17);
|
||||
//buffer.writeUInt8(APF_CHANNEL_OPEN_FAILURE, 0);
|
||||
//buffer.writeUInt32BE(channelSender, 1); // Intel AMT sender channel
|
||||
//buffer.writeUInt32BE(2, 5); // Reason code
|
||||
//buffer.writeUInt32BE(0, 9); // Reserved
|
||||
//buffer.writeUInt32BE(0, 13); // Reserved
|
||||
//this.write(buffer);
|
||||
//console.log('Sent APF_CHANNEL_OPEN_FAILURE', channelSender);
|
||||
/*
|
||||
var buffer = Buffer.alloc(17);
|
||||
buffer.writeUInt8(APF_CHANNEL_OPEN_FAILURE, 0);
|
||||
buffer.writeUInt32BE(channelSender, 1); // Intel AMT sender channel
|
||||
buffer.writeUInt32BE(2, 5); // Reason code
|
||||
buffer.writeUInt32BE(0, 9); // Reserved
|
||||
buffer.writeUInt32BE(0, 13); // Reserved
|
||||
this.write(buffer);
|
||||
console.log('Sent APF_CHANNEL_OPEN_FAILURE', channelSender);
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/)
|
|||
obj.FailAllError = 0; // Set this to non-zero to fail all AJAX calls with that error status, 999 causes responses to be silent.
|
||||
obj.digest = null;
|
||||
obj.RequestCount = 0;
|
||||
obj.requests = {};
|
||||
|
||||
if (arguments.length == 1 && typeof(arguments[0] == 'object'))
|
||||
{
|
||||
|
@ -90,12 +89,9 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/)
|
|||
}
|
||||
var request = { protocol: (obj.tls == 1 ? 'https:' : 'http:'), method: 'POST', host: obj.host, path: '/wsman', port: obj.port, rejectUnauthorized: false, checkServerIdentity: function (cert) { console.log('checkServerIdentity', JSON.stringify(cert)); } };
|
||||
var req = obj.digest.request(request);
|
||||
req.reqid = obj.RequestCount++;
|
||||
obj.requests[req.reqid] = req; // Keep a reference to the request object so it does not get disposed.
|
||||
//console.log('Request ' + (obj.RequestCount++));
|
||||
req.on('error', function (e) { delete obj.requests[this.reqid]; obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); });
|
||||
req.on('error', function (e) { obj.gotNextMessagesError({ status: 600 }, 'error', null, [postdata, callback, tag]); });
|
||||
req.on('response', function (response) {
|
||||
response.reqid = this.reqid;
|
||||
//console.log('Response: ' + response.statusCode);
|
||||
if (response.statusCode != 200) {
|
||||
//console.log('ERR:' + JSON.stringify(response));
|
||||
|
@ -103,7 +99,7 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/)
|
|||
} else {
|
||||
response.acc = '';
|
||||
response.on('data', function (data2) { this.acc += data2; });
|
||||
response.on('end', function () { delete obj.requests[this.reqid]; obj.gotNextMessages(response.acc, 'success', { status: response.statusCode }, [postdata, callback, tag]); });
|
||||
response.on('end', function () { obj.gotNextMessages(response.acc, 'success', { status: response.statusCode }, [postdata, callback, tag]); });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
try { Object.defineProperty(Array.prototype, "peek", { value: function () { return (this.length > 0 ? this[this.length - 1] : undefined); } }); } catch (e) { }
|
||||
|
||||
|
||||
// Parse XML and return JSON
|
||||
module.exports.ParseWsman = function (xml) {
|
||||
try {
|
||||
|
@ -36,7 +39,7 @@ module.exports.ParseWsman = function (xml) {
|
|||
}
|
||||
return r;
|
||||
} catch (e) {
|
||||
console.log("Unable to parse XML: " + xml);
|
||||
console.error("Unable to parse XML: " + xml, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +106,6 @@ function _PutObjToBodyXml(resuri, putObj) {
|
|||
}
|
||||
|
||||
// This is a drop-in replacement to _turnToXml() that works without xml parser dependency.
|
||||
try { Object.defineProperty(Array.prototype, "peek", { value: function () { return (this.length > 0 ? this[this.length - 1] : null); } }); } catch (ex) { }
|
||||
function _treeBuilder() {
|
||||
this.tree = [];
|
||||
this.push = function (element) { this.tree.push(element); };
|
||||
|
|
|
@ -202,9 +202,6 @@ function AmtStackCreateService(wsmanStack) {
|
|||
obj.AMT_AgentPresenceWatchdog_RegisterAgent = function (callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "RegisterAgent", {}, callback_func, tag, pri, selectors); }
|
||||
obj.AMT_AgentPresenceWatchdog_AssertPresence = function (SequenceNumber, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertPresence", { "SequenceNumber": SequenceNumber }, callback_func, tag, pri, selectors); }
|
||||
obj.AMT_AgentPresenceWatchdog_AssertShutdown = function (SequenceNumber, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertShutdown", { "SequenceNumber": SequenceNumber }, callback_func, tag, pri, selectors); }
|
||||
//obj.AMT_AgentPresenceWatchdog_RegisterAgent = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "RegisterAgent", {}, callback_func); }
|
||||
//obj.AMT_AgentPresenceWatchdog_AssertPresence = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertPresence", { "SequenceNumber": SequenceNumber }, callback_func); }
|
||||
//obj.AMT_AgentPresenceWatchdog_AssertShutdown = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertShutdown", { "SequenceNumber": SequenceNumber }, callback_func); }
|
||||
obj.AMT_AgentPresenceWatchdog_AddAction = function (OldState, NewState, EventOnTransition, ActionSd, ActionEac, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AddAction", { "OldState": OldState, "NewState": NewState, "EventOnTransition": EventOnTransition, "ActionSd": ActionSd, "ActionEac": ActionEac }, callback_func, tag, pri, selectors); }
|
||||
obj.AMT_AgentPresenceWatchdog_DeleteAllActions = function (callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "DeleteAllActions", {}, callback_func, tag, pri, selectors); }
|
||||
obj.AMT_AgentPresenceWatchdogAction_GetActionEac = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdogAction", "GetActionEac", {}, callback_func); }
|
||||
|
@ -264,7 +261,7 @@ function AmtStackCreateService(wsmanStack) {
|
|||
obj.AMT_MessageLog_FreezeLog = function (Freeze, callback_func) { obj.Exec("AMT_MessageLog", "FreezeLog", { "Freeze": Freeze }, callback_func); }
|
||||
obj.AMT_PublicKeyManagementService_AddCRL = function (Url, SerialNumbers, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddCRL", { "Url": Url, "SerialNumbers": SerialNumbers }, callback_func); }
|
||||
obj.AMT_PublicKeyManagementService_ResetCRLList = function (_method_dummy, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "ResetCRLList", { "_method_dummy": _method_dummy }, callback_func); }
|
||||
obj.AMT_PublicKeyManagementService_AddCertificate = function (CertificateBlob, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddCertificate", { "CertificateBlob": CertificateBlob }, callback_func); }
|
||||
obj.AMT_PublicKeyManagementService_AddCertificate = function (CertificateBlob, callback_func, tag) { obj.Exec("AMT_PublicKeyManagementService", "AddCertificate", { "CertificateBlob": CertificateBlob }, callback_func, tag); }
|
||||
obj.AMT_PublicKeyManagementService_AddTrustedRootCertificate = function (CertificateBlob, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddTrustedRootCertificate", { "CertificateBlob": CertificateBlob }, callback_func); }
|
||||
obj.AMT_PublicKeyManagementService_AddKey = function (KeyBlob, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddKey", { "KeyBlob": KeyBlob }, callback_func); }
|
||||
obj.AMT_PublicKeyManagementService_GeneratePKCS10Request = function (KeyPair, DNName, Usage, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "GeneratePKCS10Request", { "KeyPair": KeyPair, "DNName": DNName, "Usage": Usage }, callback_func); }
|
||||
|
@ -275,7 +272,7 @@ function AmtStackCreateService(wsmanStack) {
|
|||
obj.AMT_RemoteAccessService_AddMpServer = function (AccessInfo, InfoFormat, Port, AuthMethod, Certificate, Username, Password, CN, callback_func) { obj.Exec("AMT_RemoteAccessService", "AddMpServer", { "AccessInfo": AccessInfo, "InfoFormat": InfoFormat, "Port": Port, "AuthMethod": AuthMethod, "Certificate": Certificate, "Username": Username, "Password": Password, "CN": CN }, callback_func); }
|
||||
obj.AMT_RemoteAccessService_AddRemoteAccessPolicyRule = function (Trigger, TunnelLifeTime, ExtendedData, MpServer, callback_func) { obj.Exec("AMT_RemoteAccessService", "AddRemoteAccessPolicyRule", { "Trigger": Trigger, "TunnelLifeTime": TunnelLifeTime, "ExtendedData": ExtendedData, "MpServer": MpServer }, callback_func); }
|
||||
obj.AMT_RemoteAccessService_CloseRemoteAccessConnection = function (_method_dummy, callback_func) { obj.Exec("AMT_RemoteAccessService", "CloseRemoteAccessConnection", { "_method_dummy": _method_dummy }, callback_func); }
|
||||
obj.AMT_SetupAndConfigurationService_CommitChanges = function (_method_dummy, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "CommitChanges", { "_method_dummy": _method_dummy }, callback_func); }
|
||||
obj.AMT_SetupAndConfigurationService_CommitChanges = function (_method_dummy, callback_func, tag) { obj.Exec("AMT_SetupAndConfigurationService", "CommitChanges", { "_method_dummy": _method_dummy }, callback_func, tag); }
|
||||
obj.AMT_SetupAndConfigurationService_Unprovision = function (ProvisioningMode, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "Unprovision", { "ProvisioningMode": ProvisioningMode }, callback_func); }
|
||||
obj.AMT_SetupAndConfigurationService_PartialUnprovision = function (_method_dummy, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "PartialUnprovision", { "_method_dummy": _method_dummy }, callback_func); }
|
||||
obj.AMT_SetupAndConfigurationService_ResetFlashWearOutProtection = function (_method_dummy, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "ResetFlashWearOutProtection", { "_method_dummy": _method_dummy }, callback_func); }
|
||||
|
@ -292,6 +289,7 @@ function AmtStackCreateService(wsmanStack) {
|
|||
obj.AMT_SystemPowerScheme_SetPowerScheme = function (callback_func, schemeInstanceId, tag) { obj.Exec("AMT_SystemPowerScheme", "SetPowerScheme", {}, callback_func, tag, 0, { "InstanceID": schemeInstanceId }); }
|
||||
obj.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch = function (callback_func, tag) { obj.Exec("AMT_TimeSynchronizationService", "GetLowAccuracyTimeSynch", {}, callback_func, tag); }
|
||||
obj.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch = function (Ta0, Tm1, Tm2, callback_func, tag) { obj.Exec("AMT_TimeSynchronizationService", "SetHighAccuracyTimeSynch", { "Ta0": Ta0, "Tm1": Tm1, "Tm2": Tm2 }, callback_func, tag); }
|
||||
obj.AMT_TLSCredentialContext_Create = function AMT_TLSCredentialContext_Create(ElementInContext, ElementProvidingContext, callback_func, tag) { obj.Create("AMT_TLSCredentialContext", { "ElementInContext": ElementInContext, "ElementProvidingContext": ElementProvidingContext }, callback_func, tag); }
|
||||
obj.AMT_UserInitiatedConnectionService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("AMT_UserInitiatedConnectionService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
|
||||
obj.AMT_WebUIService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func, tag) { obj.Exec("AMT_WebUIService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func, tag); }
|
||||
obj.AMT_WiFiPortConfigurationService_AddWiFiSettings = function (WiFiEndpoint, WiFiEndpointSettingsInput, IEEE8021xSettingsInput, ClientCredential, CACredential, callback_func) { obj.ExecWithXml("AMT_WiFiPortConfigurationService", "AddWiFiSettings", { "WiFiEndpoint": WiFiEndpoint, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, callback_func); }
|
||||
|
@ -765,18 +763,18 @@ function AmtStackCreateService(wsmanStack) {
|
|||
x['Initiator'] = 'KVM Default Port';
|
||||
ptr = 5;
|
||||
}
|
||||
|
||||
|
||||
// Read timestamp
|
||||
TimeStamp = ReadInt(e, ptr);
|
||||
x['Time'] = new Date((TimeStamp + (t.getTimezoneOffset() * 60)) * 1000);
|
||||
ptr += 4;
|
||||
|
||||
|
||||
// Read network access
|
||||
x['MCLocationType'] = e[ptr++];
|
||||
var netlen = e[ptr++];
|
||||
|
||||
x['NetAddress'] = e.slice(ptr, ptr + netlen).toString();
|
||||
|
||||
|
||||
// Read extended data
|
||||
ptr += netlen;
|
||||
var exlen = e[ptr++];
|
||||
|
@ -990,7 +988,7 @@ function AmtStackCreateService(wsmanStack) {
|
|||
// Convert a byte array of SID into string
|
||||
function GetSidString(sid) {
|
||||
var r = "S-" + sid.charCodeAt(0) + "-" + sid.charCodeAt(7);
|
||||
for (var i = 2; i < (sid.length / 4) ; i++) r += "-" + ReadIntX(sid, i * 4);
|
||||
for (var i = 2; i < (sid.length / 4); i++) r += "-" + ReadIntX(sid, i * 4);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ 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
|
||||
|
@ -21,7 +22,8 @@ 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) {
|
||||
switch (process.platform)
|
||||
{
|
||||
case 'win32':
|
||||
this._kernel32 = GM.CreateNativeProxy('kernel32.dll');
|
||||
this._kernel32.CreateMethod('GetLastError');
|
||||
|
@ -30,17 +32,26 @@ function processManager() {
|
|||
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: // This is not a supported platform.
|
||||
this.getProcesses = function getProcesses(callback)
|
||||
{
|
||||
switch(process.platform)
|
||||
{
|
||||
default:
|
||||
throw ('Enumerating processes on ' + process.platform + ' not supported');
|
||||
break;
|
||||
case 'win32': // Windows processes
|
||||
|
@ -49,8 +60,9 @@ function processManager() {
|
|||
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)] = { cmd: info.Deref(GM.PointerSize == 4 ? 36 : 44, 260).String };
|
||||
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]); }
|
||||
|
@ -64,40 +76,80 @@ function processManager() {
|
|||
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];
|
||||
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) {
|
||||
for (var i in lines)
|
||||
{
|
||||
var tokens = lines[i].split(' ');
|
||||
var tokenList = [];
|
||||
for (var x in tokens) {
|
||||
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 && tokens[x]) { tokenList.push(tokens[x]);}
|
||||
}
|
||||
if (i > 0) {
|
||||
if (tokenList[key.PID]) { retVal[tokenList[key.PID]] = { user: tokenList[key.USER], cmd: tokenList[key.COMMAND] }; }
|
||||
if (tokenList[key.PID]) { retVal[tokenList[key.PID]] = { pid: key.PID, user: tokenList[key.USER], cmd: tokenList[key.COMMAND] }; }
|
||||
}
|
||||
}
|
||||
if (this.callback) {
|
||||
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) {
|
||||
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 = {}, lines = status.toString().split('\n');
|
||||
for (var i in lines) {
|
||||
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];
|
||||
|
|
|
@ -16,10 +16,32 @@ limitations under the License.
|
|||
|
||||
var refTable = {};
|
||||
|
||||
function event_switcher_helper(desired_callee, target)
|
||||
{
|
||||
this._ObjectID = 'event_switcher';
|
||||
this.func = function func()
|
||||
{
|
||||
var args = [];
|
||||
for(var i in arguments)
|
||||
{
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
return (func.target.apply(func.desired, args));
|
||||
};
|
||||
this.func.desired = desired_callee;
|
||||
this.func.target = target;
|
||||
this.func.self = this;
|
||||
}
|
||||
function event_switcher(desired_callee, target)
|
||||
{
|
||||
return (new event_switcher_helper(desired_callee, target));
|
||||
}
|
||||
|
||||
function Promise(promiseFunc)
|
||||
{
|
||||
this._ObjectID = 'promise';
|
||||
this._internal = { promise: this, func: promiseFunc, completed: false, errors: false, completedArgs: [] };
|
||||
this.promise = this;
|
||||
this._internal = { _ObjectID: 'promise.internal', promise: this, func: promiseFunc, completed: false, errors: false, completedArgs: [] };
|
||||
require('events').EventEmitter.call(this._internal);
|
||||
this._internal.on('_eventHook', function (eventName, eventCallback)
|
||||
{
|
||||
|
@ -82,21 +104,21 @@ function Promise(promiseFunc)
|
|||
};
|
||||
this.catch = function(func)
|
||||
{
|
||||
this._internal.once('settled', func);
|
||||
this._internal.once('rejected', event_switcher(this, func).func);
|
||||
}
|
||||
this.finally = function (func)
|
||||
{
|
||||
this._internal.once('settled', func);
|
||||
this._internal.once('settled', event_switcher(this, func).func);
|
||||
};
|
||||
this.then = function (resolved, rejected)
|
||||
{
|
||||
if (resolved) { this._internal.once('resolved', resolved); }
|
||||
if (rejected) { this._internal.once('rejected', rejected); }
|
||||
if (resolved) { this._internal.once('resolved', event_switcher(this, resolved).func); }
|
||||
if (rejected) { this._internal.once('rejected', event_switcher(this, rejected).func); }
|
||||
|
||||
var retVal = new Promise(function (r, j) { });
|
||||
|
||||
this._internal.once('resolved', retVal._internal.resolver);
|
||||
this._internal.once('rejected', retVal._internal.rejector);
|
||||
retVal.parentPromise = this;
|
||||
return (retVal);
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,18 @@ var RSMB = 1381190978;
|
|||
var memoryLocation = { 0x1: 'Other', 0x2: 'Unknown', 0x3: 'System Board', 0x4: 'ISA', 0x5: 'EISA', 0x6: 'PCI', 0x7: 'MCA', 0x8: 'PCMCIA', 0x9: 'Proprietary', 0xA: 'NuBus', 0xA0: 'PC-98/C20', 0xA1: 'PC-98/C24', 0xA2: 'PC-98/E', 0xA3: 'PC-98/LB' };
|
||||
var wakeReason = ['Reserved', 'Other', 'Unknown', 'APM Timer', 'Modem Ring', 'LAN', 'Power Switch', 'PCI', 'AC Power'];
|
||||
|
||||
function SMBiosTables() {
|
||||
// Fill the left with zeros until the string is of a given length
|
||||
function zeroLeftPad(str, len)
|
||||
{
|
||||
if ((len == null) && (typeof (len) != 'number')) { return null; }
|
||||
if (str == null) str = ''; // If null, this is to generate zero leftpad string
|
||||
var zlp = '';
|
||||
for (var i = 0; i < len - str.length; i++) { zlp += '0'; }
|
||||
return zlp + str;
|
||||
}
|
||||
|
||||
function SMBiosTables()
|
||||
{
|
||||
this._ObjectID = 'SMBiosTable';
|
||||
if (process.platform == 'win32') {
|
||||
this._marshal = require('_GenericMarshal');
|
||||
|
@ -181,12 +192,21 @@ function SMBiosTables() {
|
|||
}
|
||||
return (retVal);
|
||||
};
|
||||
this.systemInfo = function systemInfo(data) {
|
||||
this.systemInfo = function systemInfo(data)
|
||||
{
|
||||
if (!data) { throw ('no data'); }
|
||||
var retVal = { _ObjectID: 'SMBiosTables.systemInfo' };
|
||||
if (data[1]) {
|
||||
if (data[1])
|
||||
{
|
||||
var si = data[1].peek();
|
||||
retVal.uuid = si.slice(4, 20).toString('hex');
|
||||
var uuid = si.slice(4, 20);
|
||||
|
||||
retVal.uuid = [zeroLeftPad(uuid.readUInt32LE(0).toString(16), 8),
|
||||
zeroLeftPad(uuid.readUInt16LE(4).toString(16), 4),
|
||||
zeroLeftPad(uuid.readUInt16LE(6).toString(16), 4),
|
||||
zeroLeftPad(uuid.readUInt16BE(8).toString(16), 4),
|
||||
zeroLeftPad(uuid.slice(10).toString('hex').toLowerCase(), 12)].join('-');
|
||||
|
||||
retVal.wakeReason = wakeReason[si[20]];
|
||||
}
|
||||
return (retVal);
|
||||
|
|
|
@ -17,6 +17,13 @@ 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);
|
||||
|
@ -29,6 +36,10 @@ 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';
|
||||
|
@ -49,7 +60,15 @@ function UserSessions()
|
|||
{
|
||||
p.__resolver(users);
|
||||
};
|
||||
this.Current(p.__handler);
|
||||
try
|
||||
{
|
||||
this.Current(p.__handler);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
p.__rejector(e);
|
||||
}
|
||||
p.parent = this;
|
||||
return (p);
|
||||
}
|
||||
|
||||
|
@ -65,6 +84,29 @@ function UserSessions()
|
|||
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
||||
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
||||
this._wts.CreateMethod('WTSFreeMemory');
|
||||
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
|
||||
this._user32.CreateMethod('RegisterPowerSettingNotification');
|
||||
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 =
|
||||
{
|
||||
|
@ -146,45 +188,112 @@ function UserSessions()
|
|||
return (retVal);
|
||||
};
|
||||
|
||||
this._immediate = setImmediate(function (self)
|
||||
{
|
||||
if (self._serviceHooked) { return; } // If we were hooked by a service, we won't need to do anything further
|
||||
|
||||
// We need to spin up a message pump, and fetch a window handle
|
||||
var message_pump = require('win-message-pump');
|
||||
self._messagepump = new message_pump({ filter: WM_WTSSESSION_CHANGE });
|
||||
self._messagepump.on('exit', function (code) { self._wts.WTSUnRegisterSessionNotification(self.hwnd); });
|
||||
self._messagepump.on('hwnd', function (h)
|
||||
// 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;
|
||||
|
||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||
this.parent._wts.WTSRegisterSessionNotification(this.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
||||
//this.parent._user32.ACDC_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
||||
//this.parent._user32.BATT_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
||||
//this.parent._user32.DISP_H = this.parent._user32.RegisterPowerSettingNotification(this.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0); // Windows 8+ only, THIS WILL BLOCK ON WIN7
|
||||
});
|
||||
this._messagepump.on('message', function (msg)
|
||||
{
|
||||
switch(msg.message)
|
||||
{
|
||||
self.hwnd = h;
|
||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||
self._wts.WTSRegisterSessionNotification(self.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
||||
});
|
||||
self._messagepump.on('message', function (msg)
|
||||
{
|
||||
if (msg.message == WM_WTSSESSION_CHANGE)
|
||||
{
|
||||
case WM_WTSSESSION_CHANGE:
|
||||
switch(msg.wparam)
|
||||
{
|
||||
case WTS_SESSION_LOCK:
|
||||
self.enumerateUsers().then(function (users)
|
||||
this.parent.enumerateUsers().then(function (users)
|
||||
{
|
||||
if (users[msg.lparam]) { self.emit('locked', users[msg.lparam]); }
|
||||
if (users[msg.lparam]) { this.parent.emit('locked', users[msg.lparam]); }
|
||||
});
|
||||
break;
|
||||
case WTS_SESSION_UNLOCK:
|
||||
self.enumerateUsers().then(function (users)
|
||||
this.parent.enumerateUsers().then(function (users)
|
||||
{
|
||||
if (users[msg.lparam]) { self.emit('unlocked', users[msg.lparam]); }
|
||||
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;
|
||||
}
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
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
|
||||
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)
|
||||
|
@ -336,6 +445,112 @@ function UserSessions()
|
|||
|
||||
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._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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
function showActiveOnly(source)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue