Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions meshcore/agentcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ limitations under the License.
#include "wincrypto.h"
#include <shellscalingapi.h>
#include <process.h>
#include "meshservice/resource.h"
#endif

#include "agentcore.h"
Expand Down Expand Up @@ -3856,7 +3857,34 @@ void MeshServer_ConnectEx(MeshAgentHostContainer *agent)
if (ILibIsChainBeingDestroyed(agent->chain) != 0) { return; }

len = ILibSimpleDataStore_Get(agent->masterDb, "MeshServer", ILibScratchPad2, sizeof(ILibScratchPad2));
if (len == 0) { printf("No MeshCentral settings found, place .msh file with this executable and restart.\r\n"); ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Microstack_Generic, ILibRemoteLogging_Flags_VerbosityLevel_1, "agentcore: MeshServer URI not found"); return; }
if (len == 0) {
printf("No MeshCentral settings found, place .msh file with this executable and restart.\r\n");
ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Microstack_Generic, ILibRemoteLogging_Flags_VerbosityLevel_1, "agentcore: MeshServer URI not found");
return;
}

#ifdef WIN32
// Check if winpty.dll and winpty-agent.exe are present and try to deploy them if not.
int length = ILibString_LastIndexOf(agent->exePath, strnlen_s(agent->exePath, MAX_PATH), "\\", 1) + 1;
char basePath[MAX_PATH];
char winPtyDllPath[MAX_PATH];
char winPtyAgentExePath[MAX_PATH];
_snprintf_s(basePath, MAX_PATH, length, "%s", agent->exePath);
sprintf_s(winPtyDllPath, MAX_PATH, "%swinpty.dll", basePath);
sprintf_s(winPtyAgentExePath, MAX_PATH, "%swinpty-agent.exe", basePath);
if (GetFileAttributes(winPtyDllPath) == INVALID_FILE_ATTRIBUTES ||
GetFileAttributes(winPtyAgentExePath) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf("Either winpty.dll or winpty-agent.exe is missing. Trying to deploy missing dependencies.\r\n");
duk_push_sprintf(agent->meshCoreCtx, "require('service-manager').manager.deployWinPtyDependencies('%s')", basePath);
duk_string_split(agent->meshCoreCtx, -1, "\\"); // [string][array]
duk_array_join(agent->meshCoreCtx, -1, "\\\\"); // [string][array][string]
duk_remove(agent->meshCoreCtx, -2); // [string][string]
duk_remove(agent->meshCoreCtx, -2); // [string]
duk_peval_noresult(agent->meshCoreCtx);
}
#endif

if (ILibSimpleDataStore_Get(agent->masterDb, "autoproxy", ILibScratchPad, sizeof(ILibScratchPad)) != 0)
{
Expand Down Expand Up @@ -6341,8 +6369,6 @@ void MeshAgent_Stop(MeshAgentHostContainer *agent)
ILibStopChain(agent->chain);
}



#ifdef WIN32
// Perform self-update (Windows console/tray version)
void MeshAgent_PerformSelfUpdate(char* selfpath, char* exepath, int argc, char **argv)
Expand Down
Binary file modified meshservice/MeshService.rc
Binary file not shown.
46 changes: 38 additions & 8 deletions meshservice/MeshService.vcxproj

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions meshservice/MeshService.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
<Filter Include="Meshcore\zlib">
<UniqueIdentifier>{cb187bde-f3b9-48e0-b3fd-f1732a3b3de2}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\x64">
<UniqueIdentifier>{4e67d388-0e2f-479f-848f-cac0c5576346}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\ia32">
<UniqueIdentifier>{a21d9586-6d67-4efa-a44b-403321268b1a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="MeshService.rc">
Expand Down Expand Up @@ -360,4 +366,18 @@
</ClInclude>
<ClInclude Include="stdafx.h" />
</ItemGroup>
<ItemGroup>
<None Include="x64\winpty.dll">
<Filter>Resource Files\x64</Filter>
</None>
<None Include="x64\winpty-agent.exe">
<Filter>Resource Files\x64</Filter>
</None>
<None Include="ia32\winpty.dll">
<Filter>Resource Files\ia32</Filter>
</None>
<None Include="ia32\winpty-agent.exe">
<Filter>Resource Files\ia32</Filter>
</None>
</ItemGroup>
</Project>
42 changes: 42 additions & 0 deletions meshservice/MeshService64.rc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,48 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)

