improves Windows terminal support.

This commit is contained in:
Ylian Saint-Hilaire 2018-12-15 16:17:46 -08:00
parent 52053fbabd
commit 286ee89f36
3 changed files with 183 additions and 244 deletions

View File

@ -54,6 +54,7 @@
<Compile Include="agents\modules_meshcore\win-console.js" />
<Compile Include="agents\modules_meshcore\win-message-pump.js" />
<Compile Include="agents\modules_meshcore\win-registry.js" />
<Compile Include="agents\modules_meshcore\win-terminal.js" />
<Compile Include="agents\testsuite.js" />
<Compile Include="agents\tinycore.js" />
<Compile Include="amtevents.js" />

View File

@ -46,8 +46,7 @@ si.Deref(GM.PointerSize == 4 ? 44 : 60, 4).toBuffer().writeUInt32LE(STARTF_USESH
var MSG = GM.CreateVariable(GM.PointerSize == 4 ? 28 : 48);
function windows_terminal()
{
function windows_terminal() {
this._ObjectID = 'windows_terminal';
this._user32 = GM.CreateNativeProxy('User32.dll');
this._user32.CreateMethod('DispatchMessageA');
@ -60,7 +59,7 @@ function windows_terminal()
this._user32.CreateMethod('UnhookWinEvent');
this._user32.CreateMethod('VkKeyScanA');
this._user32.terminal = this;
this._kernel32 = GM.CreateNativeProxy('Kernel32.dll');
this._kernel32.CreateMethod('AllocConsole');
this._kernel32.CreateMethod('CreateProcessA');
@ -79,137 +78,119 @@ function windows_terminal()
this._kernel32.CreateMethod('TerminateProcess');
this._kernel32.CreateMethod('WaitForSingleObject');
this._kernel32.CreateMethod('WriteConsoleInputA');
var currentX = 0;
var currentY = 0;
this._scrx = 0;
this._scry = 0;
this.SendCursorUpdate = function()
{
var newCsbi = GM.CreateVariable(22);
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, newCsbi).Val == 0) { return; }
if (newCsbi.Deref(4,2).toBuffer().readUInt16LE() != this.currentX || newCsbi.Deref(6,2).toBuffer().readUInt16LE() != this.currentY)
{
this.SendCursorUpdate = function () {
var newCsbi = GM.CreateVariable(22);
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, newCsbi).Val == 0) { return; }
if (newCsbi.Deref(4, 2).toBuffer().readUInt16LE() != this.currentX || newCsbi.Deref(6, 2).toBuffer().readUInt16LE() != this.currentY) {
//wchar_t mywbuf[512];
//swprintf(mywbuf, 512, TEXT("csbi.dwCursorPosition.X = %d, csbi.dwCursorPosition.Y = %d, newCsbi.dwCursorPosition.X = %d, newCsbi.dwCursorPosition.Y = %d\r\n"), csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y, newCsbi.dwCursorPosition.X, newCsbi.dwCursorPosition.Y);
//OutputDebugString(mywbuf);
//m_viewOffset = newCsbi.srWindow.Top;
//WriteMoveCursor((SerialAgent *)this->sa, (char)(newCsbi.dwCursorPosition.Y - m_viewOffset), (char)(newCsbi.dwCursorPosition.X - m_viewOffset));
//LowStackSendData((SerialAgent *)(this->sa), "", 0);
this.currentX = newCsbi.Deref(4,2).toBuffer().readUInt16LE();
this.currentY = newCsbi.Deref(6,2).toBuffer().readUInt16LE();
this.currentX = newCsbi.Deref(4, 2).toBuffer().readUInt16LE();
this.currentY = newCsbi.Deref(6, 2).toBuffer().readUInt16LE();
}
}
this.ClearScreen = function()
{
var CONSOLE_SCREEN_BUFFER_INFO = GM.CreateVariable(22);
this.ClearScreen = function () {
var CONSOLE_SCREEN_BUFFER_INFO = GM.CreateVariable(22);
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO).Val == 0) { return; }
var coordScreen = GM.CreateVariable(4);
var dwConSize = CONSOLE_SCREEN_BUFFER_INFO.Deref(0,2).toBuffer().readUInt16LE(0) * CONSOLE_SCREEN_BUFFER_INFO.Deref(2,2).toBuffer().readUInt16LE(0);
var dwConSize = CONSOLE_SCREEN_BUFFER_INFO.Deref(0, 2).toBuffer().readUInt16LE(0) * CONSOLE_SCREEN_BUFFER_INFO.Deref(2, 2).toBuffer().readUInt16LE(0);
var cCharsWritten = GM.CreateVariable(4);
// Fill the entire screen with blanks.
if (this._kernel32.FillConsoleOutputCharacterA(this._stdoutput, 32, dwConSize, coordScreen.Deref(0,4).toBuffer().readUInt32LE(), cCharsWritten).Val == 0) { return; }
if (this._kernel32.FillConsoleOutputCharacterA(this._stdoutput, 32, dwConSize, coordScreen.Deref(0, 4).toBuffer().readUInt32LE(), cCharsWritten).Val == 0) { return; }
// Get the current text attribute.
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO).Val == 0) { return; }
// Set the buffer's attributes accordingly.
if (this._kernel32.FillConsoleOutputAttribute(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO.Deref(8, 2).toBuffer().readUInt16LE(0), dwConSize, coordScreen.Deref(0, 4).toBuffer().readUInt32LE(), cCharsWritten).Val == 0) { return; }
// Put the cursor at its home coordinates.
this._kernel32.SetConsoleCursorPosition(this._stdoutput, coordScreen.Deref(0, 4).toBuffer().readUInt32LE());
// Put the window to top-left.
var rect = GM.CreateVariable(8);
var srWindow = CONSOLE_SCREEN_BUFFER_INFO.Deref(10,8).toBuffer();
rect.Deref(4,2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(4) - srWindow.readUInt16LE(0));
rect.Deref(6,2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(6) - srWindow.readUInt16LE(2));
var srWindow = CONSOLE_SCREEN_BUFFER_INFO.Deref(10, 8).toBuffer();
rect.Deref(4, 2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(4) - srWindow.readUInt16LE(0));
rect.Deref(6, 2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(6) - srWindow.readUInt16LE(2));
this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect);
}
this.Start = function Start(CONSOLE_SCREEN_WIDTH, CONSOLE_SCREEN_HEIGHT)
{
if(this._kernel32.GetConsoleWindow().Val == 0)
{
if(this._kernel32.AllocConsole().Val == 0)
{
this.Start = function Start(CONSOLE_SCREEN_WIDTH, CONSOLE_SCREEN_HEIGHT) {
if (this._kernel32.GetConsoleWindow().Val == 0) {
if (this._kernel32.AllocConsole().Val == 0) {
throw ('AllocConsole failed with: ' + this._kernel32.GetLastError().Val);
}
}
this._stdinput = this._kernel32.GetStdHandle(STD_INPUT_HANDLE);
this._stdoutput = this._kernel32.GetStdHandle(STD_OUTPUT_HANDLE);
this._connected = false;
var coordScreen = GM.CreateVariable(4);
coordScreen.Deref(0, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_WIDTH);
coordScreen.Deref(2, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_HEIGHT);
var rect = GM.CreateVariable(8);
rect.Deref(4, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_WIDTH - 1);
rect.Deref(6, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_HEIGHT - 1);
if(this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect).Val == 0)
{
if (this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect).Val == 0) {
throw ('Failed to set Console Screen Size');
}
if(this._kernel32.SetConsoleScreenBufferSize(this._stdoutput, coordScreen.Deref(0,4).toBuffer().readUInt32LE()).Val == 0)
{
if (this._kernel32.SetConsoleScreenBufferSize(this._stdoutput, coordScreen.Deref(0, 4).toBuffer().readUInt32LE()).Val == 0) {
throw ('Failed to set Console Buffer Size');
}
this.ClearScreen();
this._hookThread().then(function ()
{
this._hookThread().then(function () {
// Hook Ready
this.terminal.StartCommand();
}, console.log);
this._stream = new duplex({
'write': function (chunk, flush)
{
if (!this.terminal.connected)
{
'write': function (chunk, flush) {
if (!this.terminal.connected) {
//console.log('_write: ' + chunk);
if (!this._promise.chunk)
{
if (!this._promise.chunk) {
this._promise.chunk = [];
}
if (typeof (chunk) == 'string')
{
if (typeof (chunk) == 'string') {
this._promise.chunk.push(chunk);
}
else
{
} else {
this._promise.chunk.push(Buffer.alloc(chunk.length));
chunk.copy(this._promise.chunk.peek());
}
this._promise.chunk.peek().flush = flush;
this._promise.then(function ()
{
this._promise.then(function () {
var buf;
while(this.chunk.length > 0)
{
while (this.chunk.length > 0) {
buf = this.chunk.shift();
this.terminal._WriteBuffer(buf);
buf.flush();
}
});
}
else
{
else {
//console.log('writeNOW: ' + chunk);
this.terminal._WriteBuffer(chunk);
flush();
}
},
'final': function (flush)
{
'final': function (flush) {
var p = this.terminal._stop();
p.__flush = flush;
p.then(function () { this.__flush(); });
@ -220,19 +201,17 @@ function windows_terminal()
this._stream._promise.terminal = this;
return (this._stream);
};
this._stop = function()
{
this._stop = function () {
if (this.stopping) { return (this.stopping); }
console.log('Stopping Terminal...');
this.stopping = new promise(function (res, rej) { this._res = res; this._rej = rej; });
var threadID = this._kernel32.GetThreadId(this._user32.SetWinEventHook.async.thread()).Val;
this._user32.PostThreadMessageA(threadID, WM_QUIT, 0, 0);
return (this.stopping);
}
this._hookThread = function ()
{
this._hookThread = function () {
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
ret.terminal = this;
this._ConsoleWinEventProc = GM.GetGenericGlobalCallback(7);
@ -240,44 +219,37 @@ function windows_terminal()
var p = this._user32.SetWinEventHook.async(EVENT_CONSOLE_CARET, EVENT_CONSOLE_END_APPLICATION, 0, this._ConsoleWinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
p.ready = ret;
p.terminal = this;
p.then(function (hwinEventHook)
{
if (hwinEventHook.Val == 0)
{
p.then(function (hwinEventHook) {
if (hwinEventHook.Val == 0) {
this.ready._rej('Error calling SetWinEventHook');
}
else
{
} else {
this.terminal.hwinEventHook = hwinEventHook;
this.ready._res();
this.terminal._GetMessage();
}
});
this._ConsoleWinEventProc.on('GlobalCallback', function (hhook, dwEvent, hwnd, idObject, idChild, idEventThread, swmsEventTime)
{
this._ConsoleWinEventProc.on('GlobalCallback', function (hhook, dwEvent, hwnd, idObject, idChild, idEventThread, swmsEventTime) {
if (!this.terminal.hwinEventHook || this.terminal.hwinEventHook.Val != hhook.Val) { return; }
var buffer = null;
switch (dwEvent.Val)
{
switch (dwEvent.Val) {
case EVENT_CONSOLE_CARET:
break;
case EVENT_CONSOLE_UPDATE_REGION:
if (!this.terminal.connected)
{
this.terminal.connected = true; this.terminal._stream._promise._res();
if (!this.terminal.connected) {
this.terminal.connected = true;
this.terminal._stream._promise._res();
}
if (this.terminal._scrollTimer == null)
{
if (this.terminal._scrollTimer == null) {
buffer = this.terminal._GetScreenBuffer(LOWORD(idObject.Val), HIWORD(idObject.Val), LOWORD(idChild.Val), HIWORD(idChild.Val));
//console.log('UPDATE REGION: [Left: ' + LOWORD(idObject.Val) + ' Top: ' + HIWORD(idObject.Val) + ' Right: ' + LOWORD(idChild.Val) + ' Bottom: ' + HIWORD(idChild.Val) + ']');
this.terminal._SendDataBuffer(buffer);
}
break;
case EVENT_CONSOLE_UPDATE_SIMPLE:
//console.log('UPDATE SIMPLE: [X: ' + LOWORD(idObject.Val) + ' Y: ' + HIWORD(idObject.Val) + ' Char: ' + LOWORD(idChild.Val) + ' Attr: ' + HIWORD(idChild.Val) + ']');
var simplebuffer = { data: [Buffer.alloc(1, LOWORD(idChild.Val))], attributes: [HIWORD(idChild.Val)], width: 1, height: 1, x: LOWORD(idObject.Val)+1, y: HIWORD(idObject.Val) };
var simplebuffer = { data: [Buffer.alloc(1, LOWORD(idChild.Val))], attributes: [HIWORD(idChild.Val)], width: 1, height: 1, x: LOWORD(idObject.Val) + 1, y: HIWORD(idObject.Val) };
this.terminal._SendDataBuffer(simplebuffer);
break;
case EVENT_CONSOLE_UPDATE_SCROLL:
@ -295,8 +267,7 @@ function windows_terminal()
//SendConsoleEvent(dwEvent, idObject, idChild);
break;
case EVENT_CONSOLE_END_APPLICATION:
if(idObject.Val == this.terminal._hProcessID)
{
if (idObject.Val == this.terminal._hProcessID) {
//console.log('END APPLICATION: [PID: ' + idObject.Val + ' CID: ' + idChild.Val + ']');
this.terminal._stop().then(function () { console.log('STOPPED'); });
}
@ -313,219 +284,172 @@ function windows_terminal()
});
return (ret);
}
this._GetMessage = function()
{
this._GetMessage = function () {
if (this._user32.abort) { console.log('aborting loop'); return; }
this._user32.GetMessageA.async(this._user32.SetWinEventHook.async, MSG, 0, 0, 0).then(function (ret)
{
this._user32.GetMessageA.async(this._user32.SetWinEventHook.async, MSG, 0, 0, 0).then(function (ret) {
//console.log('GetMessage Response');
if(ret.Val != 0)
{
if (ret.Val == -1)
{
if (ret.Val != 0) {
if (ret.Val == -1) {
// handle the error and possibly exit
}
else
{
} else {
//console.log('TranslateMessage');
this.nativeProxy._user32.TranslateMessage.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function ()
{
this.nativeProxy._user32.TranslateMessage.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function () {
//console.log('DispatchMessage');
this.nativeProxy._user32.DispatchMessageA.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function ()
{
this.nativeProxy._user32.DispatchMessageA.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function () {
this.nativeProxy.terminal._GetMessage();
}, console.log);
}, console.log);
}
}
else
{
} else {
this.nativeProxy.UnhookWinEvent.async(this.nativeProxy.terminal._user32.SetWinEventHook.async, this.nativeProxy.terminal.hwinEventHook)
.then(function ()
{
this.nativeProxy.terminal.stopping._res();
if(this.nativeProxy.terminal._kernel32.TerminateProcess(this.nativeProxy.terminal._hProcess, 1067).Val == 0)
{
var e = this.nativeProxy.terminal._kernel32.GetLastError().Val;
console.log('Unable to kill Terminal Process, error: ' + e);
}
this.nativeProxy.terminal.stopping = null;
}, function (err)
{
console.log('REJECTED_UnhookWinEvent: ' + err);
});
.then(function () {
this.nativeProxy.terminal.stopping._res();
if (this.nativeProxy.terminal._kernel32.TerminateProcess(this.nativeProxy.terminal._hProcess, 1067).Val == 0) {
var e = this.nativeProxy.terminal._kernel32.GetLastError().Val;
console.log('Unable to kill Terminal Process, error: ' + e);
}
this.nativeProxy.terminal.stopping = null;
}, function (err) {
console.log('REJECTED_UnhookWinEvent: ' + err);
});
}
}, function (err)
{
}, function (err) {
// Get Message Failed
console.log('REJECTED_GETMessage: ' + err);
});
}
this._WriteBuffer = function(buf)
{
for (var i = 0; i < buf.length; ++i)
{
if (typeof (buf) == 'string')
{
this._WriteBuffer = function (buf) {
for (var i = 0; i < buf.length; ++i) {
if (typeof (buf) == 'string') {
this._WriteCharacter(buf.charCodeAt(i), false);
}
else
{
} else {
this._WriteCharacter(buf[i], false);
}
}
}
this._WriteCharacter = function(key, bControlKey)
{
this._WriteCharacter = function (key, bControlKey) {
var rec = GM.CreateVariable(20);
rec.Deref(0,2).toBuffer().writeUInt16LE(KEY_EVENT); // rec.EventType
rec.Deref(4,4).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.bKeyDown
rec.Deref(0, 2).toBuffer().writeUInt16LE(KEY_EVENT); // rec.EventType
rec.Deref(4, 4).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.bKeyDown
rec.Deref(16, 4).toBuffer().writeUInt32LE(bControlKey); // rec.Event.KeyEvent.dwControlKeyState
rec.Deref(14, 1).toBuffer()[0] = key; // rec.Event.KeyEvent.uChar.AsciiChar
rec.Deref(8, 2).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.wRepeatCount
rec.Deref(10, 2).toBuffer().writeUInt16LE(this._user32.VkKeyScanA(key).Val); // rec.Event.KeyEvent.wVirtualKeyCode
rec.Deref(12, 2).toBuffer().writeUInt16LE(this._user32.MapVirtualKeyA(this._user32.VkKeyScanA(key).Val, MAPVK_VK_TO_VSC).Val);
var dwWritten = GM.CreateVariable(4);
if(this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val == 0) { return(false); }
rec.Deref(4,4).toBuffer().writeUInt16LE(0); // rec.Event.KeyEvent.bKeyDown
return(this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val != 0);
if (this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val == 0) { return (false); }
rec.Deref(4, 4).toBuffer().writeUInt16LE(0); // rec.Event.KeyEvent.bKeyDown
return (this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val != 0);
}
this._GetScreenBuffer = function(sx, sy, ex, ey)
{
this._GetScreenBuffer = function (sx, sy, ex, ey) {
// get the current visible screen buffer
var info = GM.CreateVariable(22);
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw('Error getting screen buffer info'); }
var nWidth = info.Deref(14,2).toBuffer().readUInt16LE() - info.Deref(10,2).toBuffer().readUInt16LE() + 1;
var nHeight = info.Deref(16,2).toBuffer().readUInt16LE() - info.Deref(12,2).toBuffer().readUInt16LE() + 1;
if (arguments[3] == null)
{
var info = GM.CreateVariable(22);
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw ('Error getting screen buffer info'); }
var nWidth = info.Deref(14, 2).toBuffer().readUInt16LE() - info.Deref(10, 2).toBuffer().readUInt16LE() + 1;
var nHeight = info.Deref(16, 2).toBuffer().readUInt16LE() - info.Deref(12, 2).toBuffer().readUInt16LE() + 1;
if (arguments[3] == null) {
// Use Default Parameters
sx = 0;
sy = 0;
ex = nWidth-1;
ey = nHeight-1;
}
else
{
if(this._scrx != 0)
{
sx += this._scrx;
ex += this._scrx;
}
if(this._scry != 0)
{
sy += this._scry;
ey += this._scry;
}
ex = nWidth - 1;
ey = nHeight - 1;
} else {
if (this._scrx != 0) { sx += this._scrx; ex += this._scrx; }
if (this._scry != 0) { sy += this._scry; ey += this._scry; }
this._scrx = this._scry = 0;
}
var nBuffer = GM.CreateVariable((ex-sx+1) * (ey-sy+1) * 4);
var nBuffer = GM.CreateVariable((ex - sx + 1) * (ey - sy + 1) * 4);
var size = GM.CreateVariable(4);
size.Deref(0,2).toBuffer().writeUInt16LE(ex-sx+1, 0);
size.Deref(2, 2).toBuffer().writeUInt16LE(ey-sy+1, 0);
size.Deref(0, 2).toBuffer().writeUInt16LE(ex - sx + 1, 0);
size.Deref(2, 2).toBuffer().writeUInt16LE(ey - sy + 1, 0);
var startCoord = GM.CreateVariable(4);
startCoord.Deref(0, 2).toBuffer().writeUInt16LE(0, 0);
startCoord.Deref(2, 2).toBuffer().writeUInt16LE(0, 0);
var region = GM.CreateVariable(8);
region.buffer = region.toBuffer();
region.buffer.writeUInt16LE(sx, 0);
region.buffer.writeUInt16LE(sy, 2);
region.buffer.writeUInt16LE(ex, 4);
region.buffer.writeUInt16LE(ey, 6);
if (this._kernel32.ReadConsoleOutputA(this._stdoutput, nBuffer, size.Deref(0, 4).toBuffer().readUInt32LE(), startCoord.Deref(0, 4).toBuffer().readUInt32LE(), region).Val == 0)
{
throw('Unable to read Console Output');
if (this._kernel32.ReadConsoleOutputA(this._stdoutput, nBuffer, size.Deref(0, 4).toBuffer().readUInt32LE(), startCoord.Deref(0, 4).toBuffer().readUInt32LE(), region).Val == 0) {
throw ('Unable to read Console Output');
}
// Lets convert the buffer into something simpler
//var retVal = { data: Buffer.alloc((dw - dx + 1) * (dh - dy + 1)), attributes: Buffer.alloc((dw - dx + 1) * (dh - dy + 1)), width: dw - dx + 1, height: dh - dy + 1, x: dx, y: dy };
var retVal = { data: [], attributes: [], width: ex - sx + 1, height: ey - sy + 1, x: sx, y: sy };
var x, y, line, ifo;
var tmp;
var lineWidth = ex - sx + 1;
for (y = 0; y <= (ey - sy) ; ++y)
{
var x, y, line, ifo, tmp, lineWidth = ex - sx + 1;
for (y = 0; y <= (ey - sy) ; ++y) {
retVal.data.push(Buffer.alloc(lineWidth));
retVal.attributes.push(Buffer.alloc(lineWidth));
line = nBuffer.Deref(y * lineWidth * 4, lineWidth * 4).toBuffer();
for(x = 0; x < lineWidth; ++x)
{
for (x = 0; x < lineWidth; ++x) {
retVal.data.peek()[x] = line[x * 4];
retVal.attributes.peek()[x] = line[2 + (x * 4)];
}
}
return (retVal);
}
this._SendDataBuffer = function(data)
{
this._SendDataBuffer = function (data) {
// { data, attributes, width, height, x, y }
var dy, line, attr;
for(dy = 0; dy < data.height; ++dy)
{
for (dy = 0; dy < data.height; ++dy) {
line = data.data[dy];
attr = data.attributes[dy];
line.s = line.toString();
//line = data.data.slice(data.width * dy, (data.width * dy) + data.width);
//attr = data.attributes.slice(data.width * dy, (data.width * dy) + data.width);
this._stream.push(TranslateLine(data.x, data.y + dy, line, attr));
}
}
this._SendScroll = function _SendScroll(dx, dy)
{
if (this._scrollTimer)
{
return;
this._stream.push(TranslateLine(data.x, data.y + dy + 1, line, attr));
}
}
this._SendScroll = function _SendScroll(dx, dy) {
if (this._scrollTimer) { return; }
var info = GM.CreateVariable(22);
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw ('Error getting screen buffer info'); }
var nWidth = info.Deref(14, 2).toBuffer().readUInt16LE() - info.Deref(10, 2).toBuffer().readUInt16LE() + 1;
var nHeight = info.Deref(16, 2).toBuffer().readUInt16LE() - info.Deref(12, 2).toBuffer().readUInt16LE() + 1;
this._stream.push(GetEsc('H', nHeight-1, 0));
for (var i = 0; i > nHeight; ++i)
{
this._stream.push(Buffer.from('\r\n'));
}
this._stream.push(GetEsc('H', [nHeight - 1, 0]));
for (var i = 0; i > nHeight; ++i) { this._stream.push(Buffer.from('\r\n')); }
var buffer = this._GetScreenBuffer(0, 0, nWidth - 1, nHeight - 1);
this._SendDataBuffer(buffer);
this._scrollTimer = setTimeout(function (self, nw, nh)
{
this._scrollTimer = setTimeout(function (self, nw, nh) {
var buffer = self._GetScreenBuffer(0, 0, nw - 1, nh - 1);
self._SendDataBuffer(buffer);
self._scrollTimer = null;
}, 250, this, nWidth, nHeight);
}
this.StartCommand = function StartCommand()
{
if(this._kernel32.CreateProcessA(GM.CreateVariable(process.env['windir'] + '\\system32\\cmd.exe'), 0, 0, 0, 1, CREATE_NEW_PROCESS_GROUP, 0, 0, si, pi).Val == 0)
{
this.StartCommand = function StartCommand() {
if (this._kernel32.CreateProcessA(GM.CreateVariable(process.env['windir'] + '\\system32\\cmd.exe'), 0, 0, 0, 1, CREATE_NEW_PROCESS_GROUP, 0, 0, si, pi).Val == 0) {
console.log('Error Spawning CMD');
return;
}
this._kernel32.CloseHandle(pi.Deref(GM.PointerSize, GM.PointerSize).Deref()); // pi.hThread
this._hProcess = pi.Deref(0, GM.PointerSize).Deref(); // pi.hProcess
this._hProcessID = pi.Deref(GM.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE(); // pi.dwProcessId
@ -533,23 +457,37 @@ function windows_terminal()
}
}
function LOWORD(val)
{
return (val & 0xFFFF);
}
function HIWORD(val)
{
return ((val >> 16) & 0xFFFF);
function LOWORD(val) { return (val & 0xFFFF); }
function HIWORD(val) { return ((val >> 16) & 0xFFFF); }
function GetEsc(op, args) { return (Buffer.from('\x1B[' + args.join(';') + op)); }
//function MeshConsole(msg) { require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": JSON.stringify(msg) }); }
function TranslateLine(x, y, data, attributes) {
var i, fcolor, bcolor, rcolor, fbright, bbright, lastAttr, fc, bc, rc, fb, bb, esc = [], output = [GetEsc('H', [y, x])];
if (typeof attributes == 'number') { attributes = [ attributes ]; } // If we get a single attribute, turn it into an array.
for (i = 0; i < data.length; i++) {
if (lastAttr != attributes[i]) { // To boost performance, if the attribute is the same as the last one, skip this entire part.
fc = (attributes[i] & 0x0007);
fc = ((fc & 0x0001) << 2) + (fc & 0x0002) + ((fc & 0x0004) >> 2); // Foreground color
bc = (attributes[i] & 0x0070) >> 4;
bc = ((bc & 0x0001) << 2) + (bc & 0x0002) + ((bc & 0x0004) >> 2); // Background color
rc = (attributes[i] & 0x4000); // Reverse color set
fb = (attributes[i] & 0x0008) >> 3; // Bright foreground set
bb = (attributes[i] & 0x0080); // Bright background set
if (rc != rcolor) { if (rc != 0) { esc.push(7); } else { esc.push(0); fcolor = 7; bcolor = 0; fbright = 0; bbright = 0; } rcolor = rc; } // Reverse Color
if (fc != fcolor) { esc.push(fc + 30); fcolor = fc; } // Set the foreground color if needed
if (bc != bcolor) { esc.push(bc + 40); bcolor = bc; } // Set the background color if needed
if (fb != fbright) { esc.push(2 - fb); fbright = fb; } // Set the bright foreground color if needed
if (bb != bbright) { if (bb == 0) { esc.push(bcolor + 40); } else { esc.push(bcolor + 100); bbright = bb; } } // Set bright Background color if needed
if (esc.length > 0) { output.push(GetEsc('m', esc)); esc = []; }
lastAttr = attributes[i];
}
output.push(Buffer.from(String.fromCharCode(data[i])));
}
return Buffer.concat(output);
}
function GetEsc(CodeCharStr, arg1, arg2)
{
return (Buffer.from('\x1B[' + arg1 + ';' + arg2 + CodeCharStr));
//return (Buffer.from('*[' + arg1 + ';' + arg2 + CodeCharStr));
}
function TranslateLine(x, y, data, attributes)
{
return (Buffer.concat([GetEsc('H', y, x), data]));
}
module.exports = new windows_terminal();

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.2.4-n",
"version": "0.2.4-p",
"keywords": [
"Remote Management",
"Intel AMT",