improves Windows terminal support.
Ylian Saint-Hilaire committed
Dec 15, 2018 at 16:17 UTC
286ee89f363049b1de94384a495fac0ad2d1eddd
3 files changed
+183
-244
MeshCentralServer.njsproj
+1
@@ -54,6 +54,7 @@
54
<Compile Include="agents\modules_meshcore\win-console.js" />
55
<Compile Include="agents\modules_meshcore\win-message-pump.js" />
56
<Compile Include="agents\modules_meshcore\win-registry.js" />
57
+ <Compile Include="agents\modules_meshcore\win-terminal.js" />
58
<Compile Include="agents\testsuite.js" />
59
<Compile Include="agents\tinycore.js" />
60
<Compile Include="amtevents.js" />
agents/modules_meshcore/win-terminal.js
+181
-243
@@ -46,8 +46,7 @@ si.Deref(GM.PointerSize == 4 ? 44 : 60, 4).toBuffer().writeUInt32LE(STARTF_USESH
46
47
var MSG = GM.CreateVariable(GM.PointerSize == 4 ? 28 : 48);
48
49
-function windows_terminal()
50
-{
49
+function windows_terminal() {
50
this._ObjectID = 'windows_terminal';
51
this._user32 = GM.CreateNativeProxy('User32.dll');
52
this._user32.CreateMethod('DispatchMessageA');
@@ -60,7 +59,7 @@ function windows_terminal()
59
this._user32.CreateMethod('UnhookWinEvent');
60
this._user32.CreateMethod('VkKeyScanA');
61
this._user32.terminal = this;
63
-
62
+
63
this._kernel32 = GM.CreateNativeProxy('Kernel32.dll');
64
this._kernel32.CreateMethod('AllocConsole');
65
this._kernel32.CreateMethod('CreateProcessA');
@@ -79,137 +78,119 @@ function windows_terminal()
78
this._kernel32.CreateMethod('TerminateProcess');
79
this._kernel32.CreateMethod('WaitForSingleObject');
80
this._kernel32.CreateMethod('WriteConsoleInputA');
82
-
81
+
82
var currentX = 0;
83
var currentY = 0;
85
-
84
+
85
this._scrx = 0;
86
this._scry = 0;
88
-
89
- this.SendCursorUpdate = function()
90
- {
91
- var newCsbi = GM.CreateVariable(22);
92
-
93
- if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, newCsbi).Val == 0) { return; }
94
- if (newCsbi.Deref(4,2).toBuffer().readUInt16LE() != this.currentX || newCsbi.Deref(6,2).toBuffer().readUInt16LE() != this.currentY)
95
- {
87
+
88
+ this.SendCursorUpdate = function () {
89
+ var newCsbi = GM.CreateVariable(22);
90
+
91
+ if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, newCsbi).Val == 0) { return; }
92
+ if (newCsbi.Deref(4, 2).toBuffer().readUInt16LE() != this.currentX || newCsbi.Deref(6, 2).toBuffer().readUInt16LE() != this.currentY) {
93
//wchar_t mywbuf[512];
94
//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);
95
//OutputDebugString(mywbuf);
99
-
96
+
97
//m_viewOffset = newCsbi.srWindow.Top;
98
//WriteMoveCursor((SerialAgent *)this->sa, (char)(newCsbi.dwCursorPosition.Y - m_viewOffset), (char)(newCsbi.dwCursorPosition.X - m_viewOffset));
99
//LowStackSendData((SerialAgent *)(this->sa), "", 0);
103
-
104
- this.currentX = newCsbi.Deref(4,2).toBuffer().readUInt16LE();
105
- this.currentY = newCsbi.Deref(6,2).toBuffer().readUInt16LE();
100
+
101
+ this.currentX = newCsbi.Deref(4, 2).toBuffer().readUInt16LE();
102
+ this.currentY = newCsbi.Deref(6, 2).toBuffer().readUInt16LE();
103
}
104
}
108
- this.ClearScreen = function()
109
- {
110
- var CONSOLE_SCREEN_BUFFER_INFO = GM.CreateVariable(22);
111
- if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO).Val == 0) { return; }
105
106
+ this.ClearScreen = function () {
107
+ var CONSOLE_SCREEN_BUFFER_INFO = GM.CreateVariable(22);
108
+ if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO).Val == 0) { return; }
109
+
110
var coordScreen = GM.CreateVariable(4);
114
- var dwConSize = CONSOLE_SCREEN_BUFFER_INFO.Deref(0,2).toBuffer().readUInt16LE(0) * CONSOLE_SCREEN_BUFFER_INFO.Deref(2,2).toBuffer().readUInt16LE(0);
111
+ var dwConSize = CONSOLE_SCREEN_BUFFER_INFO.Deref(0, 2).toBuffer().readUInt16LE(0) * CONSOLE_SCREEN_BUFFER_INFO.Deref(2, 2).toBuffer().readUInt16LE(0);
112
var cCharsWritten = GM.CreateVariable(4);
116
-
113
+
114
// Fill the entire screen with blanks.
118
- if (this._kernel32.FillConsoleOutputCharacterA(this._stdoutput, 32, dwConSize, coordScreen.Deref(0,4).toBuffer().readUInt32LE(), cCharsWritten).Val == 0) { return; }
115
+ if (this._kernel32.FillConsoleOutputCharacterA(this._stdoutput, 32, dwConSize, coordScreen.Deref(0, 4).toBuffer().readUInt32LE(), cCharsWritten).Val == 0) { return; }
116
117
// Get the current text attribute.
118
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, CONSOLE_SCREEN_BUFFER_INFO).Val == 0) { return; }
122
-
119
+
120
// Set the buffer's attributes accordingly.
121
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; }
125
-
122
+
123
// Put the cursor at its home coordinates.
124
this._kernel32.SetConsoleCursorPosition(this._stdoutput, coordScreen.Deref(0, 4).toBuffer().readUInt32LE());
128
-
125
+
126
// Put the window to top-left.
127
var rect = GM.CreateVariable(8);
131
- var srWindow = CONSOLE_SCREEN_BUFFER_INFO.Deref(10,8).toBuffer();
132
- rect.Deref(4,2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(4) - srWindow.readUInt16LE(0));
133
- rect.Deref(6,2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(6) - srWindow.readUInt16LE(2));
134
-
128
+ var srWindow = CONSOLE_SCREEN_BUFFER_INFO.Deref(10, 8).toBuffer();
129
+ rect.Deref(4, 2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(4) - srWindow.readUInt16LE(0));
130
+ rect.Deref(6, 2).toBuffer().writeUInt16LE(srWindow.readUInt16LE(6) - srWindow.readUInt16LE(2));
131
+
132
this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect);
133
}
137
-
138
- this.Start = function Start(CONSOLE_SCREEN_WIDTH, CONSOLE_SCREEN_HEIGHT)
139
- {
140
- if(this._kernel32.GetConsoleWindow().Val == 0)
141
- {
142
- if(this._kernel32.AllocConsole().Val == 0)
143
- {
134
+
135
+ this.Start = function Start(CONSOLE_SCREEN_WIDTH, CONSOLE_SCREEN_HEIGHT) {
136
+ if (this._kernel32.GetConsoleWindow().Val == 0) {
137
+ if (this._kernel32.AllocConsole().Val == 0) {
138
throw ('AllocConsole failed with: ' + this._kernel32.GetLastError().Val);
139
}
140
}
147
-
141
+
142
this._stdinput = this._kernel32.GetStdHandle(STD_INPUT_HANDLE);
143
this._stdoutput = this._kernel32.GetStdHandle(STD_OUTPUT_HANDLE);
144
this._connected = false;
145
var coordScreen = GM.CreateVariable(4);
146
coordScreen.Deref(0, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_WIDTH);
147
coordScreen.Deref(2, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_HEIGHT);
154
-
148
+
149
var rect = GM.CreateVariable(8);
150
rect.Deref(4, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_WIDTH - 1);
151
rect.Deref(6, 2).toBuffer().writeUInt16LE(CONSOLE_SCREEN_HEIGHT - 1);
158
-
159
- if(this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect).Val == 0)
160
- {
152
+
153
+ if (this._kernel32.SetConsoleWindowInfo(this._stdoutput, 1, rect).Val == 0) {
154
throw ('Failed to set Console Screen Size');
155
}
163
- if(this._kernel32.SetConsoleScreenBufferSize(this._stdoutput, coordScreen.Deref(0,4).toBuffer().readUInt32LE()).Val == 0)
164
- {
156
+ if (this._kernel32.SetConsoleScreenBufferSize(this._stdoutput, coordScreen.Deref(0, 4).toBuffer().readUInt32LE()).Val == 0) {
157
throw ('Failed to set Console Buffer Size');
158
}
159
this.ClearScreen();
168
- this._hookThread().then(function ()
169
- {
160
+ this._hookThread().then(function () {
161
// Hook Ready
162
this.terminal.StartCommand();
163
}, console.log);
164
this._stream = new duplex({
174
- 'write': function (chunk, flush)
175
- {
176
- if (!this.terminal.connected)
177
- {
165
+ 'write': function (chunk, flush) {
166
+ if (!this.terminal.connected) {
167
//console.log('_write: ' + chunk);
179
- if (!this._promise.chunk)
180
- {
168
+ if (!this._promise.chunk) {
169
this._promise.chunk = [];
170
}
183
- if (typeof (chunk) == 'string')
184
- {
171
+ if (typeof (chunk) == 'string') {
172
this._promise.chunk.push(chunk);
186
- }
187
- else
188
- {
173
+ } else {
174
this._promise.chunk.push(Buffer.alloc(chunk.length));
175
chunk.copy(this._promise.chunk.peek());
176
}
177
this._promise.chunk.peek().flush = flush;
193
- this._promise.then(function ()
194
- {
178
+ this._promise.then(function () {
179
var buf;
196
- while(this.chunk.length > 0)
197
- {
180
+ while (this.chunk.length > 0) {
181
buf = this.chunk.shift();
182
this.terminal._WriteBuffer(buf);
183
buf.flush();
184
}
185
});
186
}
204
- else
205
- {
187
+ else {
188
//console.log('writeNOW: ' + chunk);
189
this.terminal._WriteBuffer(chunk);
190
flush();
191
}
192
},
211
- 'final': function (flush)
212
- {
193
+ 'final': function (flush) {
194
var p = this.terminal._stop();
195
p.__flush = flush;
196
p.then(function () { this.__flush(); });
@@ -220,19 +201,17 @@ function windows_terminal()
201
this._stream._promise.terminal = this;
202
return (this._stream);
203
};
223
- this._stop = function()
224
- {
204
+ this._stop = function () {
205
if (this.stopping) { return (this.stopping); }
206
console.log('Stopping Terminal...');
207
this.stopping = new promise(function (res, rej) { this._res = res; this._rej = rej; });
228
-
208
+
209
var threadID = this._kernel32.GetThreadId(this._user32.SetWinEventHook.async.thread()).Val;
210
this._user32.PostThreadMessageA(threadID, WM_QUIT, 0, 0);
211
return (this.stopping);
212
}
233
-
234
- this._hookThread = function ()
235
- {
213
+
214
+ this._hookThread = function () {
215
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
216
ret.terminal = this;
217
this._ConsoleWinEventProc = GM.GetGenericGlobalCallback(7);
@@ -240,44 +219,37 @@ function windows_terminal()
219
var p = this._user32.SetWinEventHook.async(EVENT_CONSOLE_CARET, EVENT_CONSOLE_END_APPLICATION, 0, this._ConsoleWinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
220
p.ready = ret;
221
p.terminal = this;
243
- p.then(function (hwinEventHook)
244
- {
245
- if (hwinEventHook.Val == 0)
246
- {
222
+ p.then(function (hwinEventHook) {
223
+ if (hwinEventHook.Val == 0) {
224
this.ready._rej('Error calling SetWinEventHook');
248
- }
249
- else
250
- {
225
+ } else {
226
this.terminal.hwinEventHook = hwinEventHook;
227
this.ready._res();
228
this.terminal._GetMessage();
229
}
230
});
256
- this._ConsoleWinEventProc.on('GlobalCallback', function (hhook, dwEvent, hwnd, idObject, idChild, idEventThread, swmsEventTime)
257
- {
231
+
232
+ this._ConsoleWinEventProc.on('GlobalCallback', function (hhook, dwEvent, hwnd, idObject, idChild, idEventThread, swmsEventTime) {
233
if (!this.terminal.hwinEventHook || this.terminal.hwinEventHook.Val != hhook.Val) { return; }
234
var buffer = null;
260
-
261
- switch (dwEvent.Val)
262
- {
235
+
236
+ switch (dwEvent.Val) {
237
case EVENT_CONSOLE_CARET:
238
break;
239
case EVENT_CONSOLE_UPDATE_REGION:
266
- if (!this.terminal.connected)
267
- {
268
- this.terminal.connected = true; this.terminal._stream._promise._res();
240
+ if (!this.terminal.connected) {
241
+ this.terminal.connected = true;
242
+ this.terminal._stream._promise._res();
243
}
270
- if (this.terminal._scrollTimer == null)
271
- {
244
+ if (this.terminal._scrollTimer == null) {
245
buffer = this.terminal._GetScreenBuffer(LOWORD(idObject.Val), HIWORD(idObject.Val), LOWORD(idChild.Val), HIWORD(idChild.Val));
246
//console.log('UPDATE REGION: [Left: ' + LOWORD(idObject.Val) + ' Top: ' + HIWORD(idObject.Val) + ' Right: ' + LOWORD(idChild.Val) + ' Bottom: ' + HIWORD(idChild.Val) + ']');
274
-
247
this.terminal._SendDataBuffer(buffer);
248
}
249
break;
250
case EVENT_CONSOLE_UPDATE_SIMPLE:
251
//console.log('UPDATE SIMPLE: [X: ' + LOWORD(idObject.Val) + ' Y: ' + HIWORD(idObject.Val) + ' Char: ' + LOWORD(idChild.Val) + ' Attr: ' + HIWORD(idChild.Val) + ']');
280
- 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) };
252
+ 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) };
253
this.terminal._SendDataBuffer(simplebuffer);
254
break;
255
case EVENT_CONSOLE_UPDATE_SCROLL:
@@ -295,8 +267,7 @@ function windows_terminal()
267
//SendConsoleEvent(dwEvent, idObject, idChild);
268
break;
269
case EVENT_CONSOLE_END_APPLICATION:
298
- if(idObject.Val == this.terminal._hProcessID)
299
- {
270
+ if (idObject.Val == this.terminal._hProcessID) {
271
//console.log('END APPLICATION: [PID: ' + idObject.Val + ' CID: ' + idChild.Val + ']');
272
this.terminal._stop().then(function () { console.log('STOPPED'); });
273
}
@@ -313,219 +284,172 @@ function windows_terminal()
284
});
285
return (ret);
286
}
316
-
317
- this._GetMessage = function()
318
- {
287
+
288
+ this._GetMessage = function () {
289
if (this._user32.abort) { console.log('aborting loop'); return; }
320
- this._user32.GetMessageA.async(this._user32.SetWinEventHook.async, MSG, 0, 0, 0).then(function (ret)
321
- {
290
+ this._user32.GetMessageA.async(this._user32.SetWinEventHook.async, MSG, 0, 0, 0).then(function (ret) {
291
//console.log('GetMessage Response');
323
- if(ret.Val != 0)
324
- {
325
- if (ret.Val == -1)
326
- {
292
+ if (ret.Val != 0) {
293
+ if (ret.Val == -1) {
294
// handle the error and possibly exit
328
- }
329
- else
330
- {
295
+ } else {
296
//console.log('TranslateMessage');
332
- this.nativeProxy._user32.TranslateMessage.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function ()
333
- {
297
+ this.nativeProxy._user32.TranslateMessage.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function () {
298
//console.log('DispatchMessage');
335
- this.nativeProxy._user32.DispatchMessageA.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function ()
336
- {
299
+ this.nativeProxy._user32.DispatchMessageA.async(this.nativeProxy.user32.SetWinEventHook.async, MSG).then(function () {
300
this.nativeProxy.terminal._GetMessage();
301
}, console.log);
302
}, console.log);
303
}
341
- }
342
- else
343
- {
304
+ } else {
305
this.nativeProxy.UnhookWinEvent.async(this.nativeProxy.terminal._user32.SetWinEventHook.async, this.nativeProxy.terminal.hwinEventHook)
345
- .then(function ()
346
- {
347
- this.nativeProxy.terminal.stopping._res();
348
- if(this.nativeProxy.terminal._kernel32.TerminateProcess(this.nativeProxy.terminal._hProcess, 1067).Val == 0)
349
- {
350
- var e = this.nativeProxy.terminal._kernel32.GetLastError().Val;
351
- console.log('Unable to kill Terminal Process, error: ' + e);
352
- }
353
- this.nativeProxy.terminal.stopping = null;
354
- }, function (err)
355
- {
356
- console.log('REJECTED_UnhookWinEvent: ' + err);
357
- });
306
+ .then(function () {
307
+ this.nativeProxy.terminal.stopping._res();
308
+ if (this.nativeProxy.terminal._kernel32.TerminateProcess(this.nativeProxy.terminal._hProcess, 1067).Val == 0) {
309
+ var e = this.nativeProxy.terminal._kernel32.GetLastError().Val;
310
+ console.log('Unable to kill Terminal Process, error: ' + e);
311
+ }
312
+ this.nativeProxy.terminal.stopping = null;
313
+ }, function (err) {
314
+ console.log('REJECTED_UnhookWinEvent: ' + err);
315
+ });
316
}
359
- }, function (err)
360
- {
317
+ }, function (err) {
318
// Get Message Failed
319
console.log('REJECTED_GETMessage: ' + err);
320
});
321
}
365
- this._WriteBuffer = function(buf)
366
- {
367
- for (var i = 0; i < buf.length; ++i)
368
- {
369
- if (typeof (buf) == 'string')
370
- {
322
+ this._WriteBuffer = function (buf) {
323
+ for (var i = 0; i < buf.length; ++i) {
324
+ if (typeof (buf) == 'string') {
325
this._WriteCharacter(buf.charCodeAt(i), false);
372
- }
373
- else
374
- {
326
+ } else {
327
this._WriteCharacter(buf[i], false);
328
}
329
}
330
}
379
- this._WriteCharacter = function(key, bControlKey)
380
- {
331
+ this._WriteCharacter = function (key, bControlKey) {
332
var rec = GM.CreateVariable(20);
382
- rec.Deref(0,2).toBuffer().writeUInt16LE(KEY_EVENT); // rec.EventType
383
- rec.Deref(4,4).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.bKeyDown
333
+ rec.Deref(0, 2).toBuffer().writeUInt16LE(KEY_EVENT); // rec.EventType
334
+ rec.Deref(4, 4).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.bKeyDown
335
rec.Deref(16, 4).toBuffer().writeUInt32LE(bControlKey); // rec.Event.KeyEvent.dwControlKeyState
336
rec.Deref(14, 1).toBuffer()[0] = key; // rec.Event.KeyEvent.uChar.AsciiChar
337
rec.Deref(8, 2).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.wRepeatCount
338
rec.Deref(10, 2).toBuffer().writeUInt16LE(this._user32.VkKeyScanA(key).Val); // rec.Event.KeyEvent.wVirtualKeyCode
339
rec.Deref(12, 2).toBuffer().writeUInt16LE(this._user32.MapVirtualKeyA(this._user32.VkKeyScanA(key).Val, MAPVK_VK_TO_VSC).Val);
389
-
340
+
341
var dwWritten = GM.CreateVariable(4);
391
- if(this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val == 0) { return(false); }
392
-
393
- rec.Deref(4,4).toBuffer().writeUInt16LE(0); // rec.Event.KeyEvent.bKeyDown
394
- return(this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val != 0);
342
+ if (this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val == 0) { return (false); }
343
+
344
+ rec.Deref(4, 4).toBuffer().writeUInt16LE(0); // rec.Event.KeyEvent.bKeyDown
345
+ return (this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val != 0);
346
}
396
-
397
- this._GetScreenBuffer = function(sx, sy, ex, ey)
398
- {
347
+
348
+ this._GetScreenBuffer = function (sx, sy, ex, ey) {
349
// get the current visible screen buffer
400
-
401
- var info = GM.CreateVariable(22);
402
- if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw('Error getting screen buffer info'); }
403
-
404
- var nWidth = info.Deref(14,2).toBuffer().readUInt16LE() - info.Deref(10,2).toBuffer().readUInt16LE() + 1;
405
- var nHeight = info.Deref(16,2).toBuffer().readUInt16LE() - info.Deref(12,2).toBuffer().readUInt16LE() + 1;
406
-
407
- if (arguments[3] == null)
408
- {
350
+
351
+ var info = GM.CreateVariable(22);
352
+ if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw ('Error getting screen buffer info'); }
353
+
354
+ var nWidth = info.Deref(14, 2).toBuffer().readUInt16LE() - info.Deref(10, 2).toBuffer().readUInt16LE() + 1;
355
+ var nHeight = info.Deref(16, 2).toBuffer().readUInt16LE() - info.Deref(12, 2).toBuffer().readUInt16LE() + 1;
356
+
357
+ if (arguments[3] == null) {
358
// Use Default Parameters
359
sx = 0;
360
sy = 0;
412
- ex = nWidth-1;
413
- ey = nHeight-1;
414
- }
415
- else
416
- {
417
- if(this._scrx != 0)
418
- {
419
- sx += this._scrx;
420
- ex += this._scrx;
421
- }
422
- if(this._scry != 0)
423
- {
424
- sy += this._scry;
425
- ey += this._scry;
426
- }
361
+ ex = nWidth - 1;
362
+ ey = nHeight - 1;
363
+ } else {
364
+ if (this._scrx != 0) { sx += this._scrx; ex += this._scrx; }
365
+ if (this._scry != 0) { sy += this._scry; ey += this._scry; }
366
this._scrx = this._scry = 0;
367
}
429
-
430
-
431
- var nBuffer = GM.CreateVariable((ex-sx+1) * (ey-sy+1) * 4);
368
+
369
+
370
+ var nBuffer = GM.CreateVariable((ex - sx + 1) * (ey - sy + 1) * 4);
371
var size = GM.CreateVariable(4);
433
- size.Deref(0,2).toBuffer().writeUInt16LE(ex-sx+1, 0);
434
- size.Deref(2, 2).toBuffer().writeUInt16LE(ey-sy+1, 0);
435
-
372
+ size.Deref(0, 2).toBuffer().writeUInt16LE(ex - sx + 1, 0);
373
+ size.Deref(2, 2).toBuffer().writeUInt16LE(ey - sy + 1, 0);
374
+
375
var startCoord = GM.CreateVariable(4);
376
startCoord.Deref(0, 2).toBuffer().writeUInt16LE(0, 0);
377
startCoord.Deref(2, 2).toBuffer().writeUInt16LE(0, 0);
439
-
378
+
379
var region = GM.CreateVariable(8);
380
region.buffer = region.toBuffer();
381
region.buffer.writeUInt16LE(sx, 0);
382
region.buffer.writeUInt16LE(sy, 2);
383
region.buffer.writeUInt16LE(ex, 4);
384
region.buffer.writeUInt16LE(ey, 6);
446
-
447
- if (this._kernel32.ReadConsoleOutputA(this._stdoutput, nBuffer, size.Deref(0, 4).toBuffer().readUInt32LE(), startCoord.Deref(0, 4).toBuffer().readUInt32LE(), region).Val == 0)
448
- {
449
- throw('Unable to read Console Output');
385
+
386
+ if (this._kernel32.ReadConsoleOutputA(this._stdoutput, nBuffer, size.Deref(0, 4).toBuffer().readUInt32LE(), startCoord.Deref(0, 4).toBuffer().readUInt32LE(), region).Val == 0) {
387
+ throw ('Unable to read Console Output');
388
}
451
-
389
+
390
// Lets convert the buffer into something simpler
391
//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 };
454
-
392
+
393
var retVal = { data: [], attributes: [], width: ex - sx + 1, height: ey - sy + 1, x: sx, y: sy };
456
- var x, y, line, ifo;
457
- var tmp;
458
- var lineWidth = ex - sx + 1;
459
-
460
- for (y = 0; y <= (ey - sy) ; ++y)
461
- {
394
+ var x, y, line, ifo, tmp, lineWidth = ex - sx + 1;
395
+
396
+ for (y = 0; y <= (ey - sy) ; ++y) {
397
retVal.data.push(Buffer.alloc(lineWidth));
398
retVal.attributes.push(Buffer.alloc(lineWidth));
464
-
399
+
400
line = nBuffer.Deref(y * lineWidth * 4, lineWidth * 4).toBuffer();
466
- for(x = 0; x < lineWidth; ++x)
467
- {
401
+ for (x = 0; x < lineWidth; ++x) {
402
retVal.data.peek()[x] = line[x * 4];
403
retVal.attributes.peek()[x] = line[2 + (x * 4)];
404
}
405
}
472
-
406
+
407
return (retVal);
408
}
475
-
476
- this._SendDataBuffer = function(data)
477
- {
409
+
410
+ this._SendDataBuffer = function (data) {
411
// { data, attributes, width, height, x, y }
479
-
412
+
413
var dy, line, attr;
481
- for(dy = 0; dy < data.height; ++dy)
482
- {
414
+ for (dy = 0; dy < data.height; ++dy) {
415
line = data.data[dy];
416
attr = data.attributes[dy];
417
line.s = line.toString();
418
+
419
//line = data.data.slice(data.width * dy, (data.width * dy) + data.width);
420
//attr = data.attributes.slice(data.width * dy, (data.width * dy) + data.width);
488
- this._stream.push(TranslateLine(data.x, data.y + dy, line, attr));
489
- }
490
- }
491
- this._SendScroll = function _SendScroll(dx, dy)
492
- {
493
- if (this._scrollTimer)
494
- {
495
- return;
421
+ this._stream.push(TranslateLine(data.x, data.y + dy + 1, line, attr));
422
}
423
+ }
424
425
+ this._SendScroll = function _SendScroll(dx, dy) {
426
+ if (this._scrollTimer) { return; }
427
+
428
var info = GM.CreateVariable(22);
429
if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw ('Error getting screen buffer info'); }
500
-
430
+
431
var nWidth = info.Deref(14, 2).toBuffer().readUInt16LE() - info.Deref(10, 2).toBuffer().readUInt16LE() + 1;
432
var nHeight = info.Deref(16, 2).toBuffer().readUInt16LE() - info.Deref(12, 2).toBuffer().readUInt16LE() + 1;
503
-
504
- this._stream.push(GetEsc('H', nHeight-1, 0));
505
- for (var i = 0; i > nHeight; ++i)
506
- {
507
- this._stream.push(Buffer.from('\r\n'));
508
- }
509
-
433
+
434
+ this._stream.push(GetEsc('H', [nHeight - 1, 0]));
435
+ for (var i = 0; i > nHeight; ++i) { this._stream.push(Buffer.from('\r\n')); }
436
+
437
var buffer = this._GetScreenBuffer(0, 0, nWidth - 1, nHeight - 1);
438
this._SendDataBuffer(buffer);
512
-
513
- this._scrollTimer = setTimeout(function (self, nw, nh)
514
- {
439
+
440
+ this._scrollTimer = setTimeout(function (self, nw, nh) {
441
var buffer = self._GetScreenBuffer(0, 0, nw - 1, nh - 1);
442
self._SendDataBuffer(buffer);
443
self._scrollTimer = null;
444
}, 250, this, nWidth, nHeight);
445
}
520
-
521
- this.StartCommand = function StartCommand()
522
- {
523
- 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)
524
- {
446
+
447
+ this.StartCommand = function StartCommand() {
448
+ 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) {
449
console.log('Error Spawning CMD');
450
return;
451
}
528
-
452
+
453
this._kernel32.CloseHandle(pi.Deref(GM.PointerSize, GM.PointerSize).Deref()); // pi.hThread
454
this._hProcess = pi.Deref(0, GM.PointerSize).Deref(); // pi.hProcess
455
this._hProcessID = pi.Deref(GM.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE(); // pi.dwProcessId
@@ -533,23 +457,37 @@ function windows_terminal()
457
}
458
}
459
536
-function LOWORD(val)
537
-{
538
- return (val & 0xFFFF);
539
-}
540
-function HIWORD(val)
541
-{
542
- return ((val >> 16) & 0xFFFF);
543
-}
544
-
545
-function GetEsc(CodeCharStr, arg1, arg2)
546
-{
547
- return (Buffer.from('\x1B[' + arg1 + ';' + arg2 + CodeCharStr));
548
- //return (Buffer.from('*[' + arg1 + ';' + arg2 + CodeCharStr));
460
+function LOWORD(val) { return (val & 0xFFFF); }
461
+function HIWORD(val) { return ((val >> 16) & 0xFFFF); }
462
+function GetEsc(op, args) { return (Buffer.from('\x1B[' + args.join(';') + op)); }
463
+//function MeshConsole(msg) { require('MeshAgent').SendCommand({ "action": "msg", "type": "console", "value": JSON.stringify(msg) }); }
464
+function TranslateLine(x, y, data, attributes) {
465
+ var i, fcolor, bcolor, rcolor, fbright, bbright, lastAttr, fc, bc, rc, fb, bb, esc = [], output = [GetEsc('H', [y, x])];
466
+ if (typeof attributes == 'number') { attributes = [ attributes ]; } // If we get a single attribute, turn it into an array.
467
+
468
+ for (i = 0; i < data.length; i++) {
469
+ if (lastAttr != attributes[i]) { // To boost performance, if the attribute is the same as the last one, skip this entire part.
470
+ fc = (attributes[i] & 0x0007);
471
+ fc = ((fc & 0x0001) << 2) + (fc & 0x0002) + ((fc & 0x0004) >> 2); // Foreground color
472
+ bc = (attributes[i] & 0x0070) >> 4;
473
+ bc = ((bc & 0x0001) << 2) + (bc & 0x0002) + ((bc & 0x0004) >> 2); // Background color
474
+ rc = (attributes[i] & 0x4000); // Reverse color set
475
+ fb = (attributes[i] & 0x0008) >> 3; // Bright foreground set
476
+ bb = (attributes[i] & 0x0080); // Bright background set
477
+
478
+ 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
479
+ if (fc != fcolor) { esc.push(fc + 30); fcolor = fc; } // Set the foreground color if needed
480
+ if (bc != bcolor) { esc.push(bc + 40); bcolor = bc; } // Set the background color if needed
481
+ if (fb != fbright) { esc.push(2 - fb); fbright = fb; } // Set the bright foreground color if needed
482
+ if (bb != bbright) { if (bb == 0) { esc.push(bcolor + 40); } else { esc.push(bcolor + 100); bbright = bb; } } // Set bright Background color if needed
483
+
484
+ if (esc.length > 0) { output.push(GetEsc('m', esc)); esc = []; }
485
+ lastAttr = attributes[i];
486
+ }
487
+ output.push(Buffer.from(String.fromCharCode(data[i])));
488
+ }
489
+
490
+ return Buffer.concat(output);
491
}
492
551
-function TranslateLine(x, y, data, attributes)
552
-{
553
- return (Buffer.concat([GetEsc('H', y, x), data]));
554
-}
493
module.exports = new windows_terminal();
\ No newline at end of file
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.2.4-n",
3
+ "version": "0.2.4-p",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",