/////////////////////////////////////////////////////////////////////////////
//
// BIN
//

#if defined(APSTUDIO_INVOKED) || defined(_ARCH_64)
#if defined(APSTUDIO_INVOKED)
IDR_WINPTY_DLL_X64$(_ARCH_64) BIN "x64\\winpty.dll"

#else
IDR_WINPTY_DLL_X64 BIN "x64\\winpty.dll"

#endif
#endif
#if defined(APSTUDIO_INVOKED) || defined(_ARCH_64)
#if defined(APSTUDIO_INVOKED)
IDR_WINPTY_AGENT_EXE_X64$(_ARCH_64) BIN "x64\\winpty-agent.exe"

#else
IDR_WINPTY_AGENT_EXE_X64 BIN "x64\\winpty-agent.exe"

#endif
#endif
#if defined(APSTUDIO_INVOKED) || defined(_ARCH_32)
#if defined(APSTUDIO_INVOKED)
IDR_WINPTY_DLL_IA32$(_ARCH_32) BIN "ia32\\winpty.dll"

#else
IDR_WINPTY_DLL_IA32 BIN "ia32\\winpty.dll"

#endif
#endif
#if defined(APSTUDIO_INVOKED) || defined(_ARCH_32)
#if defined(APSTUDIO_INVOKED)
IDR_WINPTY_AGENT_EXE_IA32$(_ARCH_32) BIN "ia32\\winpty-agent.exe"

#else
IDR_WINPTY_AGENT_EXE_IA32 BIN "ia32\\winpty-agent.exe"

#endif
#endif

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
Expand Down
Binary file added meshservice/ia32/winpty-agent.exe
Binary file not shown.
Binary file added meshservice/ia32/winpty.dll
Binary file not shown.
Binary file modified meshservice/resource.h
Binary file not shown.
Binary file added meshservice/x64/winpty-agent.exe
Binary file not shown.
Binary file added meshservice/x64/winpty.dll
Binary file not shown.
6 changes: 3 additions & 3 deletions microscript/ILibDuktape_Commit.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// This file is auto-generated, any edits may be overwritten
#define SOURCE_COMMIT_DATE "2025-Mar-6 21:44:07+0000"
#define SOURCE_COMMIT_HASH "28d67274264e140e0c7a4254ad0e32865d5c4a13"
// This file is auto-generated, any edits may be overwritten
#define SOURCE_COMMIT_DATE "2025-Sep-1 14:28:47+0200"
#define SOURCE_COMMIT_HASH "b08c510a7efea567c3306da88cbb15c92e29f1c1"
10 changes: 5 additions & 5 deletions microscript/ILibDuktape_Polyfills.c

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions modules/service-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var GENERIC_READ = 0x80000000;
var GENERIC_WRITE = 0x40000000;
var CREATE_ALWAYS = 2;
var FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000;
var FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
var INVALID_HANDLE_VALUE = -1;

var promise = require('promise');
var systemd_escape = null;

Expand Down Expand Up @@ -637,6 +645,15 @@ function serviceManager()
this.proxy.CreateMethod('FreeSid');

this.proxy2 = this.GM.CreateNativeProxy('Kernel32.dll');
this.proxy2.CreateMethod('GetModuleHandleW');
this.proxy2.CreateMethod('FindResourceW');
this.proxy2.CreateMethod('LoadResource');
this.proxy2.CreateMethod('SizeofResource');
this.proxy2.CreateMethod('LockResource');
this.proxy2.CreateMethod('FreeResource');
this.proxy2.CreateMethod('CreateFileW');
this.proxy2.CreateMethod('WriteFile');
this.proxy2.CreateMethod('CloseHandle');
this.proxy2.CreateMethod('GetLastError');

this.isAdmin = function isAdmin() {
Expand Down Expand Up @@ -2325,6 +2342,11 @@ function serviceManager()
}

console.info1(' Install Path = ' + options.installPath);

