1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-06 00:13:33 +00:00

Added support for parallel installs, using alternative service names

This commit is contained in:
Bryan Roe
2020-10-24 13:26:02 -07:00
parent f94758c7e6
commit aeef17e649
9 changed files with 538 additions and 226 deletions

View File

@@ -138,6 +138,13 @@ char* crashMemory = ILib_POSIX_InstallCrashHandler(argv[0]);
integratedJavaScript = ILibString_Copy(script, sizeof(script) - 1);
integratedJavaScriptLen = (int)sizeof(script) - 1;
}
if (argc > 1 && strcasecmp(argv[1], "-name") == 0 && integratedJavaScriptLen == 0)
{
char script[] = "console.log(require('_agentNodeId').serviceName());process.exit();";
integratedJavaScript = ILibString_Copy(script, sizeof(script) - 1);
integratedJavaScriptLen = (int)sizeof(script) - 1;
}
if (argc > 1 && strcmp(argv[1], "-daemon") == 0 && integratedJavaScriptLen == 0)
{
integratedJavaScript = ILibString_Copy("require('daemon').agent();", 0);

View File

@@ -1796,6 +1796,12 @@ void ILibDuktape_MeshAgent_PUSH(duk_context *ctx, void *chain)
Duktape_CreateEnum(ctx, "ContainerPermissions", (char*[]) { "DEFAULT", "NO_AGENT", "NO_MARSHAL", "NO_PROCESS_SPAWNING", "NO_FILE_SYSTEM_ACCESS", "NO_NETWORK_ACCESS" }, (int[]) { 0x00, 0x10000000, 0x08000000, 0x04000000, 0x00000001, 0x00000002 }, 6);
if (agent->JSRunningAsService)
{
duk_push_string(ctx, agent->meshServiceName);
ILibDuktape_CreateReadonlyProperty(ctx, "serviceName");
}
#ifdef WIN32
#ifdef _WINSERVICE
duk_push_boolean(ctx, agent->runningAsConsole == 0);
@@ -1893,8 +1899,16 @@ int agent_GenerateCertificates(MeshAgentHostContainer *agent, char* certfile)
if (certfile == NULL)
{
#if defined(WIN32)
char *rootSubject = (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "CN=MeshNodeDiagnosticCertificate" : "CN=MeshNodeCertificate";
char rootSubject[255];
if (agent->noCertStore == 0 && agent->meshServiceName != NULL && strcmp(agent->meshServiceName, "Mesh Agent") == 0)
{
sprintf_s(rootSubject, sizeof(rootSubject), "CN=MeshNode%s", (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "DiagnosticCertificate" : "Certificate");
}
else
{
sprintf_s(rootSubject, sizeof(rootSubject), "CN=%s_Node%s", agent->meshServiceName, (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "DiagnosticCertificate" : "Certificate");
}
if (agent->noCertStore == 0 && (agent->certObject = wincrypto_open(TRUE, rootSubject)) != NULL) // Force certificate re-generation
{
int l;
@@ -2003,7 +2017,15 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent)
if (len == 0 || util_from_p12(ILibScratchPad2, len, "hidden", &(agent->selfcert)) == 0)
{
#if defined(WIN32)
char *rootSubject = (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "CN=MeshNodeDiagnosticCertificate" : "CN=MeshNodeCertificate";
char rootSubject[255];
if (agent->noCertStore == 0 && agent->meshServiceName != NULL && strcmp(agent->meshServiceName, "Mesh Agent") == 0)
{
sprintf_s(rootSubject, sizeof(rootSubject), "CN=MeshNode%s", (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "DiagnosticCertificate" : "Certificate");
}
else
{
sprintf_s(rootSubject, sizeof(rootSubject), "CN=%s_Node%s", agent->meshServiceName, (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "DiagnosticCertificate" : "Certificate");
}
// No cert in this .db file. Try to load or generate a root certificate from a Windows crypto provider. This can be TPM backed which is great.
// However, if we don't have the second cert created, we need to regen the root...
@@ -3687,6 +3709,7 @@ void MeshServer_Connect(MeshAgentHostContainer *agent)
agent->controlChannelDebug = ILibSimpleDataStore_Get(agent->masterDb, "controlChannelDebug", NULL, 0);
ILibDuktape_HECI_Debug = (ILibSimpleDataStore_Get(agent->masterDb, "heciDebug", NULL, 0) != 0);
#if defined(_LINKVM) && defined(_POSIX) && !defined(__APPLE__)
SLAVELOG = ILibSimpleDataStore_Get(agent->masterDb, "slaveKvmLog", NULL, 0);
#endif
@@ -3733,11 +3756,14 @@ int ValidateMeshServer(ILibWebClient_RequestToken sender, int preverify_ok, STAC
}
#endif
void checkForEmbeddedMSH(MeshAgentHostContainer *agent)
#define checkForEmbeddedMSH(agent) checkForEmbeddedMSH_ex(agent, NULL)
void checkForEmbeddedMSH_ex(MeshAgentHostContainer *agent, char **eMSH)
{
FILE *tmpFile = NULL;
int mshLen;
char *data = NULL;
if (eMSH != NULL) { *eMSH = NULL; }
#ifdef WIN32
_wfopen_s(&tmpFile, ILibUTF8ToWide(agent->exePath, -1), L"rb");
@@ -3756,26 +3782,39 @@ void checkForEmbeddedMSH(MeshAgentHostContainer *agent)
{
mshLen = ntohl(mshLen);
fseek(tmpFile, -4 - mshLen, SEEK_CUR);
char *eMSH = ILibMemory_AllocateA(mshLen);
if (fread(eMSH, 1, mshLen, tmpFile) == mshLen)
data = (char*)ILibMemory_SmartAllocate(mshLen);
if (eMSH != NULL) { *eMSH = data; }
if (fread(data, 1, mshLen, tmpFile) == mshLen)
{
FILE *msh = NULL;
#ifdef WIN32
_wfopen_s(&msh, ILibUTF8ToWide(MeshAgent_MakeAbsolutePath(agent->exePath, ".msh"), -1), L"wb");
#else
msh = fopen(MeshAgent_MakeAbsolutePath(agent->exePath, ".msh"), "wb");
#endif
if (msh != NULL)
if (eMSH == NULL)
{
ignore_result(fwrite(eMSH, 1, mshLen, msh));
fclose(msh);
FILE *msh = NULL;
#ifdef WIN32
_wfopen_s(&msh, ILibUTF8ToWide(MeshAgent_MakeAbsolutePath(agent->exePath, ".msh"), -1), L"wb");
#else
msh = fopen(MeshAgent_MakeAbsolutePath(agent->exePath, ".msh"), "wb");
#endif
if (msh != NULL)
{
ignore_result(fwrite(data, 1, mshLen, msh));
fclose(msh);
}
ILibMemory_Free(data);
}
}
}
}
fclose(tmpFile);
}
void checkForEmbeddedMSH_ex2(char *binPath, char **eMSH)
{
MeshAgentHostContainer tmp;
memset(&tmp, 0, sizeof(tmp));
tmp.exePath = binPath;
checkForEmbeddedMSH_ex(&tmp, eMSH);
}
int importSettings(MeshAgentHostContainer *agent, char* fileName)
{
int eq;
@@ -4348,16 +4387,35 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
#if !defined(MICROSTACK_NOTLS) || defined(_POSIX)
duk_context *tmpCtx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(0, 0, agentHost->chain, NULL, NULL, agentHost->exePath, NULL, NULL, NULL);
duk_peval_string_noresult(tmpCtx, "require('linux-pathfix')();");
int msnlen;
char *tmpString;
agentHost->platformType = MeshAgent_Posix_PlatformTypes_UNKNOWN;
agentHost->JSRunningAsService = 0;
agentHost->JSRunningWithAdmin = 0;
if ((msnlen = ILibSimpleDataStore_Get(agentHost->masterDb, "meshServiceName", NULL, 0)) != 0)
{
agentHost->meshServiceName = (char*)ILibMemory_SmartAllocate(msnlen+1);
ILibSimpleDataStore_Get(agentHost->masterDb, "meshServiceName", agentHost->meshServiceName, msnlen);
}
else
{
#ifdef WIN32
agentHost->meshServiceName = "Mesh Agent";
#else
agentHost->meshServiceName = "meshagent";
#endif
}
duk_push_sprintf(tmpCtx, "require('service-manager').manager.getService('%s').isMe();", agentHost->meshServiceName);
tmpString = (char*)duk_get_string(tmpCtx, -1);
if (duk_peval_string(tmpCtx, "(function foo() { var f = require('service-manager').manager.getServiceType(); switch(f){case 'procd': return(7); case 'windows': return(10); case 'launchd': return(3); case 'freebsd': return(5); case 'systemd': return(1); case 'init': return(2); case 'upstart': return(4); default: return(0);}})()") == 0)
{
agentHost->platformType = (MeshAgent_Posix_PlatformTypes)duk_get_int(tmpCtx, -1);
}
if (duk_peval_string(tmpCtx, "require('service-manager').manager.getService(process.platform=='win32'?'Mesh Agent':'meshagent').isMe();") == 0)
if (duk_peval_string(tmpCtx, tmpString) == 0)
{
agentHost->JSRunningAsService = duk_get_boolean(tmpCtx, -1);
}
@@ -4484,88 +4542,104 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
#ifdef WIN32
// If running as a Windows service, set basic values to the registry, this allows other applications to know what the mesh agent is doing.
HKEY hKey;
size_t rlen = snprintf(NULL, 0, "Software\\Open Source\\%s", agentHost->meshServiceName);
char *tmp1 = (char*)ILibMemory_SmartAllocate(rlen + 1);
snprintf(tmp1, ILibMemory_Size(tmp1), "Software\\Open Source\\%s", agentHost->meshServiceName);
size_t wlen = ILibUTF8ToWideCount(tmp1) + 1;
WCHAR* wstr = (WCHAR*)ILibMemory_SmartAllocate(wlen * sizeof(WCHAR));
if (wlen < INT32_MAX && rlen <= INT32_MAX)
{
ILibUTF8ToWideEx(tmp1, (int)rlen, wstr, (int)wlen + 1);
#if defined(_WINSERVICE)
// If running as a Windows Service, save the key in LOCAL_MACHINE
if (RegCreateKey(agentHost->runningAsConsole == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, TEXT("Software\\Open Source\\MeshAgent2"), &hKey) == ERROR_SUCCESS)
// If running as a Windows Service, save the key in LOCAL_MACHINE
if (RegCreateKeyW(agentHost->runningAsConsole == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, wstr, &hKey) == ERROR_SUCCESS)
#else
// If running in Console mode, save the key in CURRENT_USER
if (RegCreateKey(HKEY_CURRENT_USER, TEXT("Software\\Open Source\\MeshAgent2"), &hKey) == ERROR_SUCCESS)
// If running in Console mode, save the key in CURRENT_USER
if (RegCreateKeyW(HKEY_CURRENT_USER, wstr, &hKey) == ERROR_SUCCESS)
#endif
{
int i, len;
char* tmp = NULL;
if ((agentHost->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == 0)
{
// Save the NodeId
len = ILibBase64Encode(agentHost->g_selfid, UTIL_SHA384_HASHSIZE, &tmp);
if ((len > 0) && (tmp != NULL))
int i, len;
char* tmp = NULL;
if ((agentHost->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == 0)
{
for (i = 0; i < len; i++) { if (tmp[i] == '+') { tmp[i] = '@'; } else if (tmp[i] == '/') { tmp[i] = '$'; } } // Replace + --> @ and / --> $
RegSetValueExA(hKey, "NodeId", 0, REG_SZ, tmp, len);
free(tmp);
tmp = NULL;
}
else { RegDeleteKeyA(hKey, "NodeId"); }
// Save the NodeId
len = ILibBase64Encode(agentHost->g_selfid, UTIL_SHA384_HASHSIZE, &tmp);
if ((len > 0) && (tmp != NULL))
{
for (i = 0; i < len; i++) { if (tmp[i] == '+') { tmp[i] = '@'; } else if (tmp[i] == '/') { tmp[i] = '$'; } } // Replace + --> @ and / --> $
RegSetValueExA(hKey, "NodeId", 0, REG_SZ, tmp, len);
free(tmp);
tmp = NULL;
}
else { RegDeleteKeyA(hKey, "NodeId"); }
// Save the AgentHash
util_tohex(agentHost->agentHash, UTIL_SHA384_HASHSIZE, ILibScratchPad);
RegSetValueExA(hKey, "AgentHash", 0, REG_SZ, ILibScratchPad, (int)strlen(ILibScratchPad));
// Save the MeshId
if (ILibSimpleDataStore_Get(agentHost->masterDb, "MeshID", NULL, 0) == 0) { RegDeleteKeyA(hKey, "MeshId"); } else {
len = ILibSimpleDataStore_Get(agentHost->masterDb, "MeshID", ILibScratchPad2, (int)sizeof(ILibScratchPad2));
if (len > 0) {
len = ILibBase64Encode(ILibScratchPad2, len, &tmp);
if ((len > 0) && (tmp != NULL)) {
for (i = 0; i < len; i++) { if (tmp[i] == '+') { tmp[i] = '@'; } else if (tmp[i] == '/') { tmp[i] = '$'; } } // Replace + --> @ and / --> $
RegSetValueExA(hKey, "MeshId", 0, REG_SZ, tmp, len);
free(tmp);
tmp = NULL;
// Save the AgentHash
util_tohex(agentHost->agentHash, UTIL_SHA384_HASHSIZE, ILibScratchPad);
RegSetValueExA(hKey, "AgentHash", 0, REG_SZ, ILibScratchPad, (int)strlen(ILibScratchPad));
// Save the MeshId
if (ILibSimpleDataStore_Get(agentHost->masterDb, "MeshID", NULL, 0) == 0) { RegDeleteKeyA(hKey, "MeshId"); }
else {
len = ILibSimpleDataStore_Get(agentHost->masterDb, "MeshID", ILibScratchPad2, (int)sizeof(ILibScratchPad2));
if (len > 0) {
len = ILibBase64Encode(ILibScratchPad2, len, &tmp);
if ((len > 0) && (tmp != NULL)) {
for (i = 0; i < len; i++) { if (tmp[i] == '+') { tmp[i] = '@'; } else if (tmp[i] == '/') { tmp[i] = '$'; } } // Replace + --> @ and / --> $
RegSetValueExA(hKey, "MeshId", 0, REG_SZ, tmp, len);
free(tmp);
tmp = NULL;
}
else { RegDeleteKeyA(hKey, "MeshId"); }
}
else { RegDeleteKeyA(hKey, "MeshId"); }
}
else { RegDeleteKeyA(hKey, "MeshId"); }
}
// Save a bunch of values in the registry
if ((pLen = ILibSimpleDataStore_Get(agentHost->masterDb, "MeshServer", ILibScratchPad2, (int)sizeof(ILibScratchPad2))) == 0) { RegDeleteKeyA(hKey, "MeshServerUrl"); } else { RegSetValueExA(hKey, "MeshServerUrl", 0, REG_SZ, (BYTE*)ILibScratchPad2, (int)strlen(ILibScratchPad2)); } // Save the mesh server URL
if ((pLen = ILibSimpleDataStore_Get(agentHost->masterDb, "ServerID", ILibScratchPad2, (int)sizeof(ILibScratchPad2))) == 0) { RegDeleteKeyA(hKey, "MeshServerId"); } else { RegSetValueExA(hKey, "MeshServerId", 0, REG_SZ, (BYTE*)ILibScratchPad2, (int)strlen(ILibScratchPad2)); } // Save the mesh server id
if ((pLen = ILibSimpleDataStore_Get(agentHost->masterDb, "WebProxy", ILibScratchPad2, (int)sizeof(ILibScratchPad2))) == 0) { RegDeleteKeyA(hKey, "Proxy"); } else { RegSetValueExA(hKey, "Proxy", 0, REG_SZ, (BYTE*)ILibScratchPad2, (int)strlen(ILibScratchPad2)); } // Save the proxy
if ((pLen = ILibSimpleDataStore_Get(agentHost->masterDb, "Tag", ILibScratchPad2, (int)sizeof(ILibScratchPad2))) == 0) { RegDeleteKeyA(hKey, "Tag"); } else { RegSetValueExA(hKey, "Tag", 0, REG_SZ, (BYTE*)ILibScratchPad2, (int)strlen(ILibScratchPad2)); } // Save the tag
}
else
{
// We're a Diagnostic Agent, so we only save a subset
// Save the NodeId
len = ILibBase64Encode(agentHost->g_selfid, UTIL_SHA384_HASHSIZE, &tmp);
if ((len > 0) && (tmp != NULL))
// Save a bunch of values in the registry
if ((pLen = ILibSimpleDataStore_Get(agentHost->masterDb, "MeshServer", ILibScratchPad2, (int)sizeof(ILibScratchPad2))) == 0) { RegDeleteKeyA(hKey, "MeshServerUrl"); }
else { RegSetValueExA(hKey, "MeshServerUrl", 0, REG_SZ, (BYTE*)ILibScratchPad2, (int)strlen(ILibScratchPad2)); } // Save the mesh server URL
if ((pLen = ILibSimpleDataStore_Get(agentHost->masterDb, "ServerID", ILibScratchPad2, (int)sizeof(ILibScratchPad2))) == 0) { RegDeleteKeyA(hKey, "MeshServerId"); }
else { RegSetValueExA(hKey, "MeshServerId", 0, REG_SZ, (BYTE*)ILibScratchPad2, (int)strlen(ILibScratchPad2)); } // Save the mesh server id
if ((pLen = ILibSimpleDataStore_Get(agentHost->masterDb, "WebProxy", ILibScratchPad2, (int)sizeof(ILibScratchPad2))) == 0) { RegDeleteKeyA(hKey, "Proxy"); }
else { RegSetValueExA(hKey, "Proxy", 0, REG_SZ, (BYTE*)ILibScratchPad2, (int)strlen(ILibScratchPad2)); } // Save the proxy
if ((pLen = ILibSimpleDataStore_Get(agentHost->masterDb, "Tag", ILibScratchPad2, (int)sizeof(ILibScratchPad2))) == 0) { RegDeleteKeyA(hKey, "Tag"); }
else { RegSetValueExA(hKey, "Tag", 0, REG_SZ, (BYTE*)ILibScratchPad2, (int)strlen(ILibScratchPad2)); } // Save the tag
}
else
{
for (i = 0; i < len; i++) { if (tmp[i] == '+') { tmp[i] = '@'; } else if (tmp[i] == '/') { tmp[i] = '$'; } } // Replace + --> @ and / --> $
RegSetValueExA(hKey, "DiagnosticAgentNodeId", 0, REG_SZ, tmp, len);
free(tmp);
tmp = NULL;
// We're a Diagnostic Agent, so we only save a subset
// Save the NodeId
len = ILibBase64Encode(agentHost->g_selfid, UTIL_SHA384_HASHSIZE, &tmp);
if ((len > 0) && (tmp != NULL))
{
for (i = 0; i < len; i++) { if (tmp[i] == '+') { tmp[i] = '@'; } else if (tmp[i] == '/') { tmp[i] = '$'; } } // Replace + --> @ and / --> $
RegSetValueExA(hKey, "DiagnosticAgentNodeId", 0, REG_SZ, tmp, len);
free(tmp);
tmp = NULL;
}
else { RegDeleteKeyA(hKey, "DiagnosticAgentNodeId"); }
}
else { RegDeleteKeyA(hKey, "DiagnosticAgentNodeId"); }
}
if (ILibSimpleDataStore_Get(agentHost->masterDb, "SelfNodeCert", NULL, 0) == 0)
{
int NodeIDLen = 0;
if ((NodeIDLen = ILibSimpleDataStore_Get(agentHost->masterDb, "NodeID", ILibScratchPad, (int)sizeof(ILibScratchPad))) == 0 || !(NodeIDLen == (int)sizeof(agentHost->g_selfid) && memcmp(agentHost->g_selfid, ILibScratchPad, NodeIDLen) == 0))
if (ILibSimpleDataStore_Get(agentHost->masterDb, "SelfNodeCert", NULL, 0) == 0)
{
// NodeID isn't saved to db, so let's put it there
ILibSimpleDataStore_PutEx(agentHost->masterDb, "NodeID", 6, agentHost->g_selfid, (int)sizeof(agentHost->g_selfid));
int NodeIDLen = 0;
if ((NodeIDLen = ILibSimpleDataStore_Get(agentHost->masterDb, "NodeID", ILibScratchPad, (int)sizeof(ILibScratchPad))) == 0 || !(NodeIDLen == (int)sizeof(agentHost->g_selfid) && memcmp(agentHost->g_selfid, ILibScratchPad, NodeIDLen) == 0))
{
// NodeID isn't saved to db, so let's put it there
ILibSimpleDataStore_PutEx(agentHost->masterDb, "NodeID", 6, agentHost->g_selfid, (int)sizeof(agentHost->g_selfid));
}
}
}
// Close the registry key
RegCloseKey(hKey);
// Close the registry key
RegCloseKey(hKey);
}
}
ILibMemory_Free(tmp1);
ILibMemory_Free(wstr);
#endif
#ifndef MICROSTACK_NOTLS
@@ -5123,6 +5197,7 @@ void MeshAgent_ScriptMode(MeshAgentHostContainer *agentHost, int argc, char **ar
agentHost->meshCoreCtx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(secFlags, execTimeout, agentHost->chain, scriptArgs, connectAgent != 0 ? agentHost->masterDb : NULL, agentHost->exePath, agentHost->pipeManager, connectAgent == 0 ? MeshAgent_RunScriptOnly_Finalizer : NULL, agentHost);
ILibDuktape_SetNativeUncaughtExceptionHandler(agentHost->meshCoreCtx, MeshAgent_ScriptMode_UncaughtExceptionSink, agentHost);
if (connectAgent != 0)
{
ILibDuktape_MeshAgent_Init(agentHost->meshCoreCtx, agentHost->chain, agentHost);
@@ -5267,6 +5342,7 @@ int MeshAgent_System(char *cmd)
int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **param)
{
char *startParms = NULL;
char _exedata[ILibMemory_Init_Size(1024, sizeof(void*))];
char *exePath = ILibMemory_Init(_exedata, 1024, sizeof(void*), ILibMemory_Types_STACK);
((void**)ILibMemory_Extra(exePath))[0] = agentHost;
@@ -5375,7 +5451,40 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
agentHost->chain = NULL; // Mesh agent has exited, set the chain to NULL
// Close the database
if (agentHost->masterDb != NULL) {
if (agentHost->masterDb != NULL)
{
if (agentHost->performSelfUpdate != 0)
{
if (agentHost->JSRunningAsService == 0)
{
int jsonlen = ILibSimpleDataStore_Cached_GetJSONEx(agentHost->masterDb, NULL, 0);
if (jsonlen > 0)
{
startParms = (char*)ILibMemory_SmartAllocateEx(jsonlen, ILibBase64EncodeLength(jsonlen));
unsigned char* tmp = (unsigned char*)ILibMemory_Extra(startParms);
ILibSimpleDataStore_Cached_GetJSONEx(agentHost->masterDb, startParms, jsonlen);
ILibBase64Encode((unsigned char*)startParms, jsonlen, &tmp);
if (agentHost->logUpdate != 0) { ILIBLOGMESSAGEX(" Service Parameters => %s", startParms); }
}
else
{
if (agentHost->logUpdate != 0) { ILIBLOGMESSAGEX(" Service Parameters => NONE"); }
}
}
else
{
#ifdef WIN32
if(strcmp(agentHost->meshServiceName, "Mesh Agent") !=0)
#else
if (strcmp(agentHost->meshServiceName, "Mesh Agent") != 0)
#endif
{
startParms = ILibMemory_SmartAllocateEx(ILibMemory_Size(agentHost->meshServiceName) + 30, ILibBase64EncodeLength(ILibMemory_Size(agentHost->meshServiceName) + 30));
unsigned char* tmp = (unsigned char*)ILibMemory_Extra(startParms);
ILibBase64Encode((unsigned char*)startParms, sprintf_s(startParms, ILibMemory_Size(startParms), "[\"--meshServiceName=\\\"%s\\\"\"]", agentHost->meshServiceName), &tmp);
}
}
}
ILibSimpleDataStore_Close(agentHost->masterDb);
agentHost->masterDb = NULL;
}
@@ -5383,7 +5492,6 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
// Check if we need to perform self-update (performSelfUpdate should indicate startup type on Liunx: 1 = systemd, 2 = upstart, 3 = sysv-init)
if (agentHost->performSelfUpdate != 0)
{
int i, ptr = 0;
#ifdef WIN32
STARTUPINFOW info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
@@ -5394,20 +5502,13 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
#else
char* updateFilePath = MeshAgent_MakeAbsolutePath(agentHost->exePath, ".update"); // uses ILibScratchPad2
#endif
char str[4096];
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Updating..."); }
// Build the argument list
str[0] = 0;
for (i = 1; i < paramLen && ptr >= 0; i++) ptr += sprintf_s(str + ptr, 4096 - ptr, " %s", param[i]);
#ifdef WIN32
// Windows version
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s -update:\"%s\"%s", updateFilePath, agentHost->exePath, str);
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s -update:*%s %s", updateFilePath, agentHost->JSRunningAsService!=0?"S":"C", startParms==NULL?"":(char*)ILibMemory_Extra(startParms));
if (!CreateProcessW(NULL, ILibUTF8ToWide(ILibScratchPad, -1), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &info, &processInfo))
{
// We tried to execute a bad executable... not good. Lets try to recover.
// We triedI to execute a bad executable... not good. Lets try to recover.
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> FAILED..."); }
if (updateFilePath != NULL && agentHost->exePath != NULL)
{
@@ -5489,13 +5590,14 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
struct stat results;
stat(agentHost->exePath, &results); // This the mode of the current executable
chmod(updateFilePath, results.st_mode); // Set the new executable to the same mode as the current one.
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "\"%s\" -update:\"%s\"%s &", updateFilePath, agentHost->exePath, str); // Launch the new executable for update.
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "\"%s\" -update:* %s &", updateFilePath, startParms == NULL ? "" : (char*)ILibMemory_Extra(startParms));
if (system(ILibScratchPad)) {}
}
#endif
}
}
if (startParms != NULL) { ILibMemory_Free(startParms); }
#ifndef MICROSTACK_NOTLS
util_openssl_uninit();
@@ -5516,6 +5618,7 @@ void MeshAgent_Destroy(MeshAgentHostContainer* agent)
if (agent->chain != NULL) { ILibChain_DestroyEx(agent->chain); agent->chain = NULL; }
if (agent->multicastDiscoveryKey != NULL) { free(agent->multicastDiscoveryKey); agent->multicastDiscoveryKey = NULL; }
if (agent->multicastServerUrl != NULL) { free(agent->multicastServerUrl); agent->multicastServerUrl = NULL; }
if (agent->meshServiceName != NULL) { ILibMemory_Free(agent->meshServiceName); agent->meshServiceName = NULL; }
#ifdef WIN32
if (agent->shCore != NULL)
{

View File

@@ -237,6 +237,7 @@ typedef struct MeshAgentHostContainer
MeshAgent_Posix_PlatformTypes platformType;
int JSRunningAsService;
int JSRunningWithAdmin;
char *meshServiceName;
#if defined(_WINSERVICE)
int runningAsConsole;
#endif

View File

@@ -109,27 +109,6 @@ BOOL RunAsAdmin(char* args, int isAdmin)
return FALSE;
}
void UpdateOwnerData()
{
WCHAR str[_MAX_PATH];
DWORD strLen;
strLen = GetModuleFileNameW(NULL, str, _MAX_PATH);
int exePathLen = WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)str, -1, NULL, 0, NULL, NULL);
char *exePath = (char*)ILibMemory_SmartAllocate(exePathLen);
WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)str, -1, exePath, exePathLen, NULL, NULL);
void *chain = ILibCreateChain();
duk_context *ctx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(0, 0, chain, NULL, NULL, exePath, NULL, NULL, NULL);
duk_peval_string_noresult(ctx, "global._noMessagePump=true;var key=require('win-registry').usernameToUserKey(require('user-sessions').getProcessOwnerName(process.pid).name);var reg=require('win-registry');reg.WriteKey(reg.HKEY.LocalMachine, 'SYSTEM\\\\CurrentControlSet\\\\Services\\\\Mesh Agent', '_InstalledBy', key);");
Duktape_SafeDestroyHeap(ctx);
ILibChain_DestroyEx(chain);
ILibMemory_Free(exePath);
}
DWORD WINAPI ServiceControlHandler( DWORD controlCode, DWORD eventType, void *eventData, void* eventContext )
{
switch (controlCode)
@@ -566,6 +545,13 @@ int wmain(int argc, char* wargv[])
integratedJavaScript = ILibString_Copy(script, sizeof(script) - 1);
integragedJavaScriptLen = (int)sizeof(script) - 1;
}
if (argc > 1 && strcasecmp(argv[1], "-name") == 0)
{
char script[] = "console.log(require('_agentNodeId').serviceName());process.exit();";
integratedJavaScript = ILibString_Copy(script, sizeof(script) - 1);
integragedJavaScriptLen = (int)sizeof(script) - 1;
}
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
@@ -717,21 +703,31 @@ int wmain(int argc, char* wargv[])
else if (r == 2) { printf("Mesh agent failed to stop"); }
}
}
#ifdef _MINCORE
else if (argc > 1 && memcmp(argv[1], "-update:", 8) == 0)
{
// Attempt to copy our own exe over the original exe
while (util_CopyFile(argv[0], argv[1] + 8, FALSE) == FALSE) { Sleep(5000); }
// Attempt to start the updated service up again
LaunchService();
}
#endif
#ifndef _MINCORE
else if (argc > 1 && memcmp(argv[1], "-update:", 8) == 0)
{
char *update = ILibMemory_Allocate(512, 0, NULL, NULL);
int updateLen = sprintf_s(update, 512, "require('agent-installer').update();");
char *update = ILibMemory_Allocate(1024, 0, NULL, NULL);
int updateLen;
if (argv[1][8] == '*')
{
// New Style
updateLen = sprintf_s(update, 1024, "require('agent-installer').update(%s, '%s');", argv[1][9] == 'S' ? "true" : "false", argc > 1 ? argv[2] : "null");
}
else
{
// Legacy
if (argc > 1 && (strcmp(argv[2], "run") == 0 || strcmp(argv[2], "connect") == 0))
{
// Console Mode
updateLen = sprintf_s(update, 1024, "require('agent-installer').update(false, ['%s']);", argv[2]);
}
else
{
// Service
updateLen = sprintf_s(update, 1024, "require('agent-installer').update(true);");
}
}
__try
{
agent = MeshAgent_Create(0);
@@ -748,13 +744,8 @@ int wmain(int argc, char* wargv[])
}
wmain_free(argv);
return(retCode);
//// Attempt to copy our own exe over the original exe
//while (util_CopyFile(argv[0], argv[1] + 8, FALSE) == FALSE) Sleep(5000);
//// Attempt to start the updated service up again
//LaunchService(serviceFile);
}
#ifndef _MINCORE
else if (argc > 1 && (strcasecmp(argv[1], "-netinfo") == 0))
{
char* data;

File diff suppressed because one or more lines are too long

View File

@@ -17,6 +17,26 @@ limitations under the License.
const exeJavaScriptGuid = 'B996015880544A19B7F7E9BE44914C18';
const exeMeshPolicyGuid = 'B996015880544A19B7F7E9BE44914C19';
function mshLength()
{
var exesize = require('fs').statSync(process.execPath).size;
var fd = require('fs').openSync(process.execPath, "rb");
var buffer = Buffer.alloc(20);
require('fs').readSync(fd, buffer, 0, buffer.length, exesize - 20);
if(buffer.slice(4).toString('hex') == exeMeshPolicyGuid)
{
return (buffer.readUInt32BE(0));
}
else
{
return (0);
}
}
// Changes a Windows Executable to add the MSH inside of it.
// This method will write to destination stream and close it.
/*
@@ -152,6 +172,7 @@ function addMsh(options)
try
{
module.exports = addMsh;
module.exports.len = mshLength;
}
catch(e)
{
@@ -171,6 +192,10 @@ catch(e)
case '-i':
inputFile = process.argv[i + 1];
break;
case '-mshlen':
console.log('Integrated MSH Length: ' + mshLength());
process.exit();
break;
default:
console.log('unrecognized parameter: ' + process.argv[i]);
break;

View File

@@ -62,5 +62,57 @@ function _meshNodeId()
return (ret);
}
module.exports = _meshNodeId;
function _meshName()
{
var name = _MSH().meshServiceName;
if(name==null)
{
switch(process.platform)
{
case 'win32':
// Enumerate the registry to see if the we can find our NodeID
var reg = require('win-registry');
var nid = _meshNodeId();
var key;
var source = [reg.HKEY.LocalMachine, reg.HKEY.CurrentUser];
var val;
while (name == null && source.length > 0)
{
val = reg.QueryKey(source.shift(), 'Software\\Open Source');
for (key = 0; key < val.subkeys.length;++key)
{
try
{
if (nid == Buffer.from(reg.QueryKey(reg.HKEY.LocalMachine, 'Software\\Open Source\\' + val.subkeys[key], 'NodeId'), 'base64').toString('hex'))
{
name = val.subkeys[key];
break;
}
}
catch (ex)
{
}
}
}
break;
default:
var service = require('service-manager').manager.enumerateService();
name = 'meshagent';
for (var i = 0; i < service.length; ++i)
{
if(service[i].appLocation()==process.execPath)
{
name = service[i].name;
break;
}
}
break;
}
}
return (name);
}
module.exports = _meshNodeId;
module.exports.serviceName = _meshName;

View File

@@ -14,22 +14,31 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
function getParameter(name, parms)
{
var tokens;
for(var i=0;i<parms.length;++i)
Object.defineProperty(Array.prototype, 'getParameter',
{
tokens = parms[i].split('=');
if(tokens[0]==name)
value: function (name, defaultValue)
{
if (tokens[1].startsWith('"')) { return (tokens[1].substring(1, tokens[1].length - 1)); }
return (tokens[1]);
var i, ret;
for (i = 0; i < this.length; ++i)
{
if (this[i].startsWith('--' + name + '='))
{
ret = this[i].substring(name.length + 3);
if (ret.startsWith('"')) { ret = ret.substring(1, ret.length - 1); }
return (ret);
}
}
return (defaultValue);
}
}
return (null);
}
});
function checkParameters(parms)
{
var msh = _MSH();
if (parms.getParameter('meshServiceName', null) == null && msh.meshServiceName != null) { parms.push('--meshServiceName="' + msh.meshServiceName + '"'); }
if (parms.getParameter('companyName', null) == null && msh.companyName != null) { parms.push('--companyName="' + msh.companyName + '"'); }
}
function installService(params)
{
process.stdout.write('...Installing service');
@@ -64,25 +73,26 @@ function installService(params)
var options =
{
name: process.platform == 'win32' ? 'Mesh Agent' : 'meshagent',
name: params.getParameter('meshServiceName', process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'),
target: process.platform == 'win32' ? 'MeshAgent' : 'meshagent',
displayName: 'Mesh Agent background service',
servicePath: process.execPath,
startType: 'AUTO_START',
parameters: params
parameters: params,
_installer: true
};
options.displayName = options.name + ' background service';
if (process.platform == 'win32') { options.companyName = ''; }
if (require('fs').existsSync(proxyFile)) { options.files = [{ source: proxyFile, newName: process.platform=='win32'?'MeshAgent.proxy':'meshagent.proxy' }]; }
if (require('fs').existsSync(proxyFile)) { options.files = [{ source: proxyFile, newName: options.target + '.proxy' }]; }
var i;
if ((i = params.indexOf('--copy-msh="1"')) >= 0)
{
var mshFile = process.platform == 'win32' ? (process.execPath.split('.exe').join('.msh')) : (process.execPath + '.msh');
if (options.files == null) { options.files = []; }
options.files.push({ source: mshFile, newName: process.platform == 'win32' ? 'MeshAgent.msh' : 'meshagent.msh' });
options.files.push({ source: mshFile, newName: options.target + '.msh' });
options.parameters.splice(i, 1);
}
if ((i=params.indexOf('--_localService="1"'))>=0)
{
// install in place
@@ -123,6 +133,10 @@ function installService(params)
options.parameters.splice(i, 1);
break;
}
if(options.parameters[i].startsWith('--meshServiceName='))
{
}
}
try
{
@@ -134,7 +148,7 @@ function installService(params)
process.stdout.write(' [ERROR] ' + sie);
process.exit();
}
var svc = require('service-manager').manager.getService(process.platform=='win32'?'Mesh Agent':'meshagent');
var svc = require('service-manager').manager.getService(options.name);
if (process.platform == 'darwin')
{
svc.load();
@@ -143,7 +157,7 @@ function installService(params)
{
require('service-manager').manager.installLaunchAgent(
{
name: 'meshagent',
name: options.name,
servicePath: svc.appLocation(),
startType: 'AUTO_START',
sessionTypes: ['LoginWindow'],
@@ -161,11 +175,11 @@ function installService(params)
if(process.platform == 'win32')
{
var loc = svc.appLocation();
process.stdout.write(' -> Writing firewall rules for Mesh Agent Service...');
process.stdout.write(' -> Writing firewall rules for ' + options.name + ' Service...');
var rule =
{
DisplayName: 'Mesh Agent Management Traffic (TCP-1)',
DisplayName: options.name + ' Management Traffic (TCP-1)',
direction: 'inbound',
Program: loc,
Protocol: 'TCP',
@@ -179,7 +193,7 @@ function installService(params)
rule =
{
DisplayName: 'Mesh Agent Management Traffic (TCP-2)',
DisplayName: options.name + ' Management Traffic (TCP-2)',
direction: 'inbound',
Program: loc,
Protocol: 'TCP',
@@ -193,7 +207,7 @@ function installService(params)
rule =
{
DisplayName: 'Mesh Agent Peer-to-Peer Traffic (UDP-1)',
DisplayName: options.name + ' Peer-to-Peer Traffic (UDP-1)',
direction: 'inbound',
Program: loc,
Protocol: 'UDP',
@@ -207,7 +221,7 @@ function installService(params)
rule =
{
DisplayName: 'Mesh Agent Peer-to-Peer Traffic (UDP-2)',
DisplayName: options.name + ' Peer-to-Peer Traffic (UDP-2)',
direction: 'inbound',
Program: loc,
Protocol: 'UDP',
@@ -242,7 +256,7 @@ function uninstallService3(params)
process.stdout.write(' -> Uninstalling launch agent...');
try
{
var launchagent = require('service-manager').manager.getLaunchAgent('meshagent');
var launchagent = require('service-manager').manager.getLaunchAgent(params.getParameter('meshServiceName', 'meshagent'));
launchagent.unload();
require('fs').unlinkSync(launchagent.plist);
process.stdout.write(' [DONE]\n');
@@ -269,6 +283,7 @@ function uninstallService2(params, msh)
var dataFolder = null;
var appPrefix = null;
var uninstallOptions = null;
var serviceName = params.getParameter('meshServiceName', process.platform == 'win32' ? 'Mesh Agent' : 'meshagent');
try { require('fs').unlinkSync(msh); } catch (mshe) { }
if ((i = params.indexOf('__skipBinaryDelete')) >= 0)
@@ -296,7 +311,7 @@ function uninstallService2(params, msh)
process.stdout.write(' -> Uninstalling previous installation...');
try
{
require('service-manager').manager.uninstallService(process.platform == 'win32' ? 'Mesh Agent' : 'meshagent', uninstallOptions);
require('service-manager').manager.uninstallService(serviceName, uninstallOptions);
process.stdout.write(' [DONE]\n');
if (dataFolder && appPrefix)
{
@@ -341,7 +356,7 @@ function uninstallService2(params, msh)
try
{
process.stdout.write(' -> Checking for secondary agent...');
var s = require('service-manager').manager.getService('meshagentDiagnostic');
var s = require('service-manager').manager.getService(serviceName + 'Diagnostic');
var loc = s.appLocation();
s.close();
process.stdout.write(' [FOUND]\n');
@@ -349,7 +364,7 @@ function uninstallService2(params, msh)
secondaryagent = true;
try
{
require('service-manager').manager.uninstallService('meshagentDiagnostic');
require('service-manager').manager.uninstallService(serviceName + 'Diagnostic');
process.stdout.write(' [DONE]\n');
}
catch (e)
@@ -365,7 +380,7 @@ function uninstallService2(params, msh)
if(secondaryagent)
{
process.stdout.write(' -> removing secondary agent from task scheduler...');
var p = require('task-scheduler').delete('meshagentDiagnostic/periodicStart');
var p = require('task-scheduler').delete(serviceName + 'Diagnostic/periodicStart');
p._params = params;
p.then(function ()
{
@@ -384,7 +399,7 @@ function uninstallService2(params, msh)
}
function uninstallService(params)
{
var svc = require('service-manager').manager.getService(process.platform == 'win32' ? 'Mesh Agent' : 'meshagent');
var svc = require('service-manager').manager.getService(params.getParameter('meshServiceName', process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'));
var msh = svc.appLocation();
if (process.platform == 'win32')
{
@@ -462,10 +477,14 @@ function fullUninstall(jsonString)
var parms = JSON.parse(jsonString);
parms.push('_stop');
checkParameters(parms);
var name = parms.getParameter('meshServiceName', process.platform == 'win32' ? 'Mesh Agent' : 'meshagent');
try
{
process.stdout.write('...Checking for previous installation');
var s = require('service-manager').manager.getService(process.platform == 'win32' ? 'Mesh Agent' : 'meshagent');
process.stdout.write('...Checking for previous installation of "' + name + '"');
var s = require('service-manager').manager.getService(name);
var loc = s.appLocation();
var appPrefix = loc.split(process.platform == 'win32' ? '\\' : '/').pop();
if (process.platform == 'win32') { appPrefix = appPrefix.substring(0, appPrefix.length - 4); }
@@ -486,9 +505,13 @@ function fullUninstall(jsonString)
function fullInstall(jsonString)
{
var parms = JSON.parse(jsonString);
var loc = null;
checkParameters(parms);
if (!(getParameter('--verbose', parms) != null && parseInt(getParameter('--verbose', parms)) > 0))
var loc = null;
var i;
var name = parms.getParameter('meshServiceName', process.platform == 'win32' ? 'Mesh Agent' : 'meshagent');
if (parseInt(parms.getParameter('verbose', 0)) == 0)
{
console.setDestination(console.Destinations.DISABLED);
}
@@ -499,8 +522,8 @@ function fullInstall(jsonString)
try
{
process.stdout.write('...Checking for previous installation');
var s = require('service-manager').manager.getService(process.platform == 'win32' ? 'Mesh Agent' : 'meshagent');
process.stdout.write('...Checking for previous installation of "' + name + '"');
var s = require('service-manager').manager.getService(name);
loc = s.appLocation();
global._workingpath = s.appWorkingDirectory();
@@ -528,59 +551,106 @@ module.exports =
fullUninstall: fullUninstall
};
if (process.platform == 'win32')
function sys_update(isservice, b64)
{
function win_update()
console.setDestination(console.Destinations.LOGFILE);
var parm = b64 != null ? JSON.parse(Buffer.from(b64, 'base64').toString()) : null;
var service = null;
var serviceLocation = "";
console.log(isservice, parm);
if (isservice)
{
console.setDestination(console.Destinations.LOGFILE);
var updateLocation = process.argv[1].substring(8);
var service = null;
var serviceLocation = "";
//
// Service Mode
//
if(!global._interval)
// Check if we have sufficient permission
if(!require('user-sessions').isRoot())
{
global._interval = setInterval(win_update, 60000);
}
try
{
service = require('service-manager').manager.getService('Mesh Agent');
serviceLocation = service.appLocation();
}
catch(e)
{
console.log('Service Manager Error: ' + e);
console.log('Trying again in one minute...');
// We don't have enough permissions, so copying the binary will likely fail, and we can't start...
// This is just to prevent looping, because agentcore.c should not call us in this scenario
console.log('* insufficient permission to continue with update');
process._exit();
return;
}
service.stop().finally(function ()
var servicename = parm!=null?(parm.getParameter('meshServiceName', process.platform=='win32'?'Mesh Agent' : 'meshagent')):(process.platform == 'win32' ? 'Mesh Agent' : 'meshagent');
try
{
require('process-manager').enumerateProcesses().then(function (proc)
{
for (var p in proc)
{
if (proc[p].path == serviceLocation)
{
process.kill(proc[p].pid);
}
}
try
{
require('fs').copyFileSync(process.execPath, updateLocation);
}
catch (ce)
{
console.log('Could not copy file.. Trying again in 60 seconds');
service.close();
return;
}
service.start();
process._exit();
});
});
service = require('service-manager').manager.getService(servicename)
serviceLocation = service.appLocation();
console.log(' Updating service: ' + servicename);
}
catch(f)
{
console.log(' * ' + servicename + ' SERVICE NOT FOUND *');
process._exit();
}
}
module.exports.update = win_update;
}
if (!global._interval)
{
global._interval = setInterval(sys_update, 60000, isservice, b64);
}
if (isservice === false)
{
// Console Mode
serviceLocation = process.execPath.split('.update.exe').join('.exe');
if (serviceLocation != process.execPath)
{
try
{
require('fs').copyFileSync(process.execPath, serviceLocation);
}
catch (ce)
{
console.log('Could not copy file.. Trying again in 60 seconds');
return;
}
}
// Copied agent binary... Need to start agent in console mode
console.log('Agent update complete. Starting in console mode...');
process._exit();
return;
}
service.stop().finally(function ()
{
require('process-manager').enumerateProcesses().then(function (proc)
{
for (var p in proc)
{
if (proc[p].path == serviceLocation)
{
process.kill(proc[p].pid);
}
}
try
{
require('fs').copyFileSync(process.execPath, serviceLocation);
}
catch (ce)
{
console.log('Could not copy file.. Trying again in 60 seconds');
service.close();
return;
}
console.log('Agent update complete. Starting service...');
service.start();
process._exit();
});
});
}
module.exports.update = sys_update;

View File

@@ -2029,9 +2029,9 @@ function serviceManager()
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'EstimatedSize', Math.floor(require('fs').statSync(options.servicePath).size / 1024));
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'NoModify', 0x1);
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'NoRepair', 0x1);
if (options.name == 'Mesh Agent')
if (options.name == 'Mesh Agent' || options._installer == true)
{
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'UninstallString', options.servicePath + ' -funinstall');
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'UninstallString', options.servicePath + ' -funinstall --meshServiceName="' + options.name + '"');
}
else
{