// On Windows, we need to install winpty.dll and winpty-agent.exe along with the executable of the agent
// to ensure that legacy / non-ConPTY remote terminal access works properly.
this.deployWinPtyDependencies(options.installPath);

console.info1(' OpenSCManagerA()');
var servicePath = this.GM.CreateVariable('"' + options.servicePath + '"', { wide: true });
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
Expand Down Expand Up @@ -3013,6 +3035,17 @@ function serviceManager()
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/C CHOICE /C Y /N /D Y /T 10 & del "' + servicePath + '"'], { type: 4 });
}
}
try
{
// Remove winpty.dll and winpty-agent.exe
var fs = require('fs');
fs.unlinkSync(service.appWorkingDirectory() + '\\winpty.dll');
fs.unlinkSync(service.appWorkingDirectory() + '\\winpty-agent.exe');
}
catch (e)
{
console.info1('Error deleting winpty.dll and winpty-agent.exe');
}
if (this.proxy.DeleteService(service._service) == 0)
{
throw ('Uninstall Service for: ' + name + ', failed with error: ' + this.proxy2.GetLastError());
Expand Down Expand Up @@ -3291,6 +3324,83 @@ function serviceManager()
}
}

// Grab the WinPTY files from the resources of the executable and copy them to the install path.
this.deployWinPtyDependencies = function deployWinPtyDependencies(installPath)
{
console.info1(' Deploy winpty.dll and winpty-agent.exe');

var agentExeHandle = this.proxy2.GetModuleHandleW(0);
var winPtyDllResourceId;
var winPtyAgentExeResourceId;
if (this.GM.PointerSize == 8) {
// 64-Bit Windows
winPtyDllResourceId = 114; // IDR_WINPTY_DLL_X64 in resource.h
winPtyAgentExeResourceId = 115; // IDR_WINPTY_AGENT_EXE_X64
} else {
// 32-Bit Windows
winPtyDllResourceId = 116; // IDR_WINPTY_DLL_IA32 in resource.h
winPtyAgentExeResourceId = 117; // IDR_WINPTY_AGENT_EXE_IA32
}
var winPtyDllResource = this.proxy2.FindResourceW(
agentExeHandle,
winPtyDllResourceId,
this.GM.CreateVariable('BIN', { wide: true })
);
var winPtyAgentExeResource = this.proxy2.FindResourceW(
agentExeHandle,
winPtyAgentExeResourceId,
this.GM.CreateVariable('BIN', { wide: true })
);
this.copyResourceToFilesystem(winPtyDllResource, installPath, 'winpty.dll');
this.copyResourceToFilesystem(winPtyAgentExeResource, installPath, 'winpty-agent.exe')

console.info1(' => SUCCESS');
}

this.copyResourceToFilesystem = function copyResourceToFilesystem(resource, installPath, fileName)
{
if (resource == 0) {
throw ('Invalid resource: ' + fileName);
}

var resourceData = this.proxy2.LoadResource(0, resource);
if (resourceData == 0) {
throw ('Unable to load resource: ' + fileName);
}

var resourceSize = this.proxy2.SizeofResource(0, resource);
var lpResource = this.proxy2.LockResource(resourceData);
if (lpResource == 0) {
this.proxy2.FreeResource(resourceData);
throw ('Unable to retrieve memory pointer to resource: ' + fileName);
}

var file = this.proxy2.CreateFileW(
this.GM.CreateVariable(installPath + '\\' + fileName, { wide: true }),
GENERIC_READ | GENERIC_WRITE,
0,
0,
CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN | FILE_ATTRIBUTE_ARCHIVE,
0
);

if (file == INVALID_HANDLE_VALUE) {
this.proxy2.FreeResource(resourceData);
throw ('Unable to create file: ' + fileName);
}

var written = this.GM.CreateVariable(4);
var isFileWritten = this.proxy2.WriteFile(file, lpResource, resourceSize, written, 0);

this.proxy2.CloseHandle(file);
this.proxy2.FreeResource(resourceData);

if (!isFileWritten) {
throw ('Unable to write file: ' + fileName);
}
}

this.getServiceType = function getServiceType()
{
if (this._platform != null) { return (this._platform); }
Expand Down
Loading