1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2026-01-10 20:43:46 +00:00

Merge branch 'Branch_pathfix'

This commit is contained in:
Bryan Roe
2020-05-17 18:08:55 -07:00
31 changed files with 2654 additions and 2130 deletions

View File

@@ -38,10 +38,12 @@
# NOTE: If you installed jpeg8 headers on your machine, you must specify --with-jpeg8 when building turbo jpeg, otherwise omit --with-jpeg8
#
#
# Special Note about KVM Support on Linux:
# If you get an error stating that an Xauthority cannot be found, and asking if your DM is configured to use X, you may need to:
# 1. Open /etc/gdm/custom.conf and uncomment WaylandEnable=false.
# 2. Add the following line to the [daemon] section:
# Special Note about KVM Support on Linux:
# If you get an error stating that an Xauthority cannot be found, and asking if your DM is configured to use X,
# or if you get a black screen when connecting to the login screen, you may need to:
# 1. Open /etc/gdm/custom.conf or /etc/gdm3/custom.conf
# 2. Uncomment: WaylandEnable=false.
# 3. Add the following line to the [daemon] section:
# DefaultSession=gnome-xorg.desktop
#
#

View File

@@ -280,16 +280,21 @@ void KVM_PumpMessage()
DWORD WINAPI KVM_InitMessagePumpEx(LPVOID parm)
{
ATOM a;
printf("MessagePump ThreadID: %u\n", GetCurrentThreadId());
memset(&CUR_WNDCLASS, 0, sizeof(CUR_WNDCLASS));
CUR_WNDCLASS.hInstance = GetModuleHandleA(NULL);
CUR_WNDCLASS.lpszClassName = "MainWWW2Class";
CUR_WNDCLASS.cbSize = sizeof(CUR_WNDCLASS);
CUR_WNDCLASS.lpfnWndProc = KVMWindowProc;
if (RegisterClassExA(&CUR_WNDCLASS) != 0)
if ((a=RegisterClassExA(&CUR_WNDCLASS)) != 0)
{
CUR_HWND = CreateWindowExA(0x00000088, "MainWWW2Class", "TestTitle", 0x00800000, 0, 0, 100, 100, 0, 0, 0, 0);
KVM_PumpMessage();
DestroyWindow(CUR_HWND);
CUR_HWND = NULL;
UnregisterClassA((LPCSTR)a, GetModuleHandleA(NULL));
}
return(0);
}

View File

@@ -91,6 +91,8 @@ char exeMeshPolicyGuid[] = { 0xB9, 0x96, 0x01, 0x58, 0x80, 0x54, 0x4A, 0x19, 0xB
#define REMOTE_DESKTOP_STREAM "\xFF_RemoteDesktopStream"
#define REMOTE_DESKTOP_ptrs "\xFF_RemoteDesktopPTRS"
#define DEFAULT_IDLE_TIMEOUT 120
#define MESH_USER_CHANGED_CB "\xFF_MeshAgent_UserChangedCallback"
#define REMOTE_DESKTOP_UID "\xFF_RemoteDesktopUID"
#define KVM_IPC_SOCKET "\xFF_KVM_IPC_SOCKET"
int ILibDuktape_HECI_Debug = 0;
@@ -430,41 +432,7 @@ int MeshAgent_GetSystemProxy(MeshAgentHostContainer *agent, char *buffer, size_t
})();";
#else
// Linux Only
char getProxy[] = "(function getProxies(){\
if(require('fs').existsSync('/etc/environment'))\
{\
var e = require('fs').readFileSync('/etc/environment').toString();\
var tokens = e.split('\\n');\
for(var line in tokens)\
{\
var val = tokens[line].split('=');\
if(val.length == 2 && (val[0].trim() == 'http_proxy' || val[0].trim() == 'https_proxy'))\
{\
return(val[1].split('//')[1]);\
}\
}\
}\
if(require('fs').existsSync('/etc/profile.d/proxy_setup'))\
{\
var child = require('child_process').execFile('/bin/sh', ['sh']);\
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });\
child.stdin.write('cat /etc/profile.d/proxy_setup | awk \\'{ split($2, tok, \"=\"); if(tok[1]==\"http_proxy\") { print tok[2]; }}\\'\\nexit\\n');\
child.waitExit();\
child.ret = child.stdout.str.trim().split('\\n')[0].split('//')[1];\
if(child.ret != '') { return(child.ret); }\
}\
if (require('fs').existsSync('/usr/bin/gsettings'))\
{\
var setting;\
var ids = require('user-sessions').loginUids(); \
for (var i in ids)\
{\
setting = require('linux-gnome-helpers').getProxySettings(ids[i]);\
if (setting.mode == 'manual') { return(setting.host + ':' + setting.port);} \
}\
}\
throw('No Proxy set');\
})();";
char getProxy[] = "require('proxy-helper').getProxy()";
#endif
// Linux and FreeBSD
if (duk_peval_string(agent->meshCoreCtx, getProxy) == 0)
@@ -1282,6 +1250,49 @@ void ILibDuktape_MeshAgent_RemoteDesktop_SendError(RemoteDesktop_Ptrs* ptrs, cha
}
#endif
#ifdef _POSIX
extern void* kvm_relay_restart(int paused, void *processPipeMgr, ILibKVM_WriteHandler writeHandler, void *reserved, int uid, char* authToken, char *dispid);
duk_ret_t ILibDuktape_MeshAgent_userChanged(duk_context *ctx)
{
char *d, *x;
void *s;
RemoteDesktop_Ptrs *ptrs;
MeshAgentHostContainer *agent;
duk_eval_string(ctx, "require('MeshAgent')"); // [MeshAgent]
agent = (MeshAgentHostContainer*)Duktape_GetPointerProperty(ctx, -1, MESH_AGENT_PTR);
if (!duk_has_prop_string(ctx, -1, REMOTE_DESKTOP_STREAM)) { return(0); }
duk_get_prop_string(ctx, -1, REMOTE_DESKTOP_STREAM); // [MeshAgent][stream]
s = duk_get_heapptr(ctx, -1);
duk_get_prop_string(ctx, -1, REMOTE_DESKTOP_ptrs);
ptrs = (RemoteDesktop_Ptrs*)Duktape_GetBuffer(ctx, -1, NULL); // [MeshAgent][stream][ptrs]
duk_peval_string(ctx, "require('user-sessions').consoleUid()");
int id = duk_to_int(ctx, -1);
duk_eval_string(ctx, "require('monitor-info')"); //[uid][monitor-info]
duk_get_prop_string(ctx, -1, "getXInfo"); //[uid][monitor-info][getXInfo]
duk_swap_top(ctx, -2); //[uid][getXInfo][this]
duk_dup(ctx, -3); //[uid][getXInfo][this][uid]
if (duk_pcall_method(ctx, 1) != 0) { duk_eval_string(ctx, "console.log('error');"); return(0); } //[uid][xinfo]
x = Duktape_GetStringPropertyValue(ctx, -1, "xauthority", NULL);
d = Duktape_GetStringPropertyValue(ctx, -1, "display", NULL);
duk_push_heapptr(ctx, s); // [stream]
duk_push_int(ctx, id); // [stream][id]
duk_put_prop_string(ctx, -2, REMOTE_DESKTOP_UID); // [stream]
duk_pop(ctx); // ...
ILibProcessPipe_Pipe_SetBrokenPipeHandler(ptrs->kvmPipe, NULL);
ptrs->kvmPipe = kvm_relay_restart(0, agent->pipeManager, ILibDuktape_MeshAgent_RemoteDesktop_KVM_WriteSink, ptrs, id, x, d);
return(0);
}
#endif
duk_ret_t ILibDuktape_MeshAgent_getRemoteDesktop(duk_context *ctx)
{
#ifndef _LINKVM
@@ -1367,11 +1378,33 @@ duk_ret_t ILibDuktape_MeshAgent_getRemoteDesktop(duk_context *ctx)
ptrs->kvmPipe = kvm_relay_setup(agent->exePath, agent->pipeManager, ILibDuktape_MeshAgent_RemoteDesktop_KVM_WriteSink, ptrs, console_uid);
}
#else
duk_push_int(ctx, console_uid); duk_put_prop_string(ctx, -2, REMOTE_DESKTOP_UID);
duk_push_this(ctx); // [MeshAgent]
if (!duk_has_prop_string(ctx, -1, MESH_USER_CHANGED_CB))
{
duk_eval_string(ctx, "require('user-sessions')"); // [MeshAgent][usersessions]
duk_get_prop_string(ctx, -1, "on"); // [MeshAgent][usersessions][on]
duk_swap_top(ctx, -2); // [MeshAgent][on][this]
duk_push_string(ctx, "changed"); // [MeshAgent][on][this][changed]
duk_push_c_function(ctx, ILibDuktape_MeshAgent_userChanged, DUK_VARARGS); // [MeshAgent][on][this][changed][func]
duk_dup(ctx, -5); // [MeshAgent][on][this][changed][func][MeshAgent]
duk_dup(ctx, -2); // [MeshAgent][on][this][changed][func][MeshAgent][func]
duk_put_prop_string(ctx, -2, MESH_USER_CHANGED_CB); // [MeshAgent][on][this][changed][func][MeshAgent]
duk_pop(ctx); // [MeshAgent][on][this][changed][func]
duk_call_method(ctx, 2); duk_pop(ctx); // [MeshAgent]
}
duk_pop(ctx); // ...
// For Linux, we need to determine where the XAUTHORITY is:
char *updateXAuth = NULL;
char *updateDisplay = NULL;
char *xdm = NULL;
int needPop = 0;
if (getenv("XAUTHORITY") == NULL || getenv("DISPLAY") == NULL)
duk_eval_string(ctx, "require('user-sessions').Self()");
int self = duk_get_int(ctx, -1); duk_pop(ctx);
if (self==0 || getenv("XAUTHORITY") == NULL || getenv("DISPLAY") == NULL)
{
if (duk_peval_string(ctx, "require('monitor-info').getXInfo") == 0)
{
@@ -1382,6 +1415,15 @@ duk_ret_t ILibDuktape_MeshAgent_getRemoteDesktop(duk_context *ctx)
{
updateXAuth = Duktape_GetStringPropertyValue(ctx, -1, "xauthority", NULL);
updateDisplay = Duktape_GetStringPropertyValue(ctx, -1, "display", NULL);
xdm = Duktape_GetStringPropertyValue(ctx, -1, "xdm", NULL);
if (strcmp(xdm, "xwayland") == 0)
{
ILibDuktape_MeshAgent_RemoteDesktop_SendError(ptrs, "This platform is configured to use Xwayland");
ILibDuktape_MeshAgent_RemoteDesktop_SendError(ptrs, "please modify config to use Xorg");
duk_pop(ctx);
return(1);
}
if (console_uid != 0 && updateXAuth == NULL)
{
@@ -1415,7 +1457,6 @@ duk_ret_t ILibDuktape_MeshAgent_getRemoteDesktop(duk_context *ctx)
}
//MeshAgent_sendConsoleText(ctx, "Using uid: %d, XAUTHORITY: %s\n", console_uid, getenv("XAUTHORITY")==NULL? updateXAuth : getenv("XAUTHORITY"));
ptrs->kvmPipe = kvm_relay_setup(agent->pipeManager, ILibDuktape_MeshAgent_RemoteDesktop_KVM_WriteSink, ptrs, console_uid, updateXAuth, updateDisplay);
if (needPop!= 0) {duk_pop(ctx); }
#endif
@@ -2175,8 +2216,14 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent)
// Load the TLS certificate from the database. If not present, generate one.
len = ILibSimpleDataStore_Get(agent->masterDb, "SelfNodeTlsCert", ILibScratchPad2, sizeof(ILibScratchPad2));
if ((len != 0) && (util_from_p12(ILibScratchPad2, len, "hidden", &(agent->selftlscert)) == 0)) { len = 0; } // Unable to decode this certificate
if (agent_VerifyMeshCertificates(agent) != 0) { len = 0; } // Check that the load TLS cert is signed by our root.
if (len == 0) {
if (agent_VerifyMeshCertificates(agent) != 0)
{
// Check that the load TLS cert is signed by our root.
len = 0;
ILIBLOGMESSAGEX("Certificate loaded from DB was not signed by our root cert in the Cert Store");
}
if (len == 0)
{
// Generate a new TLS certificate & save it.
util_freecert(&(agent->selftlscert));
l = wincrypto_mkCert(agent->certObject, rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &str);
@@ -2185,16 +2232,33 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent)
ILibSimpleDataStore_PutEx(agent->masterDb, "SelfNodeTlsCert", 15, str, l);
}
util_free(str);
if (l <= 0) { return 1; } // Problem generating the TLS cert, reset everything.
if (l <= 0)
{
// Problem generating the TLS cert, reset everything.
ILIBLOGMESSAGEX("Error occured trying to generate a TLS cert that is signed by our root in Cert Store");
return 1;
}
}
return 0; // All good. We loaded or generated a root agent cert and TLS cert.
}
else
{
ILIBLOGMESSAGEX("No certificate found in Microsoft Certificate Store");
}
}
else
{
if (agent->noCertStore == 0 && agent->certObject == NULL)
{
ILIBLOGMESSAGEX("Error opening Microsoft Certificate Store");
}
}
#endif
// No certificate in the database. Return 1 here so we can generate one.
ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Agent_GuardPost, ILibRemoteLogging_Flags_VerbosityLevel_1, "...Failed to load Node Certificate from Database");
SSL_TRACE2("agent_LoadCertificates([ERROR: SelfNodeCert])");
ILIBLOGMESSAGEX("Info: No certificate was found in db");
return 1;
}
@@ -2341,7 +2405,7 @@ int GenerateSHA384FileHash(char *filePath, char *fileHash)
#ifdef WIN32
int retVal = 1;
fopen_s(&tmpFile, filePath, "rb");
_wfopen_s(&tmpFile, ILibUTF8ToWide(filePath, -1), L"rb");
#else
tmpFile = fopen(filePath, "rb");
#endif
@@ -3587,7 +3651,7 @@ void checkForEmbeddedMSH(MeshAgentHostContainer *agent)
int mshLen;
#ifdef WIN32
fopen_s(&tmpFile, agent->exePath, "rb");
_wfopen_s(&tmpFile, ILibUTF8ToWide(agent->exePath, -1), L"rb");
#else
tmpFile = fopen(agent->exePath, "rb");
#endif
@@ -3608,7 +3672,7 @@ void checkForEmbeddedMSH(MeshAgentHostContainer *agent)
{
FILE *msh = NULL;
#ifdef WIN32
fopen_s(&msh, MeshAgent_MakeAbsolutePath(agent->exePath, ".msh"), "wb");
_wfopen_s(&msh, ILibUTF8ToWide(MeshAgent_MakeAbsolutePath(agent->exePath, ".msh"), -1), L"wb");
#else
msh = fopen(MeshAgent_MakeAbsolutePath(agent->exePath, ".msh"), "wb");
#endif
@@ -3958,18 +4022,32 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
{
int len = (int)strnlen_s(param[ri], 4096);
int ix;
if ((ix=ILibString_IndexOf(param[ri], len, "=", 1)) > 2 && strncmp(param[ri], "--", 2)==0)
{
if (agentHost->masterDb != NULL) { ILibSimpleDataStore_Cached(agentHost->masterDb, param[ri] + 2, ix - 2, param[ri] + ix + 1, len - (ix + 1)); }
++ixr;
}
if (strcmp("-finstall", param[ri]) == 0)
if (strcmp("-finstall", param[ri]) == 0 || strcmp("-fullinstall", param[ri]) == 0)
{
installFlag = 1;
}
if (strcmp("-install", param[ri]) == 0)
{
installFlag = 5;
if (agentHost->masterDb == NULL && installFlag != 0) { agentHost->masterDb = ILibSimpleDataStore_CreateCachedOnly(); }
ILibSimpleDataStore_Cached(agentHost->masterDb, "_localService", 13, "1", 1);
}
if (strcmp("-funinstall", param[ri]) == 0 || strcmp("-fulluninstall", param[ri]) == 0)
{
installFlag = 2;
if (agentHost->masterDb == NULL && installFlag != 0) { agentHost->masterDb = ILibSimpleDataStore_CreateCachedOnly(); }
ILibSimpleDataStore_Cached(agentHost->masterDb, "_deleteData", 11, "1", 1);
}
if (strcmp("-uninstall", param[ri]) == 0)
{
installFlag = 2;
}
if (agentHost->masterDb == NULL && installFlag != 0) { agentHost->masterDb = ILibSimpleDataStore_CreateCachedOnly(); }
if ((ix = ILibString_IndexOf(param[ri], len, "=", 1)) > 2 && strncmp(param[ri], "--", 2) == 0)
{
if (agentHost->masterDb != NULL) { ILibSimpleDataStore_Cached(agentHost->masterDb, param[ri] + 2, ix - 2, param[ri] + ix + 1, len - (ix + 1)); }
++ixr;
}
}
paramLen -= ixr;
@@ -3989,6 +4067,7 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
switch (installFlag)
{
case 1:
case 5:
bufLen = ILibSimpleDataStore_Cached_GetJSONEx(agentHost->masterDb, NULL, 0);
buf = (char*)ILibMemory_SmartAllocate(bufLen);
bufLen = ILibSimpleDataStore_Cached_GetJSONEx(agentHost->masterDb, buf, bufLen);
@@ -4009,10 +4088,15 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
return(1);
break;
case 2:
bufLen = ILibSimpleDataStore_Cached_GetJSONEx(agentHost->masterDb, NULL, 0);
buf = (char*)ILibMemory_SmartAllocate(bufLen);
bufLen = ILibSimpleDataStore_Cached_GetJSONEx(agentHost->masterDb, buf, bufLen);
duk_eval_string(ctxx, "require('agent-installer');");
duk_get_prop_string(ctxx, -1, "fullUninstall");
duk_swap_top(ctxx, -2);
if (duk_pcall_method(ctxx, 0) != 0)
duk_push_string(ctxx, buf);
if (duk_pcall_method(ctxx, 1) != 0)
{
if (strcmp(duk_safe_to_string(ctxx, -1), "Process.exit() forced script termination") != 0)
{
@@ -4020,6 +4104,7 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
}
}
duk_pop(ctxx);
ILibMemory_Free(buf);
return(1);
break;
default:
@@ -4079,7 +4164,12 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
{
if (RegQueryValueExA(hKey, TEXT("ResetNodeId"), NULL, NULL, NULL, &len) == ERROR_SUCCESS && len > 0)
{
if (RegDeleteValue(hKey, TEXT("ResetNodeId")) == ERROR_SUCCESS) { resetNodeId = 1; } // Force certificate reset
if (RegDeleteValue(hKey, TEXT("ResetNodeId")) == ERROR_SUCCESS)
{
// Force certificate reset
ILIBLOGMESSAGEX("NodeID will reset, because ResetNodeID key was found in registry");
resetNodeId = 1;
}
}
RegCloseKey(hKey);
}
@@ -4091,7 +4181,11 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
int i;
// Parse command-line arguments
for (i = 0; i < paramLen; ++i) {
if (strcmp(param[i], "--resetnodeid") == 0) { resetNodeId = 1; }
if (strcmp(param[i], "--resetnodeid") == 0)
{
resetNodeId = 1;
ILIBLOGMESSAGEX("NodeID will reset, because --resetnodeid command line switch was specified");
}
}
}
#endif
@@ -4156,7 +4250,7 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
// We have at least one valid MAC address, so we can continue with the checks
i = 0;
char *curr = ILibMemory_AllocateA(len);
char *curr = ILibMemory_AllocateA(len+1);
ILibSimpleDataStore_Get(agentHost->masterDb, "LocalMacAddresses", curr, len);
while (i < len)
@@ -4167,7 +4261,11 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
}
i += 19;
}
if (i >= len) { resetNodeId = 1; ILibSimpleDataStore_PutEx(agentHost->masterDb, "LocalMacAddresses", 17, mac, (int)macLen); }
if (i >= len)
{
ILIBLOGMESSAGEX("NodeID will reset, MAC Address Mismatch: %s <==> %s", mac, curr);
resetNodeId = 1; ILibSimpleDataStore_PutEx(agentHost->masterDb, "LocalMacAddresses", 17, mac, (int)macLen);
}
}
}
}
@@ -4582,7 +4680,9 @@ void MeshAgent_ScriptMode(MeshAgentHostContainer *agentHost, int argc, char **ar
{
// Get the full path name of the JavaScript file
#ifdef WIN32
pathLen = GetFullPathName(argv[1], sizeof(ILibScratchPad2), ILibScratchPad2, NULL);
WCHAR wjsPath[4096];
GetFullPathNameW(ILibUTF8ToWide(argv[1], -1), sizeof(wjsPath) / 2, wjsPath, NULL);
pathLen = WideCharToMultiByte(CP_UTF8, 0, wjsPath, -1, (LPSTR)ILibScratchPad2, sizeof(ILibScratchPad2), NULL, NULL);
#else
if (realpath(argv[1], ILibScratchPad2) != NULL) { pathLen = strnlen_s(ILibScratchPad2, PATH_MAX); }
#endif
@@ -4596,18 +4696,6 @@ void MeshAgent_ScriptMode(MeshAgentHostContainer *agentHost, int argc, char **ar
strncpy_s(jsPath, ILibMemory_GetExtraMemorySize(jsPath), ILibScratchPad2, ILibMemory_GetExtraMemorySize(jsPath));
scriptArgs[0] = jsPath;
#ifdef WIN32
i = ILibString_LastIndexOf(ILibScratchPad2, pathLen, "\\", 1);
#else
i = ILibString_LastIndexOf(ILibScratchPad2, pathLen, "/", 1);
#endif
ILibScratchPad2[i] = 0;
#ifdef WIN32
SetCurrentDirectory(ILibScratchPad2);
#else
ignore_result(chdir(ILibScratchPad2));
#endif
// Parse arguments. Handle the ones we can, others will be passed to the JavaScript engine.
for (i = 2; i < argc; ++i)
{
@@ -4793,7 +4881,9 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
exePath[0] = 0;
#ifdef WIN32
GetModuleFileName(NULL, exePath, sizeof(exePath));
WCHAR tmpExePath[2048];
GetModuleFileNameW(NULL, tmpExePath, sizeof(tmpExePath)/2);
WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)tmpExePath, -1, (LPSTR)exePath, (int)sizeof(exePath), NULL, NULL);
#elif defined(__APPLE__)
if (_NSGetExecutablePath(exePath, &len) != 0) ILIBCRITICALEXIT(247);
exePath[(int)len] = 0;
@@ -4826,7 +4916,7 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
{
strncpy_s(ILibScratchPad2, sizeof(ILibScratchPad2), param[0], x);
ILibScratchPad2[x] = 0;
SetCurrentDirectory(ILibScratchPad2);
SetCurrentDirectoryW(ILibUTF8ToWide(ILibScratchPad2, -1));
}
#endif
@@ -4858,7 +4948,7 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
{
int i, ptr = 0;
#ifdef WIN32
STARTUPINFOA info = { sizeof(info) };
STARTUPINFOW info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
#endif
// Get the update executable path
@@ -4878,14 +4968,14 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
#ifdef WIN32
// Windows version
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s -update:\"%s\"%s", updateFilePath, agentHost->exePath, str);
if (!CreateProcessA(NULL, ILibScratchPad, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &info, &processInfo))
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.
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> FAILED..."); }
if (updateFilePath != NULL && agentHost->exePath != NULL)
{
while (util_CopyFile(agentHost->exePath, updateFilePath, FALSE) == FALSE) Sleep(5000);
if (CreateProcessA(NULL, ILibScratchPad, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &info, &processInfo))
if (CreateProcessW(NULL, ILibUTF8ToWide(ILibScratchPad, -1), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &info, &processInfo))
{
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
@@ -5003,7 +5093,7 @@ void MeshAgent_Stop(MeshAgentHostContainer *agent)
void MeshAgent_PerformSelfUpdate(char* selfpath, char* exepath, int argc, char **argv)
{
int i, ptr = 0;
STARTUPINFOA info = { sizeof(info) };
STARTUPINFOW info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
// Sleep for 5 seconds, this will give some time for the calling process to get going.
@@ -5018,7 +5108,7 @@ void MeshAgent_PerformSelfUpdate(char* selfpath, char* exepath, int argc, char *
while (util_CopyFile(selfpath, exepath, FALSE) == FALSE) Sleep(5000);
// Now run the process
if (!CreateProcessA(NULL, ILibScratchPad2, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
if (!CreateProcessW(NULL, ILibUTF8ToWide(ILibScratchPad2, -1), NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
// TODO: Failed to run update.
}

View File

@@ -152,7 +152,7 @@ int signcheck_verifysign(char* filename, int upgrade)
cert.x509 = NULL;
#ifdef WIN32
fopen_s(&pFile, filename, "rb");
_wfopen_s(&pFile, ILibUTF8ToWide(filename, -1), L"rb");
#else
pFile = fopen(filename, "rb");
#endif

View File

@@ -52,7 +52,6 @@ int ClearWindowsFirewall(wchar_t* processname);
#include <WtsApi32.h>
TCHAR* serviceFile = TEXT("Mesh Agent");
TCHAR* serviceFileOld = TEXT("Mesh Agent v2");
TCHAR* serviceName = TEXT("Mesh Agent background service");
TCHAR* serviceDesc = TEXT("Remote monitoring and management service.");
@@ -95,17 +94,18 @@ BOOL IsAdmin()
return admin;
}
BOOL RunAsAdmin(char* args) {
char szPath[_MAX_PATH + 100];
if (GetModuleFileNameA(NULL, szPath, _MAX_PATH))
BOOL RunAsAdmin(char* args, int isAdmin)
{
WCHAR szPath[_MAX_PATH + 100];
if (GetModuleFileNameW(NULL, szPath, sizeof(szPath)/2))
{
SHELLEXECUTEINFO sei = { sizeof(sei) };
SHELLEXECUTEINFOW sei = { sizeof(sei) };
sei.hwnd = NULL;
sei.nShow = SW_NORMAL;
sei.lpVerb = "runas";
sei.lpVerb = isAdmin?L"open":L"runas";
sei.lpFile = szPath;
sei.lpParameters = args;
return ShellExecuteExA(&sei);
sei.lpParameters = ILibUTF8ToWide(args, -1);
return ShellExecuteExW(&sei);
}
return FALSE;
}
@@ -375,134 +375,6 @@ int RunService(int argc, char* argv[])
return StartServiceCtrlDispatcher( serviceTable );
}
BOOL InstallService()
{
SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CREATE_SERVICE );
SERVICE_DESCRIPTION sd;
SERVICE_DELAYED_AUTO_START_INFO as;
SERVICE_FAILURE_ACTIONS fa;
SC_ACTION failactions[3];
BOOL r = FALSE;
if ( serviceControlManager )
{
char path[1024];
if (GetModuleFileName( 0, (LPTSTR)path, 1024) > 0)
{
// Install the service
SC_HANDLE service = CreateService(
serviceControlManager,
serviceFile,
serviceName,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_IGNORE,
(LPCTSTR)path,
0, 0, 0, 0, 0 );
if (service)
{
// Update the service description
sd.lpDescription = serviceDesc;
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &sd);
// Update the service auto-start
as.fDelayedAutostart = FALSE;
ChangeServiceConfig2(service, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &as);
// Update the faliure action
failactions[0].Type = SC_ACTION_RESTART;
failactions[0].Delay = 60000; // Wait 1 minutes before faliure restart (milliseconds)
failactions[1].Type = SC_ACTION_RESTART;
failactions[1].Delay = 60000; // Wait 1 minutes before faliure restart (milliseconds)
failactions[2].Type = SC_ACTION_RESTART;
failactions[2].Delay = 60000;
memset(&fa, 0, sizeof(SERVICE_FAILURE_ACTIONS));
fa.dwResetPeriod = 86400; // After 1 days, reset the faliure counters (seconds)
fa.cActions = 3;
fa.lpsaActions = failactions;
r = ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &fa);
// Cleanup
CloseServiceHandle( service );
#ifdef _DEBUG
//ILIBMESSAGE("Mesh service installed successfully");
#endif
}
else
{
#ifdef _DEBUG
if(GetLastError() == ERROR_SERVICE_EXISTS)
{
ILIBMESSAGE("Mesh service already exists.");
}
else
{
ILIBMESSAGE("Mesh service was not Installed Successfully.");
}
#endif
}
}
CloseServiceHandle( serviceControlManager );
}
return r;
}
int UninstallService(TCHAR* serviceName)
{
int r = 0;
SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CONNECT);
if (serviceControlManager)
{
SC_HANDLE service = OpenService( serviceControlManager, serviceName, SERVICE_QUERY_STATUS | DELETE );
if (service)
{
SERVICE_STATUS serviceStatusEx;
if ( QueryServiceStatus( service, &serviceStatusEx ) )
{
if ( serviceStatusEx.dwCurrentState == SERVICE_STOPPED )
{
if (DeleteService(service))
{
#ifdef _DEBUG
//ILIBMESSAGE("Mesh service removed successfully");
#endif
r = 1;
}
else
{
#ifdef _DEBUG
DWORD dwError = GetLastError();
if(dwError == ERROR_ACCESS_DENIED) {
ILIBMESSAGE("Access denied while trying to remove mesh service");
}
else if(dwError == ERROR_INVALID_HANDLE) {
ILIBMESSAGE("Handle invalid while trying to remove mesh service");
}
else if(dwError == ERROR_SERVICE_MARKED_FOR_DELETE) {
ILIBMESSAGE("Mesh service already marked for deletion");
}
#endif
}
}
else
{
r = 2;
#ifdef _DEBUG
ILIBMESSAGE("Mesh service is still running");
#endif
}
}
CloseServiceHandle( service );
}
CloseServiceHandle( serviceControlManager );
}
return r;
}
// SERVICE_STOPPED 1 The service is not running.
// SERVICE_START_PENDING 2 The service is starting.
// SERVICE_STOP_PENDING 3 The service is stopping.
@@ -596,27 +468,6 @@ int StopService(LPCSTR servicename)
return r;
}
int RunProcess(char* exe, int waitForExit)
{
BOOL r = TRUE;
int count = 50;
DWORD exitcode;
STARTUPINFOA info = {sizeof(info)};
PROCESS_INFORMATION processInfo;
if (CreateProcessA(NULL, exe, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &info, &processInfo) == 0) return 0;
if (waitForExit != 0) {
do
{
Sleep(100);
r = GetExitCodeProcess(processInfo.hProcess, &exitcode);
if (exitcode == STILL_ACTIVE) r = 0;
} while (r == 0 && count-- > 0);
}
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
return r;
}
/*
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
@@ -630,287 +481,6 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
}
*/
#ifndef _MINCORE
void fullinstall(int uninstallonly, char* proxy, int proxylen, char* tag, int taglen)
{
int r = 0;
int loops = 0;
char targetexe2[_MAX_PATH + 40];
char *targetexe = targetexe2 + 1;
size_t targetexelen = 0;
char selfexe[_MAX_PATH];
size_t selfexelen = 0;
char setup1[_MAX_PATH];
char setup2[_MAX_PATH];
int setup1len;
int setup2len;
if (IsAdmin() == FALSE) { printf("Requires administrator permissions.\r\n"); return; }
if (uninstallonly != 0) { printf("Performing uninstall...\r\n"); } else { printf("Performing install...\r\n"); }
HKEY hKey;
DWORD len = 0;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Mesh Agent", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
{
if (RegQueryValueExA(hKey, "ImagePath", NULL, NULL, NULL, &len) == ERROR_SUCCESS && len > 0)
{
char *ipath = ILibMemory_Allocate(len, 0, NULL, NULL);
RegQueryValueExA(hKey, "ImagePath", NULL, NULL, ipath, &len);
STARTUPINFOA info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s -exec \"try { require('service-manager').manager.uninstallService('meshagentDiagnostic'); require('task-scheduler').delete('meshagentDiagnostic/periodicStart').then(function(){process.exit();}, function(){process.exit();}); } catch(e){process.exit();}\"", ipath);
CreateProcessA(NULL, ILibScratchPad, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &info, &processInfo);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
free(ipath);
}
RegCloseKey(hKey);
}
// Stop and remove the service
StopService(serviceFile);
// Wait for the service to stop
int serviceStateLoopCount = 0;;
int serviceState;
do {
serviceStateLoopCount++;
Sleep(100);
serviceState = GetServiceState(serviceFile);
} while ((serviceState == 3) && (serviceStateLoopCount < 400));
UninstallService(serviceFile);
UninstallService(serviceFileOld);
// Get our own executable
selfexelen = GetModuleFileNameA(NULL, selfexe, _MAX_PATH);
// Get the target executable
if (SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, targetexe) != S_FALSE)
{
targetexe2[0] = '\"';
targetexelen = strnlen_s(targetexe, _MAX_PATH + 40);
if (targetexelen <= MAX_PATH) memcpy_s(targetexe + targetexelen, _MAX_PATH + 40 - targetexelen, "\\Mesh Agent\\MeshAgent.exe\" -uninstall", 38);
targetexelen += 25;
}
// Check if we are uninstalling ourself
if ((uninstallonly != 0) && (targetexelen == selfexelen) && (memcmp(selfexe, targetexe, targetexelen) == 0)) {
// Copy ourself to a temp folder and run full uninstall.
char tempPath[_MAX_PATH + 40];
int tempPathLen = GetTempPathA(_MAX_PATH, tempPath);
memcpy_s(tempPath + tempPathLen, _MAX_PATH + 40 - tempPathLen, "MeshAgent.exe\0", 15);
remove(tempPath);
util_CopyFile(selfexe, tempPath, FALSE);
memcpy_s(tempPath + tempPathLen, _MAX_PATH + 40 - tempPathLen, "MeshAgent.exe -fulluninstall\0", 30);
RunProcess(tempPath, 0); // Don't wait for the process to terminate since we want to self-delete.
return;
}
// Call uninstall, this will remove the firewall rules.
RunProcess(targetexe2, 1);
#ifdef _MINCORE
// Remove the MeshAgent registry keys
RegDeleteKeyEx(HKEY_LOCAL_MACHINE, "Software\\Open Source\\MeshAgent2", KEY_WOW64_32KEY, 0);
RegDeleteKeyEx(HKEY_CURRENT_USER, "Software\\Open Source\\MeshAgent2", KEY_WOW64_32KEY, 0);
#else
// Remove the MeshAgent registry keys
RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Open Source\\MeshAgent2");
RegDeleteKey(HKEY_CURRENT_USER, "Software\\Open Source\\MeshAgent2");
#endif
// Remove the uninstall icon from the control panel if present
RemoveUninstallIcon();
// Check if selfexe is already located at the target, if so, skip to copy steps.
if ((uninstallonly != 0) || (targetexelen != selfexelen) || (memcmp(selfexe, targetexe, targetexelen) != 0))
{
// Remove the target executable, wait if needed
int selfExeDelLoopCount = 0;;
int selfExeDel;
targetexe[targetexelen] = 0;
do {
Sleep(100);
selfExeDelLoopCount++;
selfExeDel = remove(targetexe);
} while ((selfExeDel != 0) && (selfExeDel != -1) && (selfExeDelLoopCount < 400));
// Remove "[Executable].msh" file
if ((setup2len = (int)strnlen_s(targetexe, _MAX_PATH + 40)) < 4 || setup2len > 259) return;
memcpy_s(setup2, sizeof(setup2), targetexe, setup2len);
memcpy_s(setup2 + (setup2len - 3), sizeof(setup2) - setup2len - 3, "msh", 4);
setup2[setup2len] = 0;
remove(setup2);
// Remove "[Executable].mshx" file
if ((setup2len = (int)strnlen_s(targetexe, _MAX_PATH + 40)) < 4 || setup2len > 259) return;
memcpy_s(setup2, sizeof(setup2), targetexe, setup2len);
memcpy_s(setup2 + (setup2len - 3), sizeof(setup2) - setup2len - 3, "mshx", 5);
setup2[setup2len + 1] = 0;
remove(setup2);
// Remove "[Executable].proxy" file
if ((setup2len = (int)strnlen_s(targetexe, _MAX_PATH + 40)) < 4 || setup2len > 257) return;
memcpy_s(setup2, sizeof(setup2), targetexe, setup2len);
memcpy_s(setup2 + (setup2len - 3), sizeof(setup2) - setup2len - 3, "proxy", 6);
setup2[setup2len + 2] = 0;
remove(setup2);
// Remove "[Executable].tag" file
if ((setup2len = (int)strnlen_s(targetexe, _MAX_PATH + 40)) < 4 || setup2len > 259) return;
memcpy_s(setup2, sizeof(setup2), targetexe, setup2len);
memcpy_s(setup2 + (setup2len - 3), sizeof(setup2) - setup2len - 3, "tag", 4);
setup2[setup2len] = 0;
remove(setup2);
// Remove "[Executable].log" file
if ((setup2len = (int)strnlen_s(targetexe, _MAX_PATH + 40)) < 4 || setup2len > 259) return;
memcpy_s(setup2, sizeof(setup2), targetexe, setup2len);
memcpy_s(setup2 + (setup2len - 3), sizeof(setup2) - setup2len - 3, "log", 4);
setup2[setup2len] = 0;
remove(setup2);
// Remove "[Executable].db" file
if ((setup2len = (int)strnlen_s(targetexe, _MAX_PATH + 40)) < 4 || setup2len > 256) return;
memcpy_s(setup2, sizeof(setup2), targetexe, setup2len);
memcpy_s(setup2 + (setup2len - 3), sizeof(setup2) - setup2len - 3, "db", 3);
setup2[setup2len] = 0;
remove(setup2);
// Remove the folder.
targetexe[targetexelen - 14] = 0;
RemoveDirectoryA(targetexe);
if (uninstallonly != 0) return;
// Get the target executable, create folders if needed
if (!CreateDirectoryA(targetexe, NULL) && GetLastError() == ERROR_ACCESS_DENIED) { ILIBMESSAGE("Access denied (1)"); return; }
targetexe[targetexelen - 14] = '\\';
// Attempt to copy our own exe over the original exe
loops = 0;
while (!util_CopyFile(selfexe, targetexe, TRUE))
{
if (GetLastError() == ERROR_ACCESS_DENIED) { ILIBMESSAGE("Access denied (2)"); return; }
if (loops++ > 5) { ILIBMESSAGE("Error copying executable file"); return; }
Sleep(5000);
}
// Try to copy "[Executable].msh" file to target directory
if ((setup1len = (int)strnlen_s(selfexe, sizeof(selfexe))) < 4) return;
memcpy_s(setup1, sizeof(setup1), selfexe, setup1len);
memcpy_s(setup1 + (setup1len - 3), sizeof(setup1) - setup1len - 3, "msh", 4);
if ((setup2len = (int)strnlen_s(targetexe, _MAX_PATH + 40)) < 4 || setup2len > 259) return;
memcpy_s(setup2, sizeof(setup2), targetexe, setup2len);
memcpy_s(setup2 + (setup2len - 3), sizeof(setup2) - setup2len - 3, "msh", 4);
util_CopyFile(setup1, setup2, TRUE);
// Write the tag if one was passed
if (tag != NULL)
{
FILE *SourceFile = NULL;
if ((setup2len = (int)strnlen_s(targetexe, _MAX_PATH + 40)) < 4 || setup2len > 259) return;
memcpy_s(setup2, sizeof(setup2), targetexe, setup2len);
memcpy_s(setup2 + (setup2len - 3), sizeof(setup2) - setup2len - 3, "tag", 4);
if (taglen > 0) {
fopen_s(&SourceFile, setup2, "wb");
if (SourceFile != NULL)
{
if (fwrite(tag, sizeof(char), taglen, SourceFile)) {}
fclose(SourceFile);
}
}
else
{
remove(setup2);
}
}
// Setup proxy filenames
if ((setup1len = (int)strnlen_s(selfexe, sizeof(selfexe))) < 4) return;
memcpy_s(setup1, sizeof(setup1), selfexe, setup1len);
memcpy_s(setup1 + (setup1len - 3), sizeof(setup1) - setup1len - 3, "proxy", 6);
if ((setup2len = (int)strnlen_s(targetexe, _MAX_PATH + 40)) < 4 || setup2len > 259) return;
memcpy_s(setup2, sizeof(setup2), targetexe, setup2len);
memcpy_s(setup2 + (setup2len - 3), sizeof(setup2) - setup2len - 3, "proxy", 6);
if (proxy != NULL && proxylen > 0)
{
// Use the specified proxy in the command line switch
FILE *SourceFile = NULL;
fopen_s(&SourceFile, setup2, "wb");
if (SourceFile != NULL)
{
if (fwrite(proxy, sizeof(char), proxylen, SourceFile)) {}
fclose(SourceFile);
}
}
else
{
// Try to copy "[Executable].proxy" file to target directory
if (util_CopyFile(setup1, setup2, TRUE) == FALSE)
{
// Failed to copy proxy file, lets try to create one.
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyEx;
if (WinHttpGetIEProxyConfigForCurrentUser(&proxyEx))
{
if (proxyEx.lpszProxy != NULL)
{
FILE *SourceFile = NULL;
size_t len;
if (wcstombs_s(&len, ILibScratchPad, 4095, proxyEx.lpszProxy, 2000) == 0)
{
char* ptr = strstr(ILibScratchPad, "https=");
if (ptr != NULL) {
char* ptr2 = strstr(ptr, ";");
ptr += 6;
if (ptr2 != NULL) ptr2[0] = 0;
} else {
ptr = ILibScratchPad;
}
fopen_s(&SourceFile, setup2, "wb");
if (SourceFile != NULL)
{
if (fwrite(ptr, sizeof(char), strnlen_s(ptr, sizeof(ILibScratchPad)), SourceFile)) {}
fclose(SourceFile);
}
}
GlobalFree(proxyEx.lpszProxy);
}
// Release the rest of the proxy settings
if (proxyEx.lpszAutoConfigUrl != NULL) GlobalFree(proxyEx.lpszAutoConfigUrl);
if (proxyEx.lpszProxyBypass != NULL) GlobalFree(proxyEx.lpszProxyBypass);
}
}
}
}
// Add the uninstall icon in the control panel
AddUninstallIcon();
UpdateOwnerData();
/*
#if defined(_LINKVM)
// Setup the SendSAS permission
kvm_setupSasPermissions();
#endif
*/
// Attempt to start the updated service up again
memcpy(targetexe + targetexelen, "\" -install", 11);
r = RunProcess(targetexe2, 1);
memcpy(targetexe + targetexelen, "\" -start", 9);
r = RunProcess(targetexe2, 1);
}
#endif
ILibTransport_DoneState kvm_serviceWriteSink(char *buffer, int bufferLen, void *reserved)
{
@@ -955,7 +525,9 @@ int wmain(int argc, char* wargv[])
WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)wargv[argvi], -1, argv[argvi], argvsz, NULL, NULL);
}
if (argc > 1 && (strcasecmp(argv[1], "-finstall") == 0 || strcasecmp(argv[1], "-funinstall") == 0 || strcasecmp(argv[1], "-fulluninstall") == 0))
if (argc > 1 && (strcasecmp(argv[1], "-finstall") == 0 || strcasecmp(argv[1], "-funinstall") == 0 ||
strcasecmp(argv[1], "-fulluninstall") == 0 || strcasecmp(argv[1], "-fullinstall") == 0 ||
strcasecmp(argv[1], "-install")==0 || strcasecmp(argv[1], "-uninstall") == 0))
{
argv[argc] = argv[1];
argv[1] = (char*)ILibMemory_SmartAllocate(4);
@@ -1278,69 +850,6 @@ int wmain(int argc, char* wargv[])
else if (r == 2) { printf("Mesh agent failed to stop"); }
}
}
else if (argc > 1 && strcasecmp(argv[1], "-install") == 0)
{
// Setup the service
StopService(serviceFile);
UninstallService(serviceFile);
UninstallService(serviceFileOld);
if (InstallService() == TRUE) { printf("Mesh agent installed"); } else { printf("Failed to install mesh agent"); }
#ifndef _MINCORE
// Setup the Windows firewall
if (GetModuleFileNameW(NULL, str, _MAX_PATH) > 5)
{
ClearWindowsFirewall(str);
if (SetupWindowsFirewall(str) != 0)
{
#ifdef _DEBUG
ILIBMESSAGE("Firewall rules added successfully");
#endif
}
else
{
#ifdef _DEBUG
ILIBMESSAGE("Unable to add firewall rules");
#endif
}
}
#endif
}
else if (argc > 1 && ((strcasecmp(argv[1], "-remove") == 0) || (strcasecmp(argv[1], "-uninstall") == 0)))
{
// Ask the service manager to stop the service
StopService(serviceFile);
// Remove the service
UninstallService(serviceFileOld);
i = UninstallService(serviceFile);
if (i == 0) { printf("Failed to uninstall mesh agent"); }
else if (i == 1) { printf("Mesh agent uninstalled"); }
else if (i == 2) { printf("Mesh agent still running"); }
#ifndef _MINCORE
// Remove the MeshAgent registry keys
RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Open Source\\MeshAgent2");
RegDeleteKey(HKEY_CURRENT_USER, "Software\\Open Source\\MeshAgent2");
// Cleanup the firewall rules
if (GetModuleFileNameW( NULL, str, _MAX_PATH ) > 5)
{
if (ClearWindowsFirewall(str) != 0)
{
#ifdef _DEBUG
ILIBMESSAGE("Firewall rules removed successfully");
#endif
}
else
{
#ifdef _DEBUG
ILIBMESSAGE("Unable to remove firewall rules");
#endif
}
}
#endif
}
#ifdef _MINCORE
else if (argc > 1 && memcmp(argv[1], "-update:", 8) == 0)
{
@@ -1366,14 +875,6 @@ int wmain(int argc, char* wargv[])
int len = MeshInfo_GetSystemInformation(&data);
if (len > 0) { printf(data); }
}
else if (argc > 1 && (strcasecmp(argv[1], "-fullinstall") == 0))
{
fullinstall( 0, proxyarg, (int)strnlen_s(proxyarg, _MAX_PATH), tagarg, (int)strnlen_s(tagarg, _MAX_PATH));
}
else if (argc > 1 && (strcasecmp(argv[1], "-fulluninstall") == 0))
{
fullinstall(1, NULL, 0, NULL, 0);
}
else if (argc > 1 && (strcasecmp(argv[1], "-setfirewall") == 0))
{
// Reset the firewall rules
@@ -1486,8 +987,6 @@ int wmain(int argc, char* wargv[])
}
else
{
UninstallService(serviceFileOld);
// See if we are running as a service
if (RunService(argc, argv) == 0 && GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
{
@@ -1522,6 +1021,27 @@ int wmain(int argc, char* wargv[])
else
{
FreeConsole();
HMODULE shCORE = LoadLibraryExA((LPCSTR)"Shcore.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
DpiAwarenessFunc dpiAwareness = NULL;
if (shCORE != NULL)
{
if ((dpiAwareness = (DpiAwarenessFunc)GetProcAddress(shCORE, (LPCSTR)"SetProcessDpiAwareness")) == NULL)
{
FreeLibrary(shCORE);
shCORE = NULL;
}
}
if (dpiAwareness != NULL)
{
dpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
FreeLibrary(shCORE);
shCORE = NULL;
}
else
{
SetProcessDPIAware();
}
DialogBox(NULL, MAKEINTRESOURCE(IDD_INSTALLDIALOG), NULL, DialogHandler);
}
}
@@ -1548,7 +1068,7 @@ char* getMshSettings(char* fileName, char* selfexe, char** meshname, char** mesh
char exeMeshPolicyGuid[] = { 0xB9, 0x96, 0x01, 0x58, 0x80, 0x54, 0x4A, 0x19, 0xB7, 0xF7, 0xE9, 0xBE, 0x44, 0x91, 0x4C, 0x19 };
char tmpHash[16];
fopen_s(&tmpFile, selfexe, "rb");
_wfopen_s(&tmpFile, ILibUTF8ToWide(selfexe, -1), L"rb");
if (tmpFile == NULL) { return NULL; } // Could not open our own executable
fseek(tmpFile, -16, SEEK_END);
@@ -1612,9 +1132,8 @@ DWORD WINAPI StartTempAgent(_In_ LPVOID lpParameter)
{
ILib_DumpEnabledContext winException;
char selfexe[_MAX_PATH];
char *selfexe_ptr[] = { selfexe };
char *selfexe_ptr[] = { selfexe, "--disableUpdate=1", "--serviceTemp=1" };
WCHAR str[_MAX_PATH];
size_t len;
char *integratedJavaScript;
int integragedJavaScriptLen;
char setup1[_MAX_PATH];
@@ -1625,7 +1144,7 @@ DWORD WINAPI StartTempAgent(_In_ LPVOID lpParameter)
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
// Get our own executable name
if (GetModuleFileNameW(NULL, str, _MAX_PATH) > 5) { wcstombs_s(&len, selfexe, _MAX_PATH, str, _MAX_PATH); }
if (GetModuleFileNameW(NULL, str, _MAX_PATH) > 5) { ILibWideToUTF8Ex(str, -1, selfexe, sizeof(selfexe)); }
// Setup proxy filenames
if ((setup1len = (int)strnlen_s(selfexe, sizeof(selfexe))) >= 4) {
@@ -1653,7 +1172,7 @@ DWORD WINAPI StartTempAgent(_In_ LPVOID lpParameter)
{
ptr = ILibScratchPad;
}
fopen_s(&SourceFile, setup1, "wb");
_wfopen_s(&SourceFile, ILibUTF8ToWide(setup1, -1), L"wb");
if (SourceFile != NULL)
{
if (fwrite(ptr, sizeof(char), strnlen_s(ptr, sizeof(ILibScratchPad)), SourceFile)) {}
@@ -1676,7 +1195,7 @@ DWORD WINAPI StartTempAgent(_In_ LPVOID lpParameter)
agent->meshCoreCtx_embeddedScript = integratedJavaScript;
agent->meshCoreCtx_embeddedScriptLen = integragedJavaScriptLen;
agent->runningAsConsole = 1;
MeshAgent_Start(agent, 1, selfexe_ptr);
MeshAgent_Start(agent, 3, selfexe_ptr);
//retCode = agent->exitCode;
MeshAgent_Destroy(agent);
agent = NULL;
@@ -1738,9 +1257,10 @@ INT_PTR CALLBACK DialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP
SetWindowTextA( GetDlgItem( hDlg, IDC_STATUSTEXT ), txt);
// Get current executable path
GetModuleFileNameA(NULL, selfexe, MAX_PATH);
WCHAR wselfexe[MAX_PATH];
GetModuleFileNameW(NULL, wselfexe, sizeof(wselfexe) / 2);
ILibWideToUTF8Ex(wselfexe, -1, selfexe, (int)sizeof(selfexe));
fileName = MeshAgent_MakeAbsolutePath(selfexe, ".msh");
{
DWORD dwSize = 0;
BYTE *pVersionInfo = NULL;
@@ -1748,10 +1268,10 @@ INT_PTR CALLBACK DialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP
UINT pLenFileInfo = 0;
int major, minor, hotfix, other;
if ((dwSize = GetFileVersionInfoSize(selfexe, NULL)))
if ((dwSize = GetFileVersionInfoSizeW(wselfexe, NULL)))
{
if ((pVersionInfo = malloc(dwSize)) == NULL) { ILIBCRITICALEXIT(254); }
if (GetFileVersionInfo(selfexe, 0, dwSize, pVersionInfo))
if (GetFileVersionInfoW(wselfexe, 0, dwSize, pVersionInfo))
{
if (VerQueryValue(pVersionInfo, TEXT("\\"), (LPVOID*)&pFileInfo, &pLenFileInfo))
{
@@ -1830,16 +1350,13 @@ INT_PTR CALLBACK DialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP
EnableWindow( GetDlgItem( hDlg, IDC_UNINSTALLBUTTON ), FALSE );
EnableWindow( GetDlgItem( hDlg, IDCANCEL ), FALSE );
if (IsAdmin() == TRUE)
if (LOWORD(wParam) == IDC_INSTALLBUTTON)
{
// We are already administrator, just install/uninstall now.
if (LOWORD(wParam) == IDC_INSTALLBUTTON) { fullinstall(0, NULL, 0, NULL, 0); } else { fullinstall(1, NULL, 0, NULL, 0); }
result = TRUE;
result = RunAsAdmin("-fullinstall", IsAdmin() == TRUE);
}
else
{
// We need to request admin escalation
if (LOWORD(wParam) == IDC_INSTALLBUTTON) { result = RunAsAdmin("-fullinstall"); } else { result = RunAsAdmin("-fulluninstall"); }
result = RunAsAdmin("-fulluninstall", IsAdmin() == TRUE);
}
if (result)

View File

@@ -110,38 +110,15 @@ void ILibDuktape_ChildProcess_SubProcess_ExitHandler(ILibProcessPipe_Process sen
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
if (!ILibMemory_CanaryOK(p)) { return; }
#ifdef WIN32
if (duk_ctx_context_data(p->ctx)->apc_flags == 0 && p->dispatchFlags == 0)
{
// This method was called with an APC, but this thread was running an unknown alertable method when it was interrupted
// So we must unwind the stack, and use a non-apc method to re-dispatch to this thread, becuase we can't risk
// calling a winsock method, in case this thread was inside winsock when it was interrupted, because otherwise, it
// will corrupt memory, resulting in a possible crash.
//
// We had to do the APC first, becuase otherwise child_process.waitExit() will not work, becuase that method is blocking
// the event loop thread with an alertable wait object, so APC is the only way to propagate this event
p->exitCode = exitCode;
p->dispatchFlags = 1;
Duktape_RunOnEventLoop(p->chain, duk_ctx_nonce(p->ctx), p->ctx, ILibDuktape_ChildProcess_SubProcess_ExitHandler_sink1, NULL, p);
}
#endif
p->exitCode = exitCode;
p->childProcess = NULL;
duk_push_heapptr(p->ctx, p->subProcess); // [childProcess]
#ifdef WIN32
HANDLE exitptr = (HANDLE)Duktape_GetPointerProperty(p->ctx, -1, "\xFF_WaitExit");
if (exitptr != NULL)
{
SetEvent(exitptr);
}
#else
if (Duktape_GetIntPropertyValue(p->ctx, -1, "\xFF_WaitExit", 0) != 0)
{
ILibChain_EndContinue(Duktape_GetChain(p->ctx));
}
#endif
duk_get_prop_string(p->ctx, -1, "emit"); // [childProcess][emit]
duk_swap_top(p->ctx, -2); // [emit][this]
duk_push_string(p->ctx, "exit"); // [emit][this][exit]
@@ -185,6 +162,7 @@ duk_ret_t ILibDuktape_ChildProcess_Kill(duk_context *ctx)
}
duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx)
{
int timeout = duk_is_number(ctx, 0) ? duk_require_int(ctx, 0) : -1;
void *chain = Duktape_GetChain(ctx);
if (ILibIsChainBeingDestroyed(chain))
{
@@ -192,29 +170,23 @@ duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx)
}
duk_push_this(ctx); // [spawnedProcess]
char *_target = Duktape_GetStringPropertyValue(ctx, -1, "_target", NULL);
if (!ILibChain_IsLinkAlive(Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager)))
{
return(ILibDuktape_Error(ctx, "Cannot waitExit() because JS Engine is exiting"));
}
#ifdef WIN32
DWORD result;
HANDLE eptr = CreateEventA(NULL, TRUE, FALSE, NULL);
duk_push_pointer(ctx, (void*)eptr);
#else
duk_push_int(ctx, 1); // [spawnedProcess][flag]
#endif
duk_put_prop_string(ctx, -2, "\xFF_WaitExit"); // [spawnedProcess]
#ifdef WIN32
duk_ctx_context_data(ctx)->apc_flags = 1;
while ((result=WaitForSingleObjectEx(eptr, duk_is_number(ctx, 0) ? duk_require_int(ctx, 0) : INFINITE, TRUE)) != WAIT_OBJECT_0 && result != WAIT_TIMEOUT);
duk_ctx_context_data(ctx)->apc_flags = 0;
CloseHandle(eptr);
if (result == WAIT_TIMEOUT) { return(ILibDuktape_Error(ctx, "timeout")); }
#else
void *mods[] = { ILibGetBaseTimer(Duktape_GetChain(ctx)), Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager) };
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, -1);
#ifdef WIN32
HANDLE handles[] = { NULL, NULL, NULL, NULL, NULL };
ILibProcessPipe_Process p = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Process);
ILibProcessPipe_Process_GetWaitHandles(p, &(handles[0]), &(handles[1]), &(handles[2]), &(handles[3]));
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, timeout, (HANDLE**)handles);
#else
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, timeout);
#endif
return(0);
@@ -432,6 +404,7 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
return(ILibDuktape_Error(ctx, "child_process.execFile(): Could not exec [%s]", target));
}
ILibDuktape_ChildProcess_SpawnedProcess_PUSH(ctx, p, callback);
duk_push_string(ctx, target); duk_put_prop_string(ctx, -2, "_target");
duk_push_pointer(ctx, manager); duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_Manager);
return(1);
}

View File

@@ -160,6 +160,8 @@ ILibTransport_DoneState ILibDuktape_HECI_Session_WriteHandler_Process(ILibDuktap
extern int ILibDuktape_HECI_Debug;
#ifdef WIN32
BOOL ILibDuktape_HECI_Session_ReceiveSink(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user);
HANDLE ILibDuktape_HECI_windowsInit()
{
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail = NULL;
@@ -284,7 +286,7 @@ void ILibDuktape_HECI_Session_EmitStreamReady(void *chain, void *session)
}
#ifdef WIN32
BOOL ILibDuktape_HECI_Session_WriteHandler_Ready(HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user)
BOOL ILibDuktape_HECI_Session_WriteHandler_Ready(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user)
{
if (errors != ILibWaitHandle_ErrorStatus_NONE) { return(FALSE); }
@@ -293,8 +295,8 @@ BOOL ILibDuktape_HECI_Session_WriteHandler_Ready(HANDLE event, ILibWaitHandle_Er
if (!ILibMemory_CanaryOK(session)) { return(FALSE); }
ILibProcessPipe_WaitHandle_Remove(session->mgr, session->wv.hEvent);
ILibChain_RemoveWaitHandle(session->chain, session->wv.hEvent);
if (session->noPipelining == 0)
{
ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)ILibQueue_DeQueue(session->PendingWrites);
@@ -378,7 +380,7 @@ ILibTransport_DoneState ILibDuktape_HECI_Session_WriteHandler_Process(ILibDuktap
{
// Not done writing
retVal = ILibTransport_DoneState_INCOMPLETE;
ILibProcessPipe_WaitHandle_Add(session->mgr, session->wv.hEvent, session, ILibDuktape_HECI_Session_WriteHandler_Ready);
ILibChain_AddWaitHandle(session->chain, session->wv.hEvent, -1, ILibDuktape_HECI_Session_WriteHandler_Ready, session);
}
else
{
@@ -471,7 +473,7 @@ ILibTransport_DoneState ILibDuktape_HECI_Session_WriteSink(ILibDuktape_DuplexStr
{
#if defined(WIN32)
state->returnIgnored = 1;
QueueUserAPC((PAPCFUNC)ILibDuktape_HECI_Session_WriteHandler, ILibProcessPipe_Manager_GetWorkerThread(session->mgr), (ULONG_PTR)state);
ILibDuktape_HECI_Session_WriteHandler((ULONG_PTR)state);
#elif defined(_POSIX)
if (ILibIsRunningOnChainThread(stream->readableStream->chain) != 0)
{
@@ -520,20 +522,6 @@ void ILibDuktape_HECI_Session_PauseSink(ILibDuktape_DuplexStream *sender, void *
UNREFERENCED_PARAMETER(user);
#endif
}
#ifdef WIN32
BOOL ILibDuktape_HECI_Session_ReceiveSink(HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user);
void __stdcall ILibDuktape_HECI_Session_ResumeSink2(ULONG_PTR obj)
{
//if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Session_ResumeSink2()\n"); }
ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)obj;
BOOL result = ReadFile(session->descriptor, session->buffer, (DWORD)session->bufferSize, &(session->bytesRead), &(session->v));
if (result == TRUE || GetLastError() == ERROR_IO_PENDING)
{
//if (ILibDuktape_HECI_Debug) { printf("...[Wait Handle Added]\n"); }
ILibProcessPipe_WaitHandle_Add(session->mgr, session->v.hEvent, session, ILibDuktape_HECI_Session_ReceiveSink);
}
}
#endif
void ILibDuktape_HECI_Session_ResumeSink_NoPipeline(void *chain, void *user)
{
// This is always called from the Microstack Thread
@@ -555,13 +543,16 @@ void ILibDuktape_HECI_Session_ResumeSink(ILibDuktape_DuplexStream *sender, void
ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user;
if (session->noPipelining != 0)
{
Duktape_RunOnEventLoop(sender->readableStream->chain, duk_ctx_nonce(sender->readableStream->ctx), sender->readableStream->ctx, ILibDuktape_HECI_Session_ResumeSink_NoPipeline, NULL, session);
// Note: DO NOT 'return' here, because we still need to QueueUserAPC, to resume the stream on Windows
ILibDuktape_HECI_Session_ResumeSink_NoPipeline(sender->readableStream->chain, session);
}
#ifdef WIN32
// To Resume, we need to first context switch to the Windows Thread
QueueUserAPC((PAPCFUNC)ILibDuktape_HECI_Session_ResumeSink2, ILibProcessPipe_Manager_GetWorkerThread(session->mgr), (ULONG_PTR)session);
BOOL result = ReadFile(session->descriptor, session->buffer, (DWORD)session->bufferSize, &(session->bytesRead), &(session->v));
if (result == TRUE || GetLastError() == ERROR_IO_PENDING)
{
//if (ILibDuktape_HECI_Debug) { printf("...[Wait Handle Added]\n"); }
ILibChain_AddWaitHandle(session->chain, session->v.hEvent, -1, ILibDuktape_HECI_Session_ReceiveSink, session);
}
#endif
}
#ifdef WIN32
@@ -576,7 +567,7 @@ void ILibDuktape_HECI_Session_ReceiveSink2(void *chain, void *user)
ILibDuktape_HECI_Session_ResumeSink(session->stream, session->stream->user);
}
}
BOOL ILibDuktape_HECI_Session_ReceiveSink(HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user)
BOOL ILibDuktape_HECI_Session_ReceiveSink(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user)
{
//if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Session_ReceiveSink\n"); }
if (errors != ILibWaitHandle_ErrorStatus_NONE)
@@ -589,7 +580,14 @@ BOOL ILibDuktape_HECI_Session_ReceiveSink(HANDLE event, ILibWaitHandle_ErrorStat
ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user;
if (ILibMemory_CanaryOK(session))
{
if (GetOverlappedResult(session->descriptor, &(session->v), &(session->bytesRead), FALSE) == TRUE) { Duktape_RunOnEventLoop(session->chain, duk_ctx_nonce(session->stream->readableStream->ctx), session->stream->readableStream->ctx, ILibDuktape_HECI_Session_ReceiveSink2, NULL, session); }
if (GetOverlappedResult(session->descriptor, &(session->v), &(session->bytesRead), FALSE) == TRUE)
{
ILibDuktape_DuplexStream_WriteData(session->stream, session->buffer, session->bytesRead);
if (session->stream != NULL && !session->stream->readableStream->paused)
{
ILibDuktape_HECI_Session_ResumeSink(session->stream, session->stream->user);
}
}
}
return(FALSE);
}
@@ -601,7 +599,7 @@ void __stdcall ILibDuktape_HECI_Session_Start(ULONG_PTR obj)
BOOL result = ReadFile(session->descriptor, session->buffer, (DWORD)session->bufferSize, &bytesRead, &(session->v));
//if (ILibDuktape_HECI_Debug) { printf("...[WaitHandle Added]\n"); }
ILibProcessPipe_WaitHandle_Add(session->mgr, session->v.hEvent, session, ILibDuktape_HECI_Session_ReceiveSink);
ILibChain_AddWaitHandle(session->chain, session->v.hEvent, -1, ILibDuktape_HECI_Session_ReceiveSink, session);
}
#endif
@@ -677,7 +675,7 @@ duk_ret_t ILibDuktape_HECI_create_OnClientConnect(duk_context *ctx)
duk_get_prop_string(ctx, -1, ILibDuktape_HECI_ChildProcess); // [HECI][childProcess]
duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager); // [HECI][childProcess][manager]
session->mgr = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
QueueUserAPC((PAPCFUNC)ILibDuktape_HECI_Session_Start, ILibProcessPipe_Manager_GetWorkerThread(session->mgr), (ULONG_PTR)session);
ILibDuktape_HECI_Session_Start((ULONG_PTR)session);
#else
duk_push_this(ctx); // [HECI]
session->descriptor = Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_HECI_Descriptor, -1);
@@ -756,10 +754,10 @@ duk_ret_t ILibDuktape_HECI_Session_close(duk_context *ctx)
duk_get_prop_string(ctx, -1, ILibDuktape_HECI_SessionMemPtr); // [HECI][SESSION]
session = (ILibDuktape_HECI_Session*)Duktape_GetBuffer(ctx, -1, NULL);
ILibProcessPipe_WaitHandle_Remove(session->mgr, session->v.hEvent);
ILibProcessPipe_WaitHandle_Remove(session->mgr, session->wv.hEvent);
ILibChain_RemoveWaitHandle(session->chain, session->v.hEvent);
ILibChain_RemoveWaitHandle(session->chain, session->wv.hEvent);
session->stream = NULL;
QueueUserAPC((PAPCFUNC)ILibDuktape_HECI_Session_CloseSink2, ILibProcessPipe_Manager_GetWorkerThread(session->mgr), (ULONG_PTR)session->descriptor);
CloseHandle(session->descriptor);
}
#else
int d = Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_HECI_Descriptor, -1);
@@ -851,7 +849,7 @@ void ILibDuktape_HECI_IoctlHandler_Dispatch(void *chain, void *user)
}
#ifdef WIN32
void ILibDuktape_HECI_NextIoctl(ILibQueue q);
BOOL ILibDuktape_HECI_IoctlHandler(HANDLE h, ILibWaitHandle_ErrorStatus errors, void *user)
BOOL ILibDuktape_HECI_IoctlHandler(void * chain, HANDLE h, ILibWaitHandle_ErrorStatus errors, void *user)
{
if (errors == ILibWaitHandle_ErrorStatus_INVALID_HANDLE || errors == ILibWaitHandle_ErrorStatus_REMOVED) { return(FALSE); }
if (!ILibMemory_CanaryOK(user)) { return(FALSE); }
@@ -870,7 +868,7 @@ BOOL ILibDuktape_HECI_IoctlHandler(HANDLE h, ILibWaitHandle_ErrorStatus errors,
}
ILibQueue_DeQueue(data->Q);
ILibProcessPipe_WaitHandle_Remove(data->pipeManager, h);
ILibChain_RemoveWaitHandle(data->chain, h);
if (data->abort != 0 || !ILibMemory_CanaryOK(data->reserved))
{
@@ -888,7 +886,7 @@ BOOL ILibDuktape_HECI_IoctlHandler(HANDLE h, ILibWaitHandle_ErrorStatus errors,
return(FALSE);
}
Duktape_RunOnEventLoop(data->chain, data->ctxnonce, data->ctx, ILibDuktape_HECI_IoctlHandler_Dispatch, NULL, data);
ILibDuktape_HECI_IoctlHandler_Dispatch(data->chain, data);
if (ILibQueue_GetCount(Q) > 0)
{
@@ -906,8 +904,7 @@ void ILibDuktape_HECI_NextIoctl(ILibQueue q)
ResetEvent(data->v.hEvent);
res = DeviceIoControl(data->device, (DWORD)data->code, data->buffer, (DWORD)data->bufferLen, data->outBuffer, (DWORD)data->outBufferLen, &(data->bytesReceived), &(data->v));
ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(data->pipeManager, data->v.hEvent, 2000, data, ILibDuktape_HECI_IoctlHandler);
ILibChain_AddWaitHandle(data->chain, data->v.hEvent, 2000, ILibDuktape_HECI_IoctlHandler, data);
}
void __stdcall ILibDuktape_HECI_apc_AddIoctl(ULONG_PTR obj)
{
@@ -1031,7 +1028,8 @@ duk_ret_t ILibDuktape_HECI_doIoctl(duk_context *ctx)
duk_get_prop_string(ctx, -2, ILibDuktape_HECI_ChildProcess); // [heci][stash][childProcess]
duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager); // [heci][stash][childProcess][manager]
data->pipeManager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
QueueUserAPC((PAPCFUNC)ILibDuktape_HECI_apc_AddIoctl, ILibProcessPipe_Manager_GetWorkerThread(data->pipeManager), (ULONG_PTR)data);
ILibDuktape_HECI_apc_AddIoctl((ULONG_PTR)data);
#elif defined(_POSIX)
ILibDuktape_HECI_AddIoctl(data);
#endif
@@ -1074,8 +1072,8 @@ duk_ret_t ILibDuktape_HECI_Finalizer(duk_context *ctx)
#ifdef WIN32
ILibQueue Q = (ILibQueue)Duktape_GetPointerProperty(ctx, 0, ILibDuktape_HECI_Q);
duk_get_prop_string(ctx, 0, ILibDuktape_HECI_ChildProcess);
ILibProcessPipe_Manager mgr = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager);
if (mgr != NULL) { QueueUserAPC((PAPCFUNC)ILibDuktape_HECI_Finalizer2, ILibProcessPipe_Manager_GetWorkerThread(mgr), (ULONG_PTR)Q); }
ILibProcessPipe_Manager mgr = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager);
ILibDuktape_HECI_Finalizer2((ULONG_PTR)Q);
#else
duk_get_prop_string(ctx, 0, ILibDuktape_HECI_Q);
ILibQueue_Destroy((ILibQueue)duk_get_pointer(ctx, -1));

View File

@@ -93,6 +93,9 @@ void *Duktape_Duplicate_GetBufferPropertyEx(duk_context *ctx, duk_idx_t i, char*
char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *len);
#define Duktape_Duplicate_GetString(ctx, i) Duktape_Duplicate_GetStringEx(ctx, i, NULL)
#define duk_array_shift(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "shift");duk_swap_top(ctx, -2);duk_call_method(ctx, 0);
#define duk_array_pop(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "pop");duk_swap_top(ctx, -2);duk_call_method(ctx, 0);
int Duktape_GetBooleanProperty(duk_context *ctx, duk_idx_t i, char *propertyName, int defaultValue);
struct sockaddr_in6* Duktape_IPAddress4_FromString(char* address, unsigned short port);
struct sockaddr_in6* Duktape_IPAddress6_FromString(char* address, unsigned short port);

File diff suppressed because one or more lines are too long

View File

@@ -260,7 +260,7 @@ void ILibDuktape_ScriptContainer_GetEmbeddedJS_Raw(char *exePath, char **script,
int integratedJavaScriptLen = 0;
FILE* tmpFile = NULL;
fopen_s(&tmpFile, exePath, "rb");
_wfopen_s(&tmpFile, ILibUTF8ToWide(exePath, -1), L"rb");
if (tmpFile != NULL)
{
// Read the PE Headers, to determine where to look for the Embedded JS
@@ -338,7 +338,7 @@ void ILibDuktape_ScriptContainer_CheckEmbeddedEx(char *exePath, char **script, i
{
i = sprintf_s(g_AgentCrashID, sizeof(g_AgentCrashID), "%s_", exePath);
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s.exe", exePath);
fopen_s(&tmpFile, ILibScratchPad, "rb");
_wfopen_s(&tmpFile, ILibUTF8ToWide(ILibScratchPad, -1), L"rb");
}
else
{
@@ -373,7 +373,7 @@ void ILibDuktape_ScriptContainer_CheckEmbeddedEx(char *exePath, char **script, i
}
#ifdef WIN32
fopen_s(&tmpFile, exePath, "rb");
_wfopen_s(&tmpFile, ILibUTF8ToWide(exePath, -1), L"rb");
#else
tmpFile = fopen(exePath, "rb");
#endif
@@ -465,13 +465,15 @@ void ILibDuktape_ScriptContainer_CheckEmbedded(char **script, int *scriptLen)
// Check if .JS file is integrated with executable
#ifndef __APPLE__
char exePath[_MAX_PATH];
char exePath[_MAX_PATH*2];
#else
char exePath[PATH_MAX+1];
#endif
#ifdef WIN32
GetModuleFileName(NULL, exePath, sizeof(exePath));
WCHAR tmpExePath[_MAX_PATH];
GetModuleFileNameW(NULL, tmpExePath, sizeof(tmpExePath)/2);
WideCharToMultiByte(CP_UTF8, 0, tmpExePath, -1, exePath, sizeof(exePath), NULL, NULL);
#elif defined(__APPLE__)
uint32_t len = sizeof(exePath);
if (_NSGetExecutablePath(exePath, &len) != 0) ILIBCRITICALEXIT(247);
@@ -500,6 +502,18 @@ void ILibDuktape_ScriptContainer_Process_ExitCallback(void *obj)
Duktape_SafeDestroyHeap(ctx);
}
}
duk_ret_t ILibDuktape_ScriptContainer_Process_ExitEx(duk_context *ctx)
{
if (duk_is_number(ctx, 0))
{
exit(duk_require_int(ctx, 0));
}
else
{
exit(0);
}
return(0);
}
duk_ret_t ILibDuktape_ScriptContainer_Process_Exit(duk_context *ctx)
{
void **tmp;
@@ -861,16 +875,23 @@ duk_ret_t ILibDuktape_ScriptContainer_Process_Kill(duk_context *ctx)
duk_ret_t ILibDuktape_Process_cwd(duk_context *ctx)
{
#ifdef WIN32
GetCurrentDirectoryA((DWORD)sizeof(ILibScratchPad), ILibScratchPad);
duk_push_string(ctx, ILibScratchPad);
return(1);
#elif defined(_POSIX)
GetCurrentDirectoryW((DWORD)sizeof(ILibScratchPad)/2, (LPWSTR)ILibScratchPad);
ILibDuktape_String_PushWideString(ctx, ILibScratchPad, 0);
#else
ignore_result((uintptr_t)getcwd(ILibScratchPad, sizeof(ILibScratchPad)));
duk_push_string(ctx, ILibScratchPad);
return(1);
#else
return(ILibDuktape_Error(ctx, "Error"));
#endif
duk_get_prop_string(ctx, -1, "concat"); // [string][concat]
duk_swap_top(ctx, -2); // [concat][this]
#ifdef WIN32
duk_push_string(ctx, "\\");
#else
duk_push_string(ctx, "/");
#endif
duk_call_method(ctx, 1);
return(1);
}
#ifdef _POSIX
@@ -1236,6 +1257,7 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEventEx(emitter, "exit");
ILibDuktape_CreateProperty_InstanceMethod(ctx, "exit", ILibDuktape_ScriptContainer_Process_Exit, DUK_VARARGS);
ILibDuktape_CreateProperty_InstanceMethod(ctx, "_exit", ILibDuktape_ScriptContainer_Process_ExitEx, DUK_VARARGS);
ILibDuktape_EventEmitter_CreateEventEx(emitter, "uncaughtException");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "SIGTERM");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "SIGCHLD");
@@ -1577,9 +1599,7 @@ duk_ret_t ILibDuktape_ScriptContainer_OS_networkInterfaces(duk_context *ctx)
ILibDuktape_CreateReadonlyProperty(ctx, "interfaceIndexes");
char fqdn[4096];
size_t fqdnLen;
int i = 0;
size_t converted;
char tmpBuffer[32768];
DWORD tmpBufferSize = sizeof(tmpBuffer);
IP_ADAPTER_ADDRESSES *padapters = (IP_ADAPTER_ADDRESSES*)tmpBuffer;
@@ -1603,7 +1623,7 @@ duk_ret_t ILibDuktape_ScriptContainer_OS_networkInterfaces(duk_context *ctx)
duk_put_prop_string(ctx, -2, "gateway");
}
wcstombs_s(&fqdnLen, fqdn, sizeof(fqdn), (const wchar_t*)padapters->DnsSuffix, wcsnlen_s(padapters->DnsSuffix, sizeof(fqdn)));
ILibWideToUTF8Ex((wchar_t*)padapters->DnsSuffix, -1, fqdn, (int)sizeof(fqdn));
duk_push_string(ctx, fqdn);
duk_put_prop_string(ctx, -2, "fqdn");
@@ -1654,7 +1674,7 @@ duk_ret_t ILibDuktape_ScriptContainer_OS_networkInterfaces(duk_context *ctx)
duk_put_prop_index(ctx, -2, i++);
addr = addr->Next;
}
wcstombs_s(&converted, ILibScratchPad, sizeof(ILibScratchPad), padapters->FriendlyName, sizeof(ILibScratchPad));
ILibWideToUTF8Ex(padapters->FriendlyName, -1, ILibScratchPad, (int)sizeof(ILibScratchPad));
duk_put_prop_string(ctx, -2, ILibScratchPad);
duk_push_heapptr(ctx, indexTable); // [table]
@@ -1815,6 +1835,22 @@ duk_ret_t ILibDuktape_ScriptContainer_OS_hostname(duk_context *ctx)
}
return(1);
}
duk_ret_t ILibDuktape_tmpdir(duk_context *ctx)
{
#ifdef WIN32
WCHAR tmp[1024];
if (GetTempPathW(sizeof(tmp) / 2, (LPWSTR)tmp) == 0) { return(ILibDuktape_Error(ctx, "Error getting temp folder")); }
ILibDuktape_String_PushWideString(ctx, (char*)tmp, 0);
#elif defined (_POSIX)
#if defined(__APPLE__)
duk_eval_string(ctx, "process.env['TMPDIR']");
if (duk_is_undefined(ctx, -1)) { duk_push_string(ctx, "/private/tmp/"); }
#else
duk_push_string(ctx, "/var/tmp/");
#endif
#endif
return(1);
}
void ILibDuktape_ScriptContainer_OS_Push(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [os]
@@ -1834,6 +1870,7 @@ void ILibDuktape_ScriptContainer_OS_Push(duk_context *ctx, void *chain)
ILibDuktape_CreateInstanceMethod(ctx, "networkInterfaces", ILibDuktape_ScriptContainer_OS_networkInterfaces, 0);
#endif
ILibDuktape_CreateInstanceMethod(ctx, "hostname", ILibDuktape_ScriptContainer_OS_hostname, 0);
ILibDuktape_CreateInstanceMethod(ctx, "tmpdir", ILibDuktape_tmpdir, 0);
char jsExtras[] = "exports.getPrimaryDnsSuffix = function getPrimaryDnsSuffix()\
{\
@@ -2161,34 +2198,31 @@ void ILibDuktape_ScriptContainer_OS_Push(duk_context *ctx, void *chain)
exports.Name = (function Name()\
{\
var child;\
switch (process.platform)\
if(process.platform!='win32')\
{\
case 'freebsd':\
case 'linux':\
case 'darwin':\
child = require('child_process').execFile('/bin/sh', ['sh']);\
break;\
case 'win32':\
child = require('child_process').execFile('%windir%\\\\system32\\\\cmd.exe');\
break;\
switch (process.platform)\
{\
case 'freebsd':\
case 'linux':\
case 'darwin':\
child = require('child_process').execFile('/bin/sh', ['sh']);\
break;\
}\
child.stdout.str=''; child.stdout.on('data', function(chunk) { this.str += chunk.toString(); });\
switch (process.platform)\
{\
case 'linux':\
child.stdin.write('cat /etc/*release\\nexit\\n');\
break;\
case 'darwin':\
child.stdin.write('sw_vers\\nexit\\n');\
break;\
case 'freebsd':\
child.stdin.write('uname -mrs\\nexit\\n');\
break;\
}\
child.waitExit();\
}\
child.stdout.str=''; child.stdout.on('data', function(chunk) { this.str += chunk.toString(); });\
switch (process.platform)\
{\
case 'linux':\
child.stdin.write('cat /etc/*release\\nexit\\n');\
break;\
case 'darwin':\
child.stdin.write('sw_vers\\nexit\\n');\
break;\
case 'win32':\
child.stdin.write('exit\\r\\n');\
break;\
case 'freebsd':\
child.stdin.write('uname -mrs\\nexit\\n');\
break;\
}\
child.waitExit();\
var ret=null;\
var lines;\
var tokens;\
@@ -2196,17 +2230,15 @@ void ILibDuktape_ScriptContainer_OS_Push(duk_context *ctx, void *chain)
switch (process.platform)\
{\
case 'win32':\
var winstr = child.stdout.str.split('\\r\\n')[0];\
if(require('user-sessions').isRoot())\
{\
try\
{\
winstr = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion', 'ProductName') + ' - ' +\
require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion', 'ReleaseID') + ' ' + winstr.substring(winstr.indexOf('['));\
require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion', 'ReleaseID');\
}\
catch(xx)\
{\
winstr = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion', 'ProductName') + ' ' + winstr.substring(winstr.indexOf('['));\
winstr = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion', 'ProductName');\
}\
}\
ret = winstr;\
@@ -2255,97 +2287,7 @@ void ILibDuktape_ScriptContainer_OS_Push(duk_context *ctx, void *chain)
{\
var promise = require('promise');\
var p = new promise(function(acc, rej) { this._acc = acc; this._rej = rej; });\
switch (process.platform)\
{\
case 'freebsd':\
case 'linux':\
case 'darwin':\
p.child = require('child_process').execFile('/bin/sh', ['sh']);\
break;\
case 'win32':\
p.child = require('child_process').execFile('%windir%\\\\system32\\\\cmd.exe');\
break;\
}\
p.child.promise = p;\
p.child.stdout.str = '';\
p.child.stdout.on('data', function(chunk) { this.str += chunk.toString(); });\
p.child.on('exit', function(code)\
{\
var lines;\
var tokens;\
var i, j;\
switch (process.platform)\
{\
case 'win32':\
var winstr = this.stdout.str.split('\\r\\n')[0];\
if(require('user-sessions').isRoot())\
{\
try\
{\
winstr = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion', 'ProductName') + ' - ' +\
require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion', 'ReleaseID') + ' ' + winstr.substring(winstr.indexOf('['));\
}\
catch(xx)\
{\
winstr = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion', 'ProductName') + ' ' + winstr.substring(winstr.indexOf('['));\
}\
}\
this.promise._acc(winstr);\
break;\
case 'linux':\
lines = this.stdout.str.split('\\n');\
for (i in lines)\
{\
tokens = lines[i].split('=');\
if (tokens[0] == 'PRETTY_NAME')\
{\
this.promise._acc(tokens[1].substring(1, tokens[1].length - 1));\
break;\
}\
}\
for (i in lines)\
{\
tokens = lines[i].split('=');\
if (tokens[0] == 'DISTRIB_DESCRIPTION')\
{\
this.promise._acc(tokens[1].substring(1, tokens[1].length - 1));\
break;\
}\
}\
this.promise._acc(lines[0]);\
break;\
case 'darwin':\
var OSNAME = '';\
var OSVERSION = '';\
lines = this.stdout.str.split('\\n');\
for (i in lines)\
{\
tokens = lines[i].split(':');\
if (tokens[0] == 'ProductName') { OSNAME = tokens[1].trim(); }\
if (tokens[0] == 'ProductVersion') { OSVERSION = tokens[1].trim(); }\
}\
this.promise._acc(OSNAME + ' ' + OSVERSION);\
break;\
case 'freebsd':\
this.promise._acc(this.stdout.str.trim());\
break;\
}\
});\
switch (process.platform)\
{\
case 'linux':\
p.child.stdin.write('cat /etc/*release\\nexit\\n');\
break;\
case 'darwin':\
p.child.stdin.write('sw_vers\\nexit\\n');\
break;\
case 'win32':\
p.child.stdin.write('exit\\r\\n');\
break;\
case 'freebsd':\
p.child.stdin.write('uname -mrs\\nexit\\n');\
break;\
}\
p._acc(this.Name);\
return (p);\
};\
if(process.platform=='freebsd')\
@@ -3144,6 +3086,7 @@ void ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread(void *chain, void *
int bufferLen = ((int*)buffer)[0];
void *ptr;
int i;
duk_context *ctx = master->ctx;
if (ILibDuktape_ScriptContainer_DecodeJSON(master->ctx, buffer+4, bufferLen-4) == 0)
{
@@ -3160,7 +3103,7 @@ void ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread(void *chain, void *
duk_push_string(master->ctx, json); // [emit][this][data][str]
duk_json_decode(master->ctx, -1); // [emit][this][data][json]
if (duk_pcall_method(master->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "ScriptContainer.OnData(): "); }
duk_pop(master->ctx);
duk_pop(ctx);
}
}
break;
@@ -3181,7 +3124,7 @@ void ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread(void *chain, void *
ILibDuktape_EventEmitter_SetupEmit(master->ctx, master->emitter->object, "error"); // [emit][this][error]
duk_get_prop_string(master->ctx, -4, "error"); // [emit][this][error][errorObj]
if (duk_pcall_method(master->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "ScriptContainer_OnError_Dispatch(): "); }
duk_pop(master->ctx); // ...
duk_pop(ctx); // ...
}
else
{
@@ -3193,7 +3136,7 @@ void ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread(void *chain, void *
duk_push_false(master->ctx); // [func][this][false]
duk_get_prop_string(master->ctx, -4, "error"); // [func][this][false][error]
if (duk_pcall_method(master->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "ScriptContainer_OnError_Dispatch(): "); }
duk_pop(master->ctx); // ...
duk_pop(ctx); // ...
}
}
}
@@ -3215,7 +3158,7 @@ void ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread(void *chain, void *
duk_push_undefined(master->ctx); // [func][this][true][undefined]
}
if (duk_pcall_method(master->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(master->ctx, "ScriptContainer_OnExec_Dispatch(): "); }
duk_pop(master->ctx); // ...
duk_pop(ctx); // ...
}
}
break;
@@ -3223,11 +3166,14 @@ void ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread(void *chain, void *
default:
break;
}
duk_pop(master->ctx); // ...
duk_pop(ctx); // ...
}
#ifdef WIN32
if (master->child != NULL) { ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Process_GetStdErr(master->child)); }
if (ILibMemory_CanaryOK(master))
{
if (master->child != NULL) { ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Process_GetStdErr(master->child)); }
}
#endif
}
void ILibDuktape_ScriptContainer_StdErrSink(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
@@ -3243,6 +3189,7 @@ void ILibDuktape_ScriptContainer_StdErrSink(ILibProcessPipe_Process sender, char
void **ptr = (void**)ILibMemory_Extra(ILibProcessPipe_Process_GetStdErr(sender));
ptr[0] = master;
ptr[1] = buffer;
ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Process_GetStdErr(sender));
Duktape_RunOnEventLoop(master->chain, duk_ctx_nonce(master->ctx), master->ctx, ILibDuktape_ScriptContainer_StdErrSink_MicrostackThread, NULL, ptr);
}

View File

@@ -922,7 +922,7 @@ duk_ret_t ILibDuktape_fs_watcher_close(duk_context *ctx)
#if defined(WIN32)
int r = CancelIo(data->h);
ILibProcessPipe_WaitHandle_Remove(data->pipeManager, data->overlapped.hEvent);
ILibChain_RemoveWaitHandle(data->chain, data->overlapped.hEvent);
CloseHandle(data->h);
data->h = NULL;
#elif defined(_POSIX) && !defined(__APPLE__) && !defined(_FREEBSD)
@@ -959,52 +959,50 @@ duk_ret_t ILibDuktape_fs_watcher_close(duk_context *ctx)
#endif
#ifdef WIN32
BOOL ILibDuktape_fs_watch_iocompletion(HANDLE h, ILibWaitHandle_ErrorStatus errors, void *user);
void ILibDuktape_fs_watch_iocompletionEx(void *chain, void *user)
BOOL ILibDuktape_fs_watch_iocompletion(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus errors, void *user)
{
if (errors != ILibWaitHandle_ErrorStatus_NONE || !ILibMemory_CanaryOK(user)) { return(FALSE); }
ILibDuktape_fs_watcherData *data = (ILibDuktape_fs_watcherData*)user;
FILE_NOTIFY_INFORMATION *n = (FILE_NOTIFY_INFORMATION*)data->results;
char filename[4096];
size_t filenameLen;
int changed = 0, renamed = 0;
BOOL ret = FALSE;
duk_push_object(data->ctx); // [detail]
while (n != NULL)
{
wcstombs_s(&filenameLen, filename, sizeof(filename), n->FileName, n->FileNameLength);
ILibWideToUTF8_stupidEx(n->FileName, n->FileNameLength, filename, (int)sizeof(filename));
switch (n->Action)
{
case FILE_ACTION_RENAMED_OLD_NAME:
duk_push_lstring(data->ctx, filename, filenameLen-1);
duk_push_string(data->ctx, filename);
duk_put_prop_string(data->ctx, -2, "oldname");
renamed = 1;
break;
case FILE_ACTION_RENAMED_NEW_NAME:
duk_push_lstring(data->ctx, filename, filenameLen - 1);
duk_push_string(data->ctx, filename);
duk_put_prop_string(data->ctx, -2, "newname");
renamed = 1;
break;
case FILE_ACTION_ADDED:
duk_push_string(data->ctx, "ADDED");
duk_put_prop_string(data->ctx, -2, "changeType");
duk_push_lstring(data->ctx, filename, filenameLen - 1);
duk_push_string(data->ctx, filename);
duk_put_prop_string(data->ctx, -2, "\xFF_FileName");
changed = 1;
break;
case FILE_ACTION_REMOVED:
duk_push_string(data->ctx, "REMOVED");
duk_put_prop_string(data->ctx, -2, "changeType");
duk_push_lstring(data->ctx, filename, filenameLen - 1);
duk_push_string(data->ctx, filename);
duk_put_prop_string(data->ctx, -2, "\xFF_FileName");
changed = 1;
break;
case FILE_ACTION_MODIFIED:
duk_push_string(data->ctx, "MODIFIED");
duk_put_prop_string(data->ctx, -2, "changeType");
duk_push_lstring(data->ctx, filename, filenameLen - 1);
duk_push_string(data->ctx, filename);
duk_put_prop_string(data->ctx, -2, "\xFF_FileName");
changed = 1;
break;
@@ -1041,18 +1039,10 @@ void ILibDuktape_fs_watch_iocompletionEx(void *chain, void *user)
}
else
{
ILibProcessPipe_WaitHandle_Add(data->pipeManager, data->overlapped.hEvent, data, ILibDuktape_fs_watch_iocompletion);
ret = TRUE;
}
}
}
BOOL ILibDuktape_fs_watch_iocompletion(HANDLE h, ILibWaitHandle_ErrorStatus errors, void *user)
{
if (errors != ILibWaitHandle_ErrorStatus_NONE || !ILibMemory_CanaryOK(user)) { return(FALSE); }
ILibDuktape_fs_watcherData *data = (ILibDuktape_fs_watcherData*)user;
ILibProcessPipe_WaitHandle_Remove(data->pipeManager, h);
Duktape_RunOnEventLoop(data->chain, duk_ctx_nonce(data->ctx), data->ctx, ILibDuktape_fs_watch_iocompletionEx, NULL, data);
return(TRUE);
return(ret);
}
#endif
@@ -1287,7 +1277,7 @@ void ILibduktape_fs_watch_appleWorker(void *obj)
duk_ret_t ILibDuktape_fs_watch(duk_context *ctx)
{
#ifdef WIN32
char *path = (char*)duk_require_string(ctx, 0);
WCHAR *path = (WCHAR*)ILibDuktape_String_AsWide(ctx, 0, NULL);
#else
char *path = ILibDuktape_fs_fixLinuxPath((char*)duk_require_string(ctx, 0));
#endif
@@ -1408,14 +1398,14 @@ duk_ret_t ILibDuktape_fs_watch(duk_context *ctx)
#if defined(WIN32)
if ((data->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { return(ILibDuktape_Error(ctx, "Could not create handle")); }
data->h = CreateFile(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
data->h = CreateFileW(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
if (data->h == INVALID_HANDLE_VALUE) { return(ILibDuktape_Error(ctx, "fs.watch(): Invalid Path or Access Denied")); }
if (ReadDirectoryChangesW(data->h, data->results, sizeof(data->results), recursive, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS, NULL, &(data->overlapped), NULL) == 0)
{
return(ILibDuktape_Error(ctx, "fs.watch(): Error creating watcher"));
}
ILibProcessPipe_WaitHandle_Add(pipeMgr, data->overlapped.hEvent, data, ILibDuktape_fs_watch_iocompletion);
ILibChain_AddWaitHandle(data->chain, data->overlapped.hEvent, -1, ILibDuktape_fs_watch_iocompletion, data);
#elif defined(_POSIX) && !defined(__APPLE__) && !defined(_FREEBSD)
data->wd.i = inotify_add_watch(data->linuxWatcher->fd, path, IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO);
if (data->wd.i < 0)

View File

@@ -82,18 +82,21 @@ int ILibDuktape_TLS_ctx2server = -1;
#define ILibDuktape_net_IPC_BUFFERSIZE 4096
typedef struct ILibDuktape_net_WindowsIPC
{
ILibProcessPipe_Manager manager;
duk_context *ctx;
void *mServer, *mSocket, *mChain;
HANDLE mPipeHandle;
ILibProcessPipe_Pipe mPipe;
int paused;
int totalRead;
void *user1;
OVERLAPPED read_overlapped;
OVERLAPPED write_overlapped;
OVERLAPPED overlapped;
ILibDuktape_DuplexStream *ds;
BOOL clientConnected;
ULONG_PTR _reserved[5];
int processingRead;
char *buffer;
int bufferLength;
int bufferOffset;
@@ -378,13 +381,12 @@ duk_ret_t ILibDuktape_net_socket_connect(duk_context *ctx)
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_net_WindowsIPC));
duk_put_prop_string(ctx, -2, ILibDuktape_net_WindowsIPC_Buffer);
winIPC->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
winIPC->read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
winIPC->write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
winIPC->ctx = ctx;
winIPC->mSocket = duk_get_heapptr(ctx, -1);
winIPC->mChain = Duktape_GetChain(ctx);
duk_eval_string(ctx, "require('child_process');");
winIPC->manager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager);
duk_pop(ctx);
winIPC->mChain = duk_ctx_chain(ctx);
winIPC->paused = 1;
if ((winIPC->mPipeHandle = CreateFileA(path, GENERIC_READ | FILE_WRITE_DATA, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0)) == INVALID_HANDLE_VALUE)
{
@@ -395,7 +397,6 @@ duk_ret_t ILibDuktape_net_socket_connect(duk_context *ctx)
{
// SUCCESS
winIPC->ds = ILibDuktape_DuplexStream_InitEx(winIPC->ctx, ILibDuktape_net_server_IPC_WriteSink, ILibDuktape_net_server_IPC_EndSink, ILibDuktape_net_server_IPC_PauseSink, ILibDuktape_net_server_IPC_ResumeSink, ILibDuktape_net_server_IPC_unshiftSink, winIPC);
winIPC->mPipe = ILibProcessPipe_Pipe_CreateFromExisting(winIPC->manager, winIPC->mPipeHandle, ILibProcessPipe_Pipe_ReaderHandleType_Overlapped);
winIPC->ds->readableStream->paused = 1;
ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "data", ILibDuktape_net_socket_ipc_dataHookCallback);
ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "end", ILibDuktape_net_socket_ipc_dataHookCallback);
@@ -838,7 +839,99 @@ void ILibDuktape_net_server_OnSendOK(ILibAsyncServerSocket_ServerModule AsyncSer
}
#ifdef WIN32
extern void ILibProcessPipe_FreePipe(ILibProcessPipe_Pipe pipeObject);
BOOL ILibDuktape_server_ipc_ReadSink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, char *buffer, int bytesRead, void* user)
{
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
int consumed = 0;
if (status == ILibWaitHandle_ErrorStatus_NONE)
{
winIPC->totalRead += bytesRead;
do
{
winIPC->unshiftedBytes = 0;
if (winIPC->totalRead > 0)
{
ILibDuktape_DuplexStream_WriteData(winIPC->ds, winIPC->buffer + winIPC->bufferOffset, winIPC->totalRead);
}
if (winIPC->unshiftedBytes > winIPC->totalRead) { winIPC->unshiftedBytes = winIPC->totalRead; }
winIPC->bufferOffset += (winIPC->totalRead - winIPC->unshiftedBytes);
winIPC->totalRead -= (winIPC->totalRead - winIPC->unshiftedBytes);
} while (winIPC->paused == 0 && consumed != 0 && winIPC->totalRead > 0);
if (winIPC->totalRead == 0) { winIPC->bufferOffset = 0; }
if (winIPC->paused == 0)
{
if (winIPC->bufferOffset > 0)
{
memmove_s(winIPC->buffer, winIPC->bufferLength, winIPC->buffer + winIPC->bufferOffset, winIPC->totalRead);
winIPC->bufferOffset = 0;
}
else if (winIPC->totalRead == winIPC->bufferLength)
{
ILibMemory_ReallocateRaw(&(winIPC->buffer), winIPC->bufferLength == 0 ? ILibDuktape_net_IPC_BUFFERSIZE : winIPC->bufferLength * 2);
winIPC->bufferLength = winIPC->bufferLength == 0 ? ILibDuktape_net_IPC_BUFFERSIZE : winIPC->bufferLength * 2;
}
ILibChain_ReadEx(chain, h, &(winIPC->read_overlapped), winIPC->buffer + winIPC->bufferOffset + winIPC->totalRead, winIPC->bufferLength - winIPC->totalRead, ILibDuktape_server_ipc_ReadSink, winIPC);
return(TRUE);
}
else
{
return(FALSE);
}
}
else
{
// I/O Errors
ILibDuktape_DuplexStream_Closed(winIPC->ds);
return(FALSE);
}
}
BOOL ILibDuktape_server_ipc_WriteSink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, int bytesWritten, void* user)
{
if (!ILibMemory_CanaryOK(user)) { return(FALSE); }
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
duk_idx_t top = duk_get_top(winIPC->ctx);
duk_size_t bufLen;
char *buf;
ILibTransport_DoneState d = ILibTransport_DoneState_COMPLETE;
BOOL ret;
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj]
duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array]
while (d == ILibTransport_DoneState_COMPLETE)
{
duk_dup(winIPC->ctx, -1); // [obj][array][array]
duk_get_prop_string(winIPC->ctx, -1, "shift"); // [obj][array][array][shift]
duk_swap_top(winIPC->ctx, -2); // [obj][array][shift][this]
if (duk_pcall_method(winIPC->ctx, 0) != 0) { duk_set_top(winIPC->ctx, top); return(FALSE); } // [obj][array][buffer]
duk_pop(winIPC->ctx); // [obj][array]
if (duk_get_length(winIPC->ctx, -1) == 0) { break; }
duk_get_prop_index(winIPC->ctx, -1, 0); // [obj][array][buffer]
buf = Duktape_GetBuffer(winIPC->ctx, -1, &bufLen);
d = ILibChain_WriteEx(chain, h, &(winIPC->write_overlapped), buf, (int)bufLen, ILibDuktape_server_ipc_WriteSink, winIPC);
duk_pop(winIPC->ctx); // [obj][array]
}
switch (d)
{
case ILibTransport_DoneState_COMPLETE:
// No more pending writes, so we can emit drain
ILibDuktape_DuplexStream_Ready(winIPC->ds);
ret = FALSE;
break;
case ILibTransport_DoneState_INCOMPLETE:
// Still pending writes, so return TRUE, so we can get evented later
ret = TRUE;
break;
case ILibTransport_DoneState_ERROR:
ret = FALSE;
break;
}
duk_set_top(winIPC->ctx, top); // ...
return(ret);
}
int ILibDuktape_net_server_IPC_unshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
{
@@ -847,184 +940,29 @@ int ILibDuktape_net_server_IPC_unshiftSink(ILibDuktape_DuplexStream *sender, int
winIPC->unshiftedBytes = unshiftBytes;
return(unshiftBytes);
}
void ILibDuktape_net_server_IPC_readsink_safe(void *chain, void *user)
{
if (!ILibMemory_CanaryOK(user)) { return; }
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
ILibProcessPipe_Pipe sender = (ILibProcessPipe_Pipe)winIPC->_reserved[0];
DWORD dwErrorCode = (DWORD)winIPC->_reserved[2];
char *buffer = (char*)winIPC->_reserved[3];
int bufferLen = (int)winIPC->_reserved[4];
if (dwErrorCode == 0)
{
winIPC->bytesLeft += bufferLen;
ILibDuktape_net_server_IPC_ResumeSink(winIPC->ds, winIPC);
}
else
{
ILibDuktape_DuplexStream_Closed(winIPC->ds);
ILibProcessPipe_FreePipe(winIPC->mPipe);
winIPC->mPipe = NULL; winIPC->mPipeHandle = NULL;
if (winIPC->mServer != NULL)
{
// Server IPC, so we can create a new Instance, and listen for a connection
duk_context *ctx = winIPC->ctx; // We need to dereference this, because winIPC will go out of scope when we call listen
CloseHandle(winIPC->overlapped.hEvent); winIPC->overlapped.hEvent = NULL;
if (winIPC->buffer != NULL) { free(winIPC->buffer); winIPC->buffer = NULL; }
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [connection]
duk_del_prop_string(ctx, -1, ILibDuktape_net_WindowsIPC_Buffer); duk_pop(winIPC->ctx); // ...
duk_push_heapptr(ctx, winIPC->mServer); // [server]
if (Duktape_GetBooleanProperty(ctx, -1, ILibDuktape_net_server_closed, 0) == 0)
{
duk_get_prop_string(ctx, -1, "listen"); // [server][listen]
duk_swap_top(ctx, -2); // [listen][this]
duk_get_prop_string(ctx, -1, ILibDuktape_SERVER2LISTENOPTIONS); // [listen][this][options]
duk_pcall_method(ctx, 1); // [ret]
}
else if (Duktape_GetBooleanProperty(ctx, -1, ILibDuktape_net_server_closed_needEmit, 0) != 0)
{
duk_push_false(ctx); duk_put_prop_string(ctx, -2, ILibDuktape_net_server_closed_needEmit);
ILibDuktape_EventEmitter_SetupEmit(ctx, winIPC->mServer, "close"); // [emit][this][closed]
duk_pcall_method(ctx, 1); // [ret]
}
duk_pop(ctx); // ...
}
}
}
void ILibDuktape_net_server_IPC_readsink(ILibProcessPipe_Pipe sender, void *user, DWORD dwErrorCode, char *buffer, int bufferLen)
{
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
if (!ILibMemory_CanaryOK(user)) { return; }
winIPC->_reserved[0] = (ULONG_PTR)sender;
winIPC->_reserved[1] = (ULONG_PTR)user;
winIPC->_reserved[2] = (ULONG_PTR)dwErrorCode;
winIPC->_reserved[3] = (ULONG_PTR)buffer;
winIPC->_reserved[4] = (ULONG_PTR)bufferLen;
Duktape_RunOnEventLoop(winIPC->mChain, duk_ctx_nonce(winIPC->ctx), winIPC->ctx, ILibDuktape_net_server_IPC_readsink_safe, NULL, winIPC);
}
void ILibDuktape_net_server_IPC_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
{
// No-OP, becuase all we need to so is set Paused flag, which is already the case when we get here
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
winIPC->paused = 1;
}
void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
if (winIPC->processingRead != 0 || winIPC->mPipeHandle == NULL) { return; }
winIPC->processingRead = 1;
if (winIPC->buffer == NULL)
{
winIPC->buffer = ILibMemory_Allocate(ILibDuktape_net_IPC_BUFFERSIZE, 0, NULL, NULL);
winIPC->bufferLength = ILibDuktape_net_IPC_BUFFERSIZE;
winIPC->bufferOffset = 0;
winIPC->bytesLeft = 0;
}
if (winIPC->bytesLeft <= 0)
{
winIPC->bytesLeft = 0;
winIPC->bufferOffset = 0;
if (ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer, winIPC->bufferLength, winIPC, ILibDuktape_net_server_IPC_readsink) != 0)
{
ILibDuktape_net_server_IPC_readsink(winIPC->mPipe, winIPC, 1, NULL, 0);
}
}
else
{
// Check to see if we can drain any of the buffer first
while (winIPC->ds->readableStream->paused == 0)
{
winIPC->unshiftedBytes = 0;
ILibDuktape_DuplexStream_WriteData(winIPC->ds, winIPC->buffer + winIPC->bufferOffset, winIPC->bytesLeft);
if (winIPC->unshiftedBytes > 0)
{
if (winIPC->unshiftedBytes == winIPC->bytesLeft)
{
// Unshift the entire buffer
winIPC->unshiftedBytes = 0;
}
else
{
// Unshift some of the buffer
winIPC->bufferOffset += (winIPC->bytesLeft - winIPC->unshiftedBytes);
if (winIPC->bytesLeft == winIPC->unshiftedBytes)
{
winIPC->unshiftedBytes = 0;
}
winIPC->bytesLeft = winIPC->unshiftedBytes;
}
}
else
{
winIPC->bufferOffset = winIPC->bytesLeft = 0;
}
if (winIPC->ds->readableStream->paused == 0 && (winIPC->bytesLeft == 0 || (winIPC->bytesLeft > 0 && winIPC->unshiftedBytes == 0)))
{
if (winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft == 0)
{
// We need to grow the buffer
ILibMemory_ReallocateRaw(&(winIPC->buffer), winIPC->bufferLength + ILibDuktape_net_IPC_BUFFERSIZE);
winIPC->bufferLength += ILibDuktape_net_IPC_BUFFERSIZE;
}
if (ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer + winIPC->bufferOffset + winIPC->bytesLeft, winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft, winIPC, ILibDuktape_net_server_IPC_readsink) != 0)
{
ILibDuktape_net_server_IPC_readsink(winIPC->mPipe, winIPC, 1, NULL, 0);
}
break;
}
}
}
winIPC->processingRead = 0;
winIPC->paused = 0;
ILibDuktape_server_ipc_ReadSink(winIPC->mChain, winIPC->mPipeHandle, ILibWaitHandle_ErrorStatus_NONE, NULL, 0, winIPC);
}
void ILibDuktape_net_server_IPC_WriteCompletionEvent(ILibProcessPipe_Pipe sender, void *user, DWORD errorCode, int bytesWritten)
{
if (!ILibMemory_CanaryOK(user) || errorCode != 0) { return; }
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
duk_idx_t top = duk_get_top(winIPC->ctx);
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj]
duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array]
duk_get_prop_string(winIPC->ctx, -1, "shift"); // [obj][array][shift]
duk_dup(winIPC->ctx, -2); // [obj][array][shift][this]
if (duk_pcall_method(winIPC->ctx, 0) != 0) // [obj][array][buffer]
{
ILibDuktape_Process_UncaughtExceptionEx(winIPC->ctx, "Internal Error: net.socket.ipc.writeCompletionEvent");
duk_set_top(winIPC->ctx, top); // ...
return;
}
duk_pop(winIPC->ctx); // [obj][array]
if (duk_get_length(winIPC->ctx, -1) > 0)
{
// Still pending Writes
duk_get_prop_index(winIPC->ctx, -1, 0); // [obj][array][buffer]
duk_size_t bufLen;
char *buf = (char*)Duktape_GetBuffer(winIPC->ctx, -1, &bufLen);
duk_set_top(winIPC->ctx, top); // ...
ILibProcessPipe_Pipe_WriteEx(winIPC->mPipe, buf, (int)bufLen, winIPC, ILibDuktape_net_server_IPC_WriteCompletionEvent);
}
else
{
// No more pending writes, so we can emit drain
duk_set_top(winIPC->ctx, top); // ...
ILibDuktape_DuplexStream_Ready(winIPC->ds);
}
}
ILibTransport_DoneState ILibDuktape_net_server_IPC_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
if (!ILibMemory_CanaryOK(user)) { return(ILibTransport_DoneState_ERROR); }
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
if (!duk_ctx_is_alive(winIPC->ctx) || winIPC->mPipeHandle == NULL) { return(ILibTransport_DoneState_ERROR); }
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj]
duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array]
char *q = duk_push_fixed_buffer(winIPC->ctx, bufferLen); // [obj][array][buffer]
duk_size_t len = duk_get_length(winIPC->ctx, -2);
duk_put_prop_index(winIPC->ctx, -2, (duk_uarridx_t)len); // [obj][array]
@@ -1034,7 +972,15 @@ ILibTransport_DoneState ILibDuktape_net_server_IPC_WriteSink(ILibDuktape_DuplexS
if (len == 0)
{
// No Pending Writes
ILibProcessPipe_Pipe_WriteEx(winIPC->mPipe, q, bufferLen, winIPC, ILibDuktape_net_server_IPC_WriteCompletionEvent);
ILibTransport_DoneState ret = ILibChain_WriteEx(winIPC->mChain, winIPC->mPipeHandle, &(winIPC->write_overlapped), q, bufferLen, ILibDuktape_server_ipc_WriteSink, winIPC);
if (ret != ILibTransport_DoneState_INCOMPLETE)
{
duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj]
duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array]
duk_array_shift(winIPC->ctx, -1); // [obj][array][val]
duk_pop_3(winIPC->ctx); // ...
}
return(ret);
}
return(ILibTransport_DoneState_INCOMPLETE);
@@ -1044,22 +990,21 @@ void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void *
if (!ILibMemory_CanaryOK(user)) { return; }
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
if (ILibProcessPipe_Pipe_CancelEx(winIPC->mPipe) == 0)
{
ILibProcessPipe_FreePipe(winIPC->mPipe);
winIPC->mPipe = NULL; winIPC->mPipeHandle = NULL;
if (winIPC->mServer != NULL)
{
// Server IPC, so we can create a new Instance, and listen for a connection
duk_context *ctx = winIPC->ctx; // We need to dereference this, because winIPC will go out of scope when we call listen
CloseHandle(winIPC->overlapped.hEvent); winIPC->overlapped.hEvent = NULL;
if (winIPC->mPipeHandle != NULL) { CloseHandle(winIPC->mPipeHandle); winIPC->mPipeHandle = NULL; }
if (winIPC->read_overlapped.hEvent != NULL) { CloseHandle(winIPC->read_overlapped.hEvent); winIPC->read_overlapped.hEvent = NULL; }
if (winIPC->write_overlapped.hEvent != NULL) { CloseHandle(winIPC->write_overlapped.hEvent); winIPC->write_overlapped.hEvent = NULL; }
duk_push_heapptr(ctx, winIPC->mServer); // [server]
duk_get_prop_string(ctx, -1, "listen"); // [server][listen]
duk_swap_top(ctx, -2); // [listen][this]
duk_get_prop_string(ctx, -1, ILibDuktape_SERVER2LISTENOPTIONS); // [listen][this][options]
duk_pcall_method(ctx, 1); duk_pop(ctx); // ...
}
if (winIPC->mServer != NULL)
{
// Server IPC, so we can create a new Instance, and listen for a connection
duk_context *ctx = winIPC->ctx; // We need to dereference this, because winIPC will go out of scope when we call listen
CloseHandle(winIPC->overlapped.hEvent); winIPC->overlapped.hEvent = NULL;
duk_push_heapptr(ctx, winIPC->mServer); // [server]
duk_get_prop_string(ctx, -1, "listen"); // [server][listen]
duk_swap_top(ctx, -2); // [listen][this]
duk_get_prop_string(ctx, -1, ILibDuktape_SERVER2LISTENOPTIONS); // [listen][this][options]
duk_pcall_method(ctx, 1); duk_pop(ctx); // ...
}
}
duk_ret_t ILibDuktape_net_server_IPC_ConnectSink_Finalizer(duk_context *ctx)
@@ -1067,22 +1012,35 @@ duk_ret_t ILibDuktape_net_server_IPC_ConnectSink_Finalizer(duk_context *ctx)
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_GetBufferProperty(ctx, 0, ILibDuktape_net_WindowsIPC_Buffer);
if (winIPC != NULL)
{
if (winIPC->mPipe != NULL && winIPC->mPipeHandle != NULL)
if (winIPC->mPipeHandle != NULL)
{
// It's ok to do this, becuase the CancelEx happens on the same thread, and the completion routine will use an APC Queue, so the Canary will fail before it tries to deref
ILibProcessPipe_Pipe_CancelEx(winIPC->mPipe);
ILibProcessPipe_FreePipe(winIPC->mPipe);
winIPC->mPipe = NULL; winIPC->mPipeHandle = NULL;
CloseHandle(winIPC->mPipeHandle);
winIPC->mPipeHandle = NULL;
}
if (winIPC->buffer != NULL) { free(winIPC->buffer); winIPC->buffer = NULL; }
if (winIPC->read_overlapped.hEvent != NULL)
{
ILibChain_RemoveWaitHandle(duk_ctx_chain(ctx), winIPC->read_overlapped.hEvent);
CloseHandle(winIPC->read_overlapped.hEvent);
winIPC->read_overlapped.hEvent = NULL;
}
if (winIPC->write_overlapped.hEvent != NULL)
{
ILibChain_RemoveWaitHandle(duk_ctx_chain(ctx), winIPC->write_overlapped.hEvent);
CloseHandle(winIPC->write_overlapped.hEvent);
winIPC->write_overlapped.hEvent = NULL;
}
if (winIPC->buffer != NULL) { free(winIPC->buffer); }
}
return(0);
}
BOOL ILibDuktape_net_server_IPC_ConnectSink(HANDLE event, ILibWaitHandle_ErrorStatus status, void* user)
//BOOL ILibDuktape_net_server_IPC_ConnectSink(HANDLE event, ILibWaitHandle_ErrorStatus status, void* user)
BOOL ILibDuktape_net_server_IPC_ConnectSink(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus status, void* user)
{
if (ILibMemory_CanaryOK(user))
if (ILibMemory_CanaryOK(user) && status == ILibWaitHandle_ErrorStatus_NONE)
{
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user;
winIPC->clientConnected = TRUE;
ILibDuktape_EventEmitter_SetupEmit(winIPC->ctx, winIPC->mServer, "connection"); // [emit][this][connection]
duk_push_object(winIPC->ctx); // [emit][this][connection][socket]
ILibDuktape_WriteID(winIPC->ctx, "net.socket.ipc");
@@ -1095,8 +1053,9 @@ BOOL ILibDuktape_net_server_IPC_ConnectSink(HANDLE event, ILibWaitHandle_ErrorSt
duk_push_array(winIPC->ctx); duk_put_prop_string(winIPC->ctx, -2, ILibDuktape_net_WindowsIPC_PendingArray);
winIPC->mSocket = duk_get_heapptr(winIPC->ctx, -1);
winIPC->ds = ILibDuktape_DuplexStream_InitEx(winIPC->ctx, ILibDuktape_net_server_IPC_WriteSink, ILibDuktape_net_server_IPC_EndSink, ILibDuktape_net_server_IPC_PauseSink, ILibDuktape_net_server_IPC_ResumeSink, ILibDuktape_net_server_IPC_unshiftSink, winIPC);
winIPC->mPipe = ILibProcessPipe_Pipe_CreateFromExisting(winIPC->manager, winIPC->mPipeHandle, ILibProcessPipe_Pipe_ReaderHandleType_Overlapped);
winIPC->ds->readableStream->paused = 1;
winIPC->paused = 1;
ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "data", ILibDuktape_net_socket_ipc_dataHookCallback);
ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "end", ILibDuktape_net_socket_ipc_dataHookCallback);
@@ -1210,12 +1169,14 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx)
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_net_WindowsIPC));
duk_put_prop_string(ctx, -2, ILibDuktape_net_WindowsIPC_Buffer);
winIPC->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
winIPC->read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
winIPC->write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
winIPC->ctx = ctx;
winIPC->mServer = duk_get_heapptr(ctx, -1);
winIPC->mChain = Duktape_GetChain(ctx);
winIPC->mChain = duk_ctx_chain(ctx);
winIPC->clientConnected = FALSE;
duk_eval_string(ctx, "require('child_process');");
winIPC->manager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager);
duk_pop(ctx);
if (Duktape_GetBooleanProperty(ctx, 0, "writableAll", 0) != 0)
@@ -1252,9 +1213,9 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx)
duk_del_prop_string(ctx, -1, ILibDuktape_net_WindowsIPC_Buffer);
return(ILibDuktape_Error(ctx, "Error Creating Named Pipe: %s", ipc));
}
//printf("ConnectNamedPipe(%s)\n", ipc);
ConnectNamedPipe(winIPC->mPipeHandle, &winIPC->overlapped);
ILibProcessPipe_WaitHandle_Add2(winIPC->manager, winIPC->overlapped.hEvent, winIPC, ILibDuktape_net_server_IPC_ConnectSink);
ILibChain_AddWaitHandle(duk_ctx_chain(ctx), winIPC->overlapped.hEvent, -1, ILibDuktape_net_server_IPC_ConnectSink, winIPC);
if (pIPC_SA != NULL) { LocalFree(IPC_ACL); }
return(1);
@@ -1334,7 +1295,7 @@ duk_ret_t ILibDuktape_net_server_Finalizer(duk_context *ctx)
ILibDuktape_net_WindowsIPC *ipc = Duktape_GetBufferProperty(ctx, 0, ILibDuktape_net_WindowsIPC_Buffer);
if (ipc != NULL && ipc->overlapped.hEvent != NULL)
{
ILibProcessPipe_WaitHandle_Remove(ipc->manager, ipc->overlapped.hEvent);
ILibChain_RemoveWaitHandle(duk_ctx_chain(ctx), ipc->overlapped.hEvent);
if (ipc->mPipeHandle != NULL) { CloseHandle(ipc->mPipeHandle); ipc->mPipeHandle = NULL; }
if (ipc->overlapped.hEvent != NULL) { CloseHandle(ipc->overlapped.hEvent); ipc->overlapped.hEvent = NULL; }
}
@@ -1399,7 +1360,7 @@ duk_ret_t ILibDuktape_net_server_close(duk_context *ctx)
ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_net_WindowsIPC_Buffer);
if (winIPC != NULL && winIPC->mPipeHandle != NULL)
{
if (winIPC->mPipe == NULL)
if (winIPC->clientConnected == FALSE)
{
// Listening
DisconnectNamedPipe(winIPC->mPipeHandle);

View File

@@ -125,7 +125,7 @@ int __fastcall util_sha384file(char* filename, char* result)
if (filename == NULL) return -1;
#ifdef WIN32
fopen_s(&pFile, filename, "rbN");
_wfopen_s(&pFile, ILibUTF8ToWide(filename, -1), L"rbN");
#else
pFile = fopen(filename, "rb");
#endif
@@ -264,7 +264,7 @@ size_t __fastcall util_writefile(char* filename, char* data, int datalen)
size_t count = 0;
#ifdef WIN32
fopen_s(&pFile, filename, "wbN");
_wfopen_s(&pFile, ILibUTF8ToWide(filename, -1), L"wbN");
#else
pFile = fopen(filename, "wb");
#endif
@@ -283,7 +283,7 @@ size_t __fastcall util_appendfile(char* filename, char* data, int datalen)
size_t count = 0;
#ifdef WIN32
fopen_s(&pFile, filename, "abN");
_wfopen_s(&pFile, ILibUTF8ToWide(filename, -1), L"abN");
#else
pFile = fopen(filename, "ab");
#endif
@@ -306,7 +306,7 @@ size_t __fastcall util_readfile(char* filename, char** data, size_t maxlen)
if (filename == NULL) return 0;
#ifdef WIN32
fopen_s(&pFile, filename, "rbN");
_wfopen_s(&pFile, ILibUTF8ToWide(filename, -1), L"rbN");
#else
pFile = fopen(filename, "rb");
#endif
@@ -367,7 +367,11 @@ int __fastcall util_readfile2(char* filename, char** data)
int __fastcall util_deletefile(char* filename)
{
if (filename == NULL) return 0;
return remove(filename);
#ifdef WIN32
return(_wremove(ILibUTF8ToWide(filename, -1)));
#else
return(remove(filename));
#endif
}
#ifdef WIN32
@@ -407,8 +411,26 @@ BOOL util_CopyFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName, _I
return (CopyFile2(lpExistingFileNameW, lpNewFileNameW, NULL) == S_OK);
}
#else
BOOL util_MoveFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName) { return MoveFileA(lpExistingFileName, lpNewFileName); }
BOOL util_CopyFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName, _In_ BOOL bFailIfExists) { return CopyFileA(lpExistingFileName, lpNewFileName, bFailIfExists); }
BOOL util_MoveFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName)
{
WCHAR wExisting[4096];
WCHAR wNew[4096];
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)lpExistingFileName, -1, (LPWSTR)wExisting, (int)sizeof(wExisting) / 2);
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)lpNewFileName, -1, (LPWSTR)wNew, (int)sizeof(wNew) / 2);
return MoveFileW(wExisting, wNew);
}
BOOL util_CopyFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName, _In_ BOOL bFailIfExists)
{
WCHAR wExisting[4096];
WCHAR wNew[4096];
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)lpExistingFileName, -1, (LPWSTR)wExisting, (int)sizeof(wExisting) / 2);
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)lpNewFileName, -1, (LPWSTR)wNew, (int)sizeof(wNew) / 2);
return CopyFileW(wExisting, wNew, bFailIfExists);
}
#endif
#endif
@@ -593,7 +615,7 @@ int __fastcall util_from_pem(char* filename, struct util_cert* cert)
if (filename == NULL) return -1;
#ifdef WIN32
fopen_s(&pFile, filename, "rbN");
_wfopen_s(&pFile, ILibUTF8ToWide(filename, -1), L"rbN");
#else
pFile = fopen(filename, "rb");
#endif

View File

@@ -179,6 +179,34 @@ int ILibWhichPowerOfTwo(int number)
return retVal;
}
#ifdef WIN32
#define ILibChain_HandleInfoIndex(i) (FD_SETSIZE+i)
WCHAR ILibWideScratchPad[4096];
char ILibUTF8ScratchPad[4096];
char *ILibWideToUTF8Ex(WCHAR* wstr, int len, char *buffer, int bufferLen)
{
if (buffer == NULL) { buffer = ILibUTF8ScratchPad; bufferLen = (int)sizeof(ILibUTF8ScratchPad); }
WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)wstr, len, (LPSTR)buffer, bufferLen, NULL, NULL);
return(buffer);
}
char *ILibWideToUTF8_stupidEx(WCHAR* wstr, int wstrBYTESIZE, char *buffer, int bufferLen)
{
char *ret = NULL;
char *tmp = ILibMemory_SmartAllocate(wstrBYTESIZE + 2);
memcpy_s(tmp, wstrBYTESIZE + 2, (char*)wstr, wstrBYTESIZE);
ret = ILibWideToUTF8Ex((WCHAR*)tmp, -1, buffer, bufferLen);
ILibMemory_Free(tmp);
return(ret);
}
WCHAR* ILibUTF8ToWideEx(char* str, int len, WCHAR* buffer, int bufferCharacterSize)
{
if (buffer == NULL) { buffer = (WCHAR*)ILibWideScratchPad; bufferCharacterSize = (int)sizeof(ILibWideScratchPad) / 2; }
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)str, len, (LPWSTR)buffer, bufferCharacterSize);
return(buffer);
}
#endif
//
// All of the following structures are meant to be private internal structures
@@ -893,6 +921,15 @@ struct ILibBaseChain_SafeData
void *Object;
};
#ifdef WIN32
typedef struct ILibChain_WaitHandleInfo
{
void *node;
ILibChain_WaitHandleHandler handler;
void *user;
struct timeval expiration;
}ILibChain_WaitHandleInfo;
#endif
typedef struct ILibBaseChain
{
@@ -917,12 +954,13 @@ typedef struct ILibBaseChain
HANDLE ChainProcessHandle;
HANDLE MicrostackThreadHandle;
CONTEXT MicrostackThreadContext;
int UnblockFlag;
void* auxSelectHandles;
HANDLE WaitHandles[FD_SETSIZE * 2];
HANDLE currentHandle;
ILibChain_WaitHandleInfo *currentInfo;
#else
pthread_t ChainThreadID;
#endif
#if defined(WIN32)
SOCKET TerminateSock;
#else
int TerminatePipe[2];
#endif
@@ -946,6 +984,7 @@ typedef struct ILibBaseChain
void *node;
}ILibBaseChain;
void* ILibMemory_AllocateA_Init(void *buffer)
{
((void**)buffer)[0] = (char*)buffer + sizeof(void*);
@@ -1807,7 +1846,6 @@ void *ILibCreateChainEx(int extraMemorySize)
#if defined(WIN32) || defined(_WIN32_WCE)
RetVal->TerminateFlag = 1;
RetVal->TerminateSock = WSASocketW(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT);
RetVal->ChainProcessHandle = GetCurrentProcess();
if (!SymInitialize(RetVal->ChainProcessHandle, NULL, TRUE)) { RetVal->ChainProcessHandle = NULL; }
#endif
@@ -1875,12 +1913,8 @@ void* ILibGetBaseTimer(void *chain)
void __stdcall ILibForceUnBlockChain_APC(ULONG_PTR obj)
{
struct ILibBaseChain *c = (struct ILibBaseChain*)obj;
c->selectTimeout = 0;
if (c->TerminateSock != ~0)
{
closesocket(c->TerminateSock);
}
c->TerminateSock = WSASocketW(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT);
//c->selectTimeout = 0;
c->UnblockFlag = 1;
}
#endif
/*! \fn ILibForceUnBlockChain(void *Chain)
@@ -1968,11 +2002,209 @@ void ILibChain_UpdateEventHook(ILibChain_EventHookToken token, int maxTimeout)
memset(hook, 0, sizeof(ILibChain_Link_Hook));
}
}
#ifdef WIN32
int ILibChain_WindowsSelect(void *chain, fd_set *readset, fd_set *writeset, fd_set *errorset, HANDLE *waitList, int waitListCount, DWORD waitTimeout)
{
int slct = -1;
int i;
struct timeval currentTime;
struct timeval tv;
if (waitListCount == 0)
{
SleepEx(waitTimeout, TRUE);
slct = -1;
}
else
{
while ((slct = WaitForMultipleObjectsEx(waitListCount, waitList, FALSE, waitTimeout, TRUE)) == WAIT_IO_COMPLETION && ((ILibBaseChain*)chain)->UnblockFlag == 0) {}
ILibGetTimeOfDay(&currentTime);
if (slct != WAIT_IO_COMPLETION && (slct - (int)WAIT_OBJECT_0 >= 0) && (slct - (int)WAIT_OBJECT_0 < waitListCount))
{
if (waitList[ILibChain_HandleInfoIndex(slct)] != NULL)
{
ILibChain_WaitHandleInfo *info = (ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(slct)];
((ILibBaseChain*)chain)->currentHandle = waitList[slct];
((ILibBaseChain*)chain)->currentInfo = info;
waitList[ILibChain_HandleInfoIndex(slct)] = NULL;
waitList[slct] = NULL;
if (info->handler != NULL)
{
if (info->handler(chain, ((ILibBaseChain*)chain)->currentHandle, ILibWaitHandle_ErrorStatus_NONE, info->user) == FALSE)
{
// FALSE means to remove tha HANDLE
if (((ILibBaseChain*)chain)->currentHandle != NULL && ILibMemory_CanaryOK(info))
{
ILibLinkedList_Remove(info->node);
}
}
}
((ILibBaseChain*)chain)->currentHandle = NULL;
((ILibBaseChain*)chain)->currentInfo = NULL;
}
}
if (slct == WAIT_TIMEOUT)
{
for (i = 0; i < waitListCount; ++i)
{
if (waitList[ILibChain_HandleInfoIndex(i)] != NULL && tvnonzero(&(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->expiration)))
{
if (tv2LTEtv1(&currentTime, &(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->expiration)))
{
// TIMEOUT occured
if (((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler != NULL)
{
((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler(chain, waitList[i], ILibWaitHandle_ErrorStatus_TIMEOUT, ((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->user);
}
ILibLinkedList_Remove(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->node);
waitList[i] = NULL;
waitList[ILibChain_HandleInfoIndex(i)] = NULL;
}
}
}
}
if (slct == WAIT_FAILED)
{
// One of the handles is invalid... Kick it out
for (i = 0; i < waitListCount; ++i)
{
if (waitList[ILibChain_HandleInfoIndex(i)] != NULL)
{
if (WaitForSingleObject(waitList[i], 0) == WAIT_FAILED)
{
if (((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler != NULL)
{
((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler(chain, waitList[i], ILibWaitHandle_ErrorStatus_INVALID_HANDLE, ((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->user);
}
ILibLinkedList_Remove(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->node);
waitList[i] = NULL;
waitList[ILibChain_HandleInfoIndex(i)] = NULL;
}
}
}
}
tv.tv_sec = 0; tv.tv_usec = 0;
slct = select(FD_SETSIZE, readset, writeset, errorset, &tv);
((ILibBaseChain*)chain)->UnblockFlag = 0;
}
return(slct);
}
void ILibChain_SetupWindowsWaitObject(HANDLE* waitList, int *waitListCount, struct timeval *tv, DWORD *timeout, fd_set *readset, fd_set *writeset, fd_set *errorset, ILibLinkedList handleList, HANDLE **onlyHandles)
{
HANDLE selectHandles[FD_SETSIZE];
memset(selectHandles, 0, sizeof(selectHandles));
if (readset->fd_count == 0 && writeset->fd_count == 0 && ILibLinkedList_GetNode_Head(handleList) == NULL)
{
*waitListCount = 0;
return;
}
int chkIndex;
void *node;
struct timeval currentTime;
struct timeval expirationTime;
int i;
int x = 0;
long flags;
for (i = 0; i < (int)readset->fd_count; ++i)
{
selectHandles[x++] = (HANDLE)readset->fd_array[i];
}
for (i = 0; i < (int)writeset->fd_count; ++i)
{
if (!FD_ISSET(writeset->fd_array[i], readset))
{
selectHandles[x++] = (HANDLE)writeset->fd_array[i];
}
}
for (i = 0; i < (int)errorset->fd_count; ++i)
{
if (!FD_ISSET(errorset->fd_array[i], readset) && !FD_ISSET(errorset->fd_array[i], writeset))
{
selectHandles[x++] = (HANDLE)errorset->fd_array[i];
}
}
for (i = 0; i < x; ++i)
{
if (waitList[i] == NULL || waitList[ILibChain_HandleInfoIndex(i)] != NULL)
{
waitList[i] = WSACreateEvent();
}
else
{
WSAResetEvent(waitList[i]);
}
flags = 0;
waitList[ILibChain_HandleInfoIndex(i)] = NULL;
if (FD_ISSET(selectHandles[i], readset)) { flags |= (FD_READ | FD_ACCEPT); }
if (FD_ISSET(selectHandles[i], writeset)) { flags |= (FD_WRITE | FD_CONNECT); }
if (FD_ISSET(selectHandles[i], errorset)) { flags |= FD_CLOSE; }
WSAEventSelect((SOCKET)selectHandles[i], waitList[i], flags);
}
ILibGetTimeOfDay(&currentTime);
memcpy_s(&expirationTime, sizeof(struct timeval), &currentTime, sizeof(struct timeval));
expirationTime.tv_sec += tv->tv_sec;
expirationTime.tv_usec += tv->tv_usec;
node = ILibLinkedList_GetNode_Head(handleList);
while (node != NULL)
{
if (onlyHandles != NULL)
{
for (chkIndex = 0; onlyHandles[chkIndex] != NULL; ++chkIndex)
{
if ((HANDLE)ILibLinkedList_GetDataFromNode(node) == onlyHandles[chkIndex])
{
chkIndex = -1;
break;
}
}
if (chkIndex != -1)
{
node = ILibLinkedList_GetNextNode(node);
continue;
}
}
i = x++;
if (waitList[i] != NULL && waitList[ILibChain_HandleInfoIndex(i)] == NULL)
{
WSACloseEvent(waitList[i]);
}
waitList[i] = (HANDLE)ILibLinkedList_GetDataFromNode(node);
waitList[ILibChain_HandleInfoIndex(i)] = (HANDLE)ILibMemory_Extra(node);
if (((ILibChain_WaitHandleInfo*)ILibMemory_Extra(node))->expiration.tv_sec != 0 || ((ILibChain_WaitHandleInfo*)ILibMemory_Extra(node))->expiration.tv_usec != 0)
{
// Timeout was specified
if (tv2LTtv1(&expirationTime, &(((ILibChain_WaitHandleInfo*)ILibMemory_Extra(node))->expiration)))
{
expirationTime.tv_sec = ((ILibChain_WaitHandleInfo*)ILibMemory_Extra(node))->expiration.tv_sec;
expirationTime.tv_usec = ((ILibChain_WaitHandleInfo*)ILibMemory_Extra(node))->expiration.tv_usec;
// If the expiration happens in the past, we need to set the timeout to zero
if (tv2LTtv1(&expirationTime, &currentTime)) { expirationTime.tv_sec = currentTime.tv_sec; expirationTime.tv_usec = currentTime.tv_usec; }
}
}
node = ILibLinkedList_GetNextNode(node);
}
expirationTime.tv_sec -= currentTime.tv_sec; if (expirationTime.tv_sec < 0) { expirationTime.tv_sec = 0; }
expirationTime.tv_usec -= currentTime.tv_usec; if (expirationTime.tv_usec < 0) { expirationTime.tv_usec = 0; }
*timeout = (DWORD)((expirationTime.tv_sec * 1000) + (expirationTime.tv_usec * 0.001));
*waitListCount = x;
}
#endif
ILibChain_ContinuationStates ILibChain_GetContinuationState(void *chain)
{
return(((ILibBaseChain*)chain)->continuationState);
}
#ifdef WIN32
ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules, int moduleCount, int maxTimeout, HANDLE **handles)
#else
ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules, int moduleCount, int maxTimeout)
#endif
{
ILibBaseChain *chain = (ILibBaseChain*)Chain;
ILibChain_Link_Hook *nodeHook;
@@ -1980,6 +2212,7 @@ ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules,
ILibChain_Link *module;
int slct = 0, vX = 0, mX = 0;
struct timeval tv;
struct timeval startTime;
fd_set readset;
fd_set errorset;
fd_set writeset;
@@ -1991,16 +2224,30 @@ ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules,
root->continuationState = ILibChain_ContinuationState_CONTINUE;
currentNode = root->node;
gettimeofday(&tv, NULL);
gettimeofday(&startTime, NULL);
ILibRemoteLogging_printf(ILibChainGetLogger(chain), ILibRemoteLogging_Modules_Microstack_Generic, ILibRemoteLogging_Flags_VerbosityLevel_1, "ContinueChain...");
#ifdef WIN32
HANDLE currentHandle = chain->currentHandle;
ILibChain_WaitHandleInfo* currentInfo = chain->currentInfo;
#endif
while (root->TerminateFlag == 0 && root->continuationState == ILibChain_ContinuationState_CONTINUE)
{
if (maxTimeout > 0)
{
gettimeofday(&tv, NULL);
if (tv.tv_sec < (startTime.tv_sec + maxTimeout / 1000))
{
root->continuationState = ILibChain_ContinuationState_END_CONTINUE;
break;
}
}
slct = 0;
FD_ZERO(&readset);
FD_ZERO(&errorset);
FD_ZERO(&writeset);
tv.tv_sec = UPNP_MAX_WAIT;
tv.tv_sec = maxTimeout < 0 ? UPNP_MAX_WAIT : maxTimeout/1000;
tv.tv_usec = 0;
//
@@ -2034,12 +2281,7 @@ ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules,
tv.tv_usec = 1000 * (chain->selectTimeout % 1000);
#if defined(WIN32) || defined(_WIN32_WCE)
//
// Add the fake socket, for ILibForceUnBlockChain
//
FD_SET(chain->TerminateSock, &errorset);
#else
#if !defined(WIN32)
//
// Put the Read end of the Pipe in the FDSET, for ILibForceUnBlockChain
//
@@ -2065,15 +2307,11 @@ ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules,
//
chain->PreSelectCount++;
#ifdef WIN32
if (readset.fd_count == 0 && writeset.fd_count == 0)
{
SleepEx((DWORD)chain->selectTimeout, TRUE); // If there is no pending IO, we must force the thread into an alertable wait state, so ILibForceUnblockChain can function.
slct = -1;
}
else
{
slct = select(FD_SETSIZE, &readset, &writeset, &errorset, &tv);
}
int x = 0;
DWORD waitTimeout = 0;
ILibChain_SetupWindowsWaitObject(chain->WaitHandles, &x, &tv, &waitTimeout, &readset, &writeset, &errorset, chain->auxSelectHandles, handles);
slct = ILibChain_WindowsSelect(chain, &readset, &writeset, &errorset, chain->WaitHandles, x, waitTimeout);
#else
slct = select(FD_SETSIZE, &readset, &writeset, &errorset, &tv);
#endif
@@ -2138,6 +2376,10 @@ ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules,
ILibRemoteLogging_printf(ILibChainGetLogger(chain), ILibRemoteLogging_Modules_Microstack_Generic, ILibRemoteLogging_Flags_VerbosityLevel_1, "ContinueChain...Ending...");
root->node = currentNode;
#ifdef WIN32
root->currentHandle = currentHandle;
root->currentInfo = currentInfo;
#endif
}
ILibExportMethod void ILibChain_EndContinue(void *chain)
@@ -2735,9 +2977,7 @@ char *ILibChain_GetMetaDataFromDescriptorSet(void *chain, fd_set *inr, fd_set *i
if (len > 0) { ret = ILibScratchPad; }
if (ret == NULL)
{
#if defined(WIN32)
if (FD_ISSET(((ILibBaseChain*)chain)->TerminateSock, ine) || FD_ISSET(((ILibBaseChain*)chain)->TerminateSock, inr)) { ret = "ILibForceUnblockChain"; }
#else
#if !defined(WIN32)
if (FD_ISSET(((ILibBaseChain*)chain)->TerminatePipe[0], inr)) { ret = "ILibForceUnblockChain"; }
#endif
if (ret == NULL)
@@ -2779,6 +3019,255 @@ void *ILibChain_GetObjectForDescriptor(void *chain, int fd)
return(ret);
}
#ifdef WIN32
BOOL ILibChain_WriteEx_Sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, void *user)
{
ILibChain_WriteEx_data *data = (ILibChain_WriteEx_data*)user;
DWORD bytesWritten = 0;
if (GetOverlappedResult(data->fileHandle, data->p, &bytesWritten, FALSE) && bytesWritten > 0)
{
data->bytesLeft -= (int)bytesWritten;
data->totalWritten += (int)bytesWritten;
data->buffer = data->buffer + bytesWritten;
if (data->bytesLeft == 0)
{
// Done Writing
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_NONE, data->totalWritten, data->user); }
ILibMemory_Free(data);
return(FALSE);
}
else
{
// More Data to write
BOOL ret = FALSE;
switch (ILibChain_WriteEx(chain, h, data->p, data->buffer, data->bytesLeft, ILibChain_WriteEx_Sink, data))
{
case ILibTransport_DoneState_COMPLETE:
data->totalWritten += data->bytesLeft;
data->bytesLeft = 0;
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_NONE, data->totalWritten, data->user); }
ILibMemory_Free(data);
ret = FALSE;
break;
case ILibTransport_DoneState_INCOMPLETE:
ret = TRUE;
case ILibTransport_DoneState_ERROR:
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_IO_ERROR, 0, data->user); }
ILibMemory_Free(data);
ret = FALSE;
break;
}
return(ret);
}
}
else
{
if (GetLastError() == ERROR_IO_PENDING)
{
// Still pending, so wait for another callback
return(TRUE);
}
else
{
// ERROR
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_IO_ERROR, 0, data->user); }
ILibMemory_Free(data);
return(FALSE);
}
}
}
BOOL ILibChain_ReadEx_Sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, void *user)
{
ILibChain_ReadEx_data *data = (ILibChain_ReadEx_data*)user;
DWORD bytesRead = 0;
DWORD err;
if (GetOverlappedResult(data->fileHandle, data->p, &bytesRead, FALSE) && bytesRead > 0)
{
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_NONE, data->buffer, bytesRead, data->user); }
ILibMemory_Free(data);
return(FALSE);
}
else
{
if ((err=GetLastError()) == ERROR_IO_PENDING)
{
// Still pending, so wait for another callback
return(TRUE);
}
else
{
// ERROR
if (data->handler != NULL) { data->handler(chain, data->fileHandle, ILibWaitHandle_ErrorStatus_IO_ERROR, data->buffer, 0, data->user); }
ILibMemory_Free(data);
return(FALSE);
}
}
}
ILibTransport_DoneState ILibChain_WriteEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_WriteEx_Handler handler, void *user)
{
int e = 0;
if (!WriteFile(h, buffer, (DWORD)bufferLen, NULL, p))
{
if ((e = GetLastError()) == ERROR_IO_PENDING)
{
// Completing Asynchronously
ILibChain_WriteEx_data *state = (ILibChain_WriteEx_data*)ILibMemory_SmartAllocate(sizeof(ILibChain_WriteEx_data));
state->buffer = buffer;
state->bytesLeft = bufferLen;
state->totalWritten = 0;
state->p = p;
state->handler = handler;
state->fileHandle = h;
state->user = user;
ILibChain_AddWaitHandle(chain, p->hEvent, -1, ILibChain_WriteEx_Sink, state);
return(ILibTransport_DoneState_INCOMPLETE);
}
else
{
// IO Error
return(ILibTransport_DoneState_ERROR);
}
}
else
{
// Write Completed
return(ILibTransport_DoneState_COMPLETE);
}
}
void ILibChain_ReadEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_ReadEx_Handler handler, void *user)
{
DWORD bytesRead = 0;
int e = 0;
if (!ReadFile(h, buffer, bufferLen, &bytesRead, p))
{
if ((e = GetLastError()) == ERROR_IO_PENDING)
{
ILibChain_ReadEx_data *state = (ILibChain_ReadEx_data*)ILibMemory_SmartAllocate(sizeof(ILibChain_ReadEx_data));
state->buffer = buffer;
state->p = p;
state->handler = handler;
state->fileHandle = h;
state->user = user;
ILibChain_AddWaitHandle(chain, p->hEvent, -1, ILibChain_ReadEx_Sink, state);
}
else
{
if (handler != NULL) { handler(chain, h, ILibWaitHandle_ErrorStatus_IO_ERROR, buffer, 0, user); }
}
}
else
{
if (bytesRead > 0)
{
if (handler != NULL) { handler(chain, h, ILibWaitHandle_ErrorStatus_NONE, buffer, bytesRead, user); }
}
else
{
if (handler != NULL) { handler(chain, h, ILibWaitHandle_ErrorStatus_IO_ERROR, buffer, 0, user); }
}
}
}
void __stdcall ILibChain_AddWaitHandle_apc(ULONG_PTR u)
{
void *chain = ((void**)u)[0];
HANDLE h = (HANDLE)((void**)u)[1];
int msTIMEOUT = (int)(uintptr_t)((void**)u)[2];
ILibChain_WaitHandleHandler handler = (ILibChain_WaitHandleHandler)((void**)u)[3];
void *user = ((void**)u)[4];
ILibChain_AddWaitHandle(chain, h, msTIMEOUT, handler, user);
ILibMemory_Free((void*)u);
}
void ILibChain_AddWaitHandle(void *chain, HANDLE h, int msTIMEOUT, ILibChain_WaitHandleHandler handler, void *user)
{
if (!ILibIsRunningOnChainThread(chain))
{
void **tmp = ILibMemory_SmartAllocate(5 * sizeof(void*));
tmp[0] = chain;
tmp[1] = h;
tmp[2] = (void*)(uintptr_t)msTIMEOUT;
tmp[3] = handler;
tmp[4] = user;
QueueUserAPC((PAPCFUNC)ILibChain_AddWaitHandle_apc, ILibChain_GetMicrostackThreadHandle(chain), (ULONG_PTR)tmp);
return;
}
ILibChain_WaitHandleInfo *info = NULL;
if (((ILibBaseChain*)chain)->currentHandle != h)
{
void *node = ILibLinkedList_AddTail(((ILibBaseChain*)chain)->auxSelectHandles, h);
info = (ILibChain_WaitHandleInfo*)ILibMemory_Extra(node);
info->node = node;
ILibForceUnBlockChain(chain);
}
else
{
((ILibBaseChain*)chain)->currentHandle = NULL;
info = ((ILibBaseChain*)chain)->currentInfo;
}
if (info != NULL)
{
info->handler = handler;
info->user = user;
if (msTIMEOUT != INFINITE && msTIMEOUT >= 0)
{
ILibGetTimeOfDay(&(info->expiration));
info->expiration.tv_sec += (long)(msTIMEOUT / 1000);
info->expiration.tv_usec += ((msTIMEOUT % 1000) * 1000);
}
}
}
void __stdcall ILibChain_RemoveWaitHandle_APC(ULONG_PTR u)
{
ILibBaseChain *chain = (ILibBaseChain*)((void**)u)[0];
HANDLE h = (HANDLE)((void**)u)[1];
void *node = ILibLinkedList_GetNode_Search(chain->auxSelectHandles, NULL, h);
if (node != NULL)
{
//
// We found the HANDLE, so if we remove the HANDLE from the list, and
// set the unblock flag, we'll be good to go
//
if (chain->currentHandle == h)
{
chain->currentHandle = NULL; chain->currentInfo = NULL;
}
ILibLinkedList_Remove(node);
chain->UnblockFlag = 1;
}
}
void ILibChain_RemoveWaitHandle(void *chain, HANDLE h)
{
if (ILibIsRunningOnChainThread(chain))
{
void *tmp[2];
tmp[0] = chain;
tmp[1] = h;
ILibChain_RemoveWaitHandle_APC((ULONG_PTR)tmp);
}
else
{
//
// We must dispatch an APC to remove the wait handle,
// because we can't change the wait list during a WaitForMultipleObjectsEx() call
//
void **tmp = (void**)ILibMemory_SmartAllocate(2 * sizeof(void*));
tmp[0] = chain;
tmp[1] = h;
QueueUserAPC((PAPCFUNC)ILibChain_RemoveWaitHandle_APC, ILibChain_GetMicrostackThreadHandle(chain), (ULONG_PTR)tmp);
}
}
#endif
/*! \fn ILibStartChain(void *Chain)
\brief Starts a Chain
\par
@@ -2797,7 +3286,12 @@ ILibExportMethod void ILibStartChain(void *Chain)
fd_set errorset;
fd_set writeset;
struct timeval tv;
#ifdef WIN32
HANDLE selectHandles[FD_SETSIZE];
memset(selectHandles, 0, sizeof(selectHandles));
memset(chain->WaitHandles, 0, sizeof(chain->WaitHandles));
#endif
struct timeval tv;
int slct;
int vX;
@@ -2808,6 +3302,7 @@ ILibExportMethod void ILibStartChain(void *Chain)
chain->ChainThreadID = GetCurrentThreadId();
chain->ChainProcessHandle = GetCurrentProcess();
chain->MicrostackThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, chain->ChainThreadID);
chain->auxSelectHandles = ILibLinkedList_CreateEx(sizeof(ILibChain_WaitHandleInfo));
#else
chain->ChainThreadID = pthread_self();
#endif
@@ -2894,12 +3389,7 @@ ILibExportMethod void ILibStartChain(void *Chain)
tv.tv_usec = 1000 * (chain->selectTimeout % 1000);
#if defined(WIN32) || defined(_WIN32_WCE)
//
// Add the fake socket, for ILibForceUnBlockChain
//
FD_SET(chain->TerminateSock, &errorset);
#else
#if !defined(WIN32)
//
// Put the Read end of the Pipe in the FDSET, for ILibForceUnBlockChain
//
@@ -2925,15 +3415,11 @@ ILibExportMethod void ILibStartChain(void *Chain)
//
chain->PreSelectCount++;
#ifdef WIN32
if (readset.fd_count == 0 && writeset.fd_count == 0)
{
SleepEx((DWORD)chain->selectTimeout, TRUE); // If there is no pending IO, we must force the thread into an alertable wait state, so ILibForceUnblockChain can function.
slct = -1;
}
else
{
slct = select(FD_SETSIZE, &readset, &writeset, &errorset, &tv);
}
int x = 0;
DWORD waitTimeout = 0;
ILibChain_SetupWindowsWaitObject(chain->WaitHandles, &x, &tv, &waitTimeout, &readset, &writeset, &errorset, chain->auxSelectHandles, NULL);
slct = ILibChain_WindowsSelect(chain, &readset, &writeset, &errorset, chain->WaitHandles, x, waitTimeout);
#else
slct = select(FD_SETSIZE, &readset, &writeset, &errorset, &tv);
#endif
@@ -3056,6 +3542,17 @@ ILibExportMethod void ILibStartChain(void *Chain)
chain->node = ILibLinkedList_Remove(chain->node);
}
#ifdef WIN32
for (vX = 0; vX < FD_SETSIZE; ++vX)
{
if (chain->WaitHandles[vX] != NULL && chain->WaitHandles[ILibChain_HandleInfoIndex(vX)] == NULL)
{
WSACloseEvent(chain->WaitHandles[vX]);
}
}
ILibLinkedList_Destroy(chain->auxSelectHandles);
#endif
if (gILibChain == Chain) { gILibChain = NULL; } // Reset the global instance if it was set
//
@@ -3102,13 +3599,6 @@ ILibExportMethod void ILibStartChain(void *Chain)
((ILibBaseChain*)Chain)->TerminatePipe[0] = 0;
((ILibBaseChain*)Chain)->TerminatePipe[1] = 0;
#endif
#if defined(WIN32)
if (((ILibBaseChain*)Chain)->TerminateSock != ~0)
{
closesocket(((ILibBaseChain*)Chain)->TerminateSock);
((ILibBaseChain*)Chain)->TerminateSock = (SOCKET)~0;
}
#endif
#ifdef WIN32
WSACleanup();
@@ -6931,6 +7421,7 @@ void* ILibLinkedList_InsertAfter(void *LinkedList_Node, void *data)
*/
void* ILibLinkedList_Remove(void *LinkedList_Node)
{
if (!ILibMemory_CanaryOK(LinkedList_Node)) { return(NULL); }
struct ILibLinkedListNode_Root *r;
struct ILibLinkedListNode *n;
void* RetVal;
@@ -8062,7 +8553,7 @@ int ILibReadFileFromDiskEx(char **Target, char *FileName)
FILE *SourceFile = NULL;
#ifdef WIN32
fopen_s(&SourceFile, FileName, "rb");
_wfopen_s(&SourceFile, ILibUTF8ToWide(FileName, -1), L"rb");
#else
SourceFile = fopen(FileName, "rb");
#endif
@@ -8111,7 +8602,7 @@ void ILibWriteStringToDiskEx(char *FileName, char *data, int dataLen)
FILE *SourceFile = NULL;
#ifdef WIN32
fopen_s(&SourceFile, FileName, "wb");
_wfopen_s(&SourceFile, ILibUTF8ToWide(FileName, -1), L"wb");
#else
SourceFile = fopen(FileName, "wb");
#endif
@@ -8127,7 +8618,7 @@ void ILibAppendStringToDiskEx(char *FileName, char *data, int dataLen)
FILE *SourceFile = NULL;
#ifdef WIN32
fopen_s(&SourceFile, FileName, "ab");
_wfopen_s(&SourceFile, ILibUTF8ToWide(FileName, -1), L"ab");
#else
SourceFile = fopen(FileName, "ab");
#endif
@@ -9647,7 +10138,7 @@ void ILibLinkedList_FileBacked_Reset(ILibLinkedList_FileBacked_Root *root)
fclose(source);
source = NULL;
#ifdef WIN32
fopen_s(&source, (char*)ptr[1], "wb+N");
_wfopen_s(&source, ILibUTF8ToWide((char*)ptr[1], -1), L"wb+N");
#else
source = fopen((char*)ptr[1], "wb+");
#endif
@@ -9721,9 +10212,9 @@ ILibLinkedList_FileBacked_Root* ILibLinkedList_FileBacked_Create(char* path, uns
ILibLinkedList_FileBacked_Root *retVal = NULL;
#ifdef WIN32
if (fopen_s(&source, path, "rb+N") != 0)
if (_wfopen_s(&source, ILibUTF8ToWide(path, -1), L"rb+N") != 0)
{
fopen_s(&source, path, "wb+N");
_wfopen_s(&source, ILibUTF8ToWide(path, -1), L"wb+N");
}
#else
if ((source = fopen(path, "rb+")) == NULL)

View File

@@ -170,6 +170,26 @@ static inline void ignore_result(uintptr_t result) { (void)result; }
#define PRINTERROR()
#endif
#ifdef WIN32
char *ILibWideToUTF8Ex(WCHAR* wstr, int wstrCharacterLen, char *buffer, int bufferLen);
#define ILibWideToUTF8(wstr, wstrCharacterLen) ILibWideToUTF8Ex(wstr, wstrCharacterLen, NULL, 0)
char *ILibWideToUTF8_stupidEx(WCHAR* wstr, int wstrBYTESIZE, char *buffer, int bufferLen);
#define ILibWideToUTF8_stupid(wstr, wstrBYTESIZE) ILibWideToUTF8_stupidEx(wstr, wstrBYTESIZE, NULL, 0)
WCHAR* ILibUTF8ToWideEx(char* str, int len, WCHAR* buffer, int bufferCharacterSize);
#define ILibUTF8ToWide(utf8string, len) ILibUTF8ToWideEx(utf8string, len, NULL, 0)
#else
#define ILibWideToUTF8(wstr, len) (wstr)
#define ILibWideToUTF8Ex(wstr, len, buffer, sz) (wstr)
#define ILibUTF8toWide(str, len) (str)
#define ILibUTF8ToWideEx(str, len, buffer, ccsz) (str)
#endif
int ILibGetLocalTime(char *dest, int destLen);
long ILibGetTimeStamp();
@@ -327,6 +347,18 @@ int ILibIsRunningOnChainThread(void* chain);
typedef void*(*ILibChain_Link_GetUserMemory)(void *ChainLinkObject, int *len);
typedef void* ILibChain_EventHookToken;
typedef void(*ILibChain_EventHookHandler)(void *hookedObject, ILibChain_EventHookToken token);
#ifdef WIN32
typedef enum ILibWaitHandle_ErrorStatus
{
ILibWaitHandle_ErrorStatus_NONE = 0,
ILibWaitHandle_ErrorStatus_INVALID_HANDLE = 1,
ILibWaitHandle_ErrorStatus_TIMEOUT = 2,
ILibWaitHandle_ErrorStatus_REMOVED = 3,
ILibWaitHandle_ErrorStatus_MANAGER_EXITING = 4,
ILibWaitHandle_ErrorStatus_IO_ERROR = 5
}ILibWaitHandle_ErrorStatus;
typedef BOOL(*ILibChain_WaitHandleHandler)(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus, void* user);
#endif
typedef struct ILibChain_Link
{
@@ -941,9 +973,44 @@ int ILibIsRunningOnChainThread(void* chain);
void ILibChain_DisableWatchDog(void *chain);
void *ILibChain_GetObjectForDescriptor(void *chain, int fd);
char *ILibChain_GetMetaDataFromDescriptorSet(void *chain, fd_set *inr, fd_set *inw, fd_set *ine);
#ifdef WIN32
typedef void(*ILib_GenericReadHandler)(char *buffer, int bufferLen, int* bytesConsumed, void* user1, void *user2);
typedef BOOL(*ILibChain_ReadEx_Handler)(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, char *buffer, int bytesRead, void* user);
typedef BOOL(*ILibChain_WriteEx_Handler)(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, int bytesWritten, void* user);
typedef struct ILibChain_ReadEx_data
{
char *buffer;
ILibChain_ReadEx_Handler handler;
HANDLE fileHandle;
OVERLAPPED *p;
void *user;
}ILibChain_ReadEx_data;
typedef struct ILibChain_WriteEx_data
{
ILibChain_WriteEx_Handler handler;
char *buffer;
int bytesLeft;
int totalWritten;
HANDLE fileHandle;
OVERLAPPED *p;
void *user;
}ILibChain_WriteEx_data;
void ILibChain_AddWaitHandle(void *chain, HANDLE h, int msTIMEOUT, ILibChain_WaitHandleHandler handler, void *user);
void ILibChain_RemoveWaitHandle(void *chain, HANDLE h);
void ILibChain_ReadEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_ReadEx_Handler handler, void *user);
ILibTransport_DoneState ILibChain_WriteEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_WriteEx_Handler handler, void *user);
#define tv2LTtv1(ptv1, ptv2) ((ptv2)->tv_sec < (ptv1)->tv_sec || ((ptv2)->tv_sec == (ptv1)->tv_sec && (ptv2)->tv_usec < (ptv1)->tv_usec))
#define tv2LTEtv1(ptv1, ptv2) (tv2LTtv1(ptv2,ptv1) || ((ptv2)->tv_sec == (ptv1)->tv_sec && (ptv2)->tv_usec <= (ptv1)->tv_usec))
#define tvnonzero(ptv) ((ptv)->tv_sec != 0 || (ptv)->tv_usec != 0)
#endif
ILibExportMethod void ILibStartChain(void *chain);
ILibExportMethod void ILibStopChain(void *chain);
#ifdef WIN32
ILibExportMethod void ILibChain_Continue(void *chain, ILibChain_Link **modules, int moduleCount, int maxTimeout, HANDLE **handles);
#else
ILibExportMethod void ILibChain_Continue(void *chain, ILibChain_Link **modules, int moduleCount, int maxTimeout);
#endif
ILibExportMethod void ILibChain_EndContinue(void *chain);
ILibChain_ContinuationStates ILibChain_GetContinuationState(void *chain);
#define ILibChain_FreeLink(link) ((ILibChain_Link*)link)->RESERVED = 0xFFFFFFFF;free(link);

File diff suppressed because it is too large Load Diff

View File

@@ -60,7 +60,7 @@ void ILibProcessPipe_Pipe_AddPipeReadHandler(ILibProcessPipe_Pipe targetPipe, in
#ifdef WIN32
int ILibProcessPipe_Pipe_CancelEx(ILibProcessPipe_Pipe targetPipe);
int ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_ReadExHandler OnReadHandler);
int ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler);
ILibTransport_DoneState ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler);
ILibProcessPipe_Pipe ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(ILibProcessPipe_Manager manager, HANDLE existingPipe, ILibProcessPipe_Pipe_ReaderHandleType handleType, int extraMemorySize);
#define ILibProcessPipe_Pipe_CreateFromExisting(PipeManager, ExistingPipe, HandleType) ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(PipeManager, ExistingPipe, HandleType, 0)
#else
@@ -86,6 +86,9 @@ void ILibProcessPipe_Process_RemoveHandlers(ILibProcessPipe_Process module);
void ILibProcessPipe_Process_UpdateUserObject(ILibProcessPipe_Process module, void *userObj);
ILibTransport_DoneState ILibProcessPipe_Process_WriteStdIn(ILibProcessPipe_Process p, char* buffer, int bufferLen, ILibTransport_MemoryOwnership ownership);
void ILibProcessPipe_Process_CloseStdIn(ILibProcessPipe_Process p);
#ifdef WIN32
void ILibProcessPipe_Process_GetWaitHandles(ILibProcessPipe_Process p, HANDLE *hProcess, HANDLE *read, HANDLE *write, HANDLE *error);
#endif
void ILibProcessPipe_Pipe_Close(ILibProcessPipe_Pipe po);
void ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Pipe pipeObject);
@@ -100,28 +103,5 @@ pid_t ILibProcessPipe_Process_GetPID(ILibProcessPipe_Process p);
int ILibProcessPipe_Process_GetPTY(ILibProcessPipe_Process p);
#endif
#ifdef WIN32
typedef enum ILibWaitHandle_ErrorStatus
{
ILibWaitHandle_ErrorStatus_NONE = 0,
ILibWaitHandle_ErrorStatus_INVALID_HANDLE = 1,
ILibWaitHandle_ErrorStatus_TIMEOUT = 2,
ILibWaitHandle_ErrorStatus_REMOVED = 3,
ILibWaitHandle_ErrorStatus_MANAGER_EXITING = 4
}ILibWaitHandle_ErrorStatus;
typedef BOOL(*ILibProcessPipe_WaitHandle_Handler)(HANDLE event, ILibWaitHandle_ErrorStatus status, void* user);
void ILibProcessPipe_WaitHandle_Remove(ILibProcessPipe_Manager mgr, HANDLE event);
// These methods will dispatch the callback on the worker thread
void ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(ILibProcessPipe_Manager mgr, HANDLE event, int milliseconds, void *user, ILibProcessPipe_WaitHandle_Handler callback);
#define ILibProcessPipe_WaitHandle_Add(processPipeManager, eventHandle, user, callback) ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(processPipeManager, eventHandle, 0, user, callback)
// These methods will context switch to the chain thread when dispatching
void ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(ILibProcessPipe_Manager mgr, HANDLE event, int milliseconds, void *user, ILibProcessPipe_WaitHandle_Handler callback);
#define ILibProcessPipe_WaitHandle_Add2(processPipeManager, eventHandle, user, callback) ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(processPipeManager, eventHandle, 0, user, callback)
#endif
#define ILibTransports_ProcessPipe 0x60
#endif

View File

@@ -501,18 +501,18 @@ FILE* ILibSimpleDataStore_OpenFileEx2(char* filePath, int forceTruncateIfNonZero
HANDLE h = NULL;
if (forceTruncateIfNonZero != 0)
{
h = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
h = CreateFileW(ILibUTF8ToWide(filePath, -1), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
{
h = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
h = CreateFileW(ILibUTF8ToWide(filePath, -1), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
}
}
else
{
h = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
h = CreateFileW(ILibUTF8ToWide(filePath, -1), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
{
h = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
h = CreateFileW(ILibUTF8ToWide(filePath, -1), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
}
}
int fd = _open_osfhandle((intptr_t)h, _O_RDWR);
@@ -522,7 +522,7 @@ FILE* ILibSimpleDataStore_OpenFileEx2(char* filePath, int forceTruncateIfNonZero
}
else
{
HANDLE h = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE h = CreateFileW(ILibUTF8ToWide(filePath, -1), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) { return(NULL); }
int fd = _open_osfhandle((intptr_t)h, _O_RDONLY);
if (fd == -1) { CloseHandle(h); return(NULL); }
@@ -547,7 +547,7 @@ FILE* ILibSimpleDataStore_OpenFileEx2(char* filePath, int forceTruncateIfNonZero
int ILibSimpleDataStore_Exists(char *filePath)
{
#ifdef WIN32
return(_access(filePath, 0) == 0 ? 1 : 0);
return(_waccess(ILibUTF8ToWide(filePath, -1), 0) == 0 ? 1 : 0);
#else
return(access(filePath, 0) == 0 ? 1 : 0);
#endif
@@ -557,18 +557,21 @@ __EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx2(char* filePath,
{
ILibSimpleDataStore_Root* retVal = (ILibSimpleDataStore_Root*)ILibMemory_Allocate(ILibMemory_SimpleDataStore_CONTAINERSIZE, userExtraMemorySize, NULL, NULL);
retVal->filePath = ILibString_Copy(filePath, (int)strnlen_s(filePath, ILibSimpleDataStore_MaxFilePath));
retVal->dataFile = ILibSimpleDataStore_OpenFileEx2(retVal->filePath, 0, readonly);
if (retVal->dataFile == NULL)
if (filePath != NULL)
{
free(retVal->filePath);
free(retVal);
return NULL;
retVal->filePath = ILibString_Copy(filePath, (int)strnlen_s(filePath, ILibSimpleDataStore_MaxFilePath));
retVal->dataFile = ILibSimpleDataStore_OpenFileEx2(retVal->filePath, 0, readonly);
if (retVal->dataFile == NULL)
{
free(retVal->filePath);
free(retVal);
return NULL;
}
}
retVal->keyTable = ILibHashtable_Create();
ILibSimpleDataStore_RebuildKeyTable(retVal);
if (retVal->dataFile != NULL) { ILibSimpleDataStore_RebuildKeyTable(retVal); }
return retVal;
}
@@ -592,13 +595,15 @@ __EXPORT_TYPE void ILibSimpleDataStore_Close(ILibSimpleDataStore dataStore)
ILibHashtable_DestroyEx(root->keyTable, ILibSimpleDataStore_TableClear_Sink, root);
if (root->cacheTable != NULL) { ILibHashtable_DestroyEx(root->cacheTable, ILibSimpleDataStore_CacheClear_Sink, NULL); }
free(root->filePath);
if (root->filePath != NULL)
{
free(root->filePath);
#ifdef _POSIX
flock(fileno(root->dataFile), LOCK_UN);
flock(fileno(root->dataFile), LOCK_UN);
#endif
fclose(root->dataFile);
}
fclose(root->dataFile);
free(root);
}
@@ -858,8 +863,10 @@ __EXPORT_TYPE int ILibSimpleDataStore_Compact(ILibSimpleDataStore dataStore)
// Now we copy the temporary data store over the data store, making it the new valid version
#ifdef WIN32
if (CopyFileA(tmp, root->filePath, FALSE) == FALSE) { retVal = 1; }
DeleteFile(tmp);
WCHAR tmptmp[4096];
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)tmp, -1, (LPWSTR)tmptmp, (int)sizeof(tmptmp) / 2);
if (CopyFileW(tmptmp, ILibUTF8ToWide(root->filePath, -1), FALSE) == FALSE) { retVal = 1; }
DeleteFileW(tmptmp);
#else
if (rename(tmp, root->filePath) != 0) { retVal = 1; }
#endif

View File

@@ -45,7 +45,7 @@ typedef void(*ILibSimpleDataStore_SizeWarningHandler)(ILibSimpleDataStore sender
__EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx2(char* filePath, int userExtraMemorySize, int readonly);
#define ILibSimpleDataStore_Create(filePath) ILibSimpleDataStore_CreateEx2(filePath, 0, 0)
#define ILibSimpleDataStore_CreateEx(filePath, userExtraMemorySize) ILibSimpleDataStore_CreateEx2(filePath, userExtraMemorySize, 0)
#define ILibSimpleDataStore_CreateCachedOnly() ILibSimpleDataStore_Create(NULL)
// Check if the data store exists
int ILibSimpleDataStore_Exists(char *filePath);

View File

@@ -149,4 +149,60 @@ function addMsh(options)
}
}
module.exports = addMsh;
try
{
module.exports = addMsh;
}
catch(e)
{
// We were run from the command line
var outputFile = null;
var inputFile = null;
var msh = null;
for (var i = 1; i < process.argv.length; i += 2)
{
switch (process.argv[i])
{
case '-o':
outputFile = process.argv[i + 1];
break;
case '-i':
inputFile = process.argv[i + 1];
break;
default:
console.log('unrecognized parameter: ' + process.argv[i]);
break;
}
}
if (process.argv.length != 5 || outputFile == null || inputFile == null)
{
console.log('usage: ' + process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop() + ' MSH_Installer.js -o outputFile -i mshFile');
process.exit();
}
try
{
msh = require('fs').readFileSync(inputFile);
}
catch(e)
{
console.log('Unable to read ' + inputFile, e);
process.exit();
}
var options =
{
destinationStream: require('fs').createWriteStream(outputFile, { flags: 'wb' }),
sourceFileName: process.execPath,
msh: msh
};
console.log('Creating MSH integrated binary...');
options.destinationStream.on('close', function () { console.log('DONE'); process.exit(); });
addMsh(options);
}

View File

@@ -18,17 +18,39 @@ limitations under the License.
function installService(params)
{
process.stdout.write('...Installing service');
var options =
{
name: 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
};
var i;
if ((i=params.indexOf('--_localService="1"'))>=0)
{
// install in place
options.parameters.splice(i, 1);
options.installInPlace = true;
}
for (i = 0; i < options.parameters.length; ++i)
{
if(options.parameters[i].startsWith('--installPath='))
{
options.installPath = options.parameters[i].split('=')[1];
if (options.installPath.startsWith('"')) { options.installPath = options.installPath.substring(1, options.installPath.length - 1); }
options.parameters.splice(i, 1);
options.installInPlace = false;
break;
}
}
try
{
require('service-manager').manager.installService(
{
name: 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
});
require('service-manager').manager.installService(options);
process.stdout.write(' [DONE]\n');
}
catch(sie)
@@ -154,7 +176,7 @@ function uninstallService3(params)
process.stdout.write(' [ERROR]\n');
}
}
if (params != null)
if (params != null && !params.includes('_stop'))
{
installService(params);
}
@@ -167,12 +189,55 @@ function uninstallService3(params)
function uninstallService2(params)
{
var secondaryagent = false;
var i;
var dataFolder = null;
var appPrefix = null;
if (params && params.includes('--_deleteData="1"'))
{
for (i = 0; i < params.length; ++i)
{
if (params[i].startsWith('_workingDir='))
{
dataFolder = params[i].split('=')[1];
if (dataFolder.startsWith('"')) { dataFolder = dataFolder.substring(1, dataFolder.length - 1); }
}
if (params[i].startsWith('_appPrefix='))
{
appPrefix = params[i].split('=')[1];
if (appPrefix.startsWith('"')) { appPrefix = appPrefix.substring(1, appPrefix.length - 1); }
}
}
}
process.stdout.write(' -> Uninstalling previous installation...');
try
{
require('service-manager').manager.uninstallService(process.platform == 'win32' ? 'Mesh Agent' : 'meshagent');
process.stdout.write(' [DONE]\n');
if (dataFolder && appPrefix)
{
process.stdout.write(' -> Deleting agent data...');
if (process.platform != 'win32')
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.on('data', function (c) { });
child.stderr.on('data', function (c) { });
child.stdin.write('cd ' + dataFolder + '\n');
child.stdin.write('rm ' + appPrefix + '.*\r\n');
child.stdin.write('exit\n');
child.waitExit();
}
else
{
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/C del "' + dataFolder + '\\' + appPrefix + '.*"']);
child.stdout.on('data', function (c) { });
child.stderr.on('data', function (c) { });
child.waitExit();
}
process.stdout.write(' [DONE]\n');
}
}
catch (e)
{
@@ -288,15 +353,23 @@ function serviceExists(loc, params)
}
}
function fullUninstall()
function fullUninstall(jsonString)
{
console.setDestination(console.Destinations.DISABLED);
var parms = JSON.parse(jsonString);
parms.push('_stop');
try
{
process.stdout.write('...Checking for previous installation');
var s = require('service-manager').manager.getService(process.platform == 'win32' ? 'Mesh Agent' : 'meshagent');
var loc = s.appLocation();
var appPrefix = loc.split(process.platform == 'win32' ? '\\' : '/').pop();
if (process.platform == 'win32') { appPrefix = appPrefix.substring(0, appPrefix.length - 4); }
parms.push('_workingDir=' + s.appWorkingDirectory());
parms.push('_appPrefix=' + appPrefix);
s.close();
}
catch (e)
@@ -304,7 +377,7 @@ function fullUninstall()
process.stdout.write(' [NONE]\n');
process.exit();
}
serviceExists(loc, null);
serviceExists(loc, parms);
}
function fullInstall(jsonString)

242
modules/child-container.js Normal file
View File

@@ -0,0 +1,242 @@
/*
Copyright 2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
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.
*/
function childContainer()
{
this._ObjectID = 'child-container';
this.create = function create(options)
{
if (!options || !options.launch || !options.launch.module || !options.launch.method || !options.launch.args) { throw ('Invalid Parameters'); }
var ipcInteger;
var ret = { options: options };
require('events').EventEmitter.call(ret, true)
.createEvent('ready')
.createEvent('message')
.createEvent('exit')
.addMethod('disconnect', function ()
{
console.log('Disconnect child =>');
this._client.end();
})
.addMethod('message', function (msg)
{
this.send({ command: 'message', value: msg });
})
.addMethod('exit', function (code)
{
this.send({ command: 'exit', value: code });
})
.addMethod('send', function (obj)
{
if (!this._client) { throw ('Not Connected'); }
var d, h = Buffer.alloc(4);
d = Buffer.from(JSON.stringify(obj));
h.writeUInt32LE(d.length + 4);
this._client.write(h);
this._client.write(d);
});
ret._ipc = require('net').createServer(); ret._ipc.parent = ret;
ret._ipc.on('close', function () { console.log('Child Container Process Closed'); });
while (true)
{
if (options._debugIPC && options._ipcInteger != null)
{ ipcInteger = options._ipcInteger; }
else
{
ipcInteger = require('tls').generateRandomInteger('1000', '9999');
}
ret._ipcPath = '\\\\.\\pipe\\taskRedirection-' + ipcInteger;
try
{
ret._ipc.listen({ path: ret._ipcPath, writableAll: true });
break;
}
catch (x)
{
if(options._ipcInteger != null)
{
console.log('DebugError: Unable to bind to IPC channel: ' + ipcInteger);
return (ret);
}
}
}
var script = Buffer.from("console.log('CHILD/START');require('child-container').connect('" + ipcInteger + "');").toString('base64');
ret._ipc.once('connection', function onConnect(s)
{
this.parent._client = s;
this.parent._client._parent = this;
var data;
for (var m in this.parent.options.modules)
{
data = { command: 'addModule', value: { name: this.parent.options.modules[m].name, js: this.parent.options.modules[m].script } };
this.parent.send(data);
}
data = { command: 'launch', value: { module: this.parent.options.launch.module, method: this.parent.options.launch.method, args: this.parent.options.launch.args } };
this.parent.send(data);
s.once('close', function ()
{
console.log('close emitted');
require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: 'close emitted'});
});
s.on('data', function (c)
{
var cLen;
if (c.length < 4 || (cLen = c.readUInt32LE(0)) > c.length) { this.unshift(c); return; }
var cmd = JSON.parse(c.slice(4, cLen).toString());
switch (cmd.command)
{
case 'message':
this._parent.parent.emit('message', cmd.value);
break;
default:
break;
}
if (cLen < c.length) { this.unshift(c.slice(cLen)); }
});
this.parent.emit('ready');
});
if (options._debugIPC)
{
console.log('-b64exec ' + script);
return (ret);
}
// Spawn the child
if(options.user && process.platform == 'win32')
{
// Use Task Scheduler
var parms = '/C SCHTASKS /CREATE /F /TN MeshUserTask /SC ONCE /ST 00:00 ';
parms += ('/RU ' + options.user + ' ');
parms += ('/TR "\\"' + process.execPath + '\\" -b64exec ' + script + '"');
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', [parms]);
child.stderr.on('data', function (c) { });
child.stdout.on('data', function (c) { });
child.waitExit();
child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['cmd']);
child.stderr.on('data', function (c) { });
child.stdout.on('data', function (c) { });
child.stdin.write('SCHTASKS /RUN /TN MeshUserTask\r\n');
child.stdin.write('SCHTASKS /DELETE /F /TN MeshUserTask\r\nexit\r\n');
child.waitExit();
}
else
{
var child_options = {};
if(options.uid != null)
{
var tsid;
if ((tsid = require('user-sessions').getProcessOwnerName(process.pid).tsid) == 0)
{
// We are running as LocalSystem
child_options.uid = options.uid;
child_options.type = require('child_process').SpawnTypes.USER;
}
else
{
// We won't be able to switch session IDs, so check to make sure we are running as this sid
if (options.sid != tsid) { throw ('Insufficient permission to run as this user'); }
}
}
ret._proc = require('child_process').execFile(process.execPath, [process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(), '-b64exec', script], child_options);
ret._proc.parent = ret;
ret._proc.stdout.on('data', function (c) { });
ret._proc.stderr.on('data', function (c) { });
ret._proc.on('exit', function (code)
{
this.parent.emit('exit', code);
});
}
return (ret);
}
this.connect = function (ipcNumber)
{
var ipcPath = '\\\\.\\pipe\\taskRedirection-' + ipcNumber;
this._ipcClient = require('net').createConnection({ path: ipcPath }, function ()
{
this.on('close', function () { process._exit(0); });
this.on('data', function (c)
{
var cLen;
if (c.length < 4 || (cLen = c.readUInt32LE(0)) > c.length) { this.unshift(c); return; }
var cmd = JSON.parse(c.slice(4, cLen).toString());
switch (cmd.command)
{
case 'addModule':
addModule(cmd.value.name, cmd.value.js);
break;
case 'launch':
var obj = require(cmd.value.module);
this._result = obj[cmd.value.method].apply(obj, cmd.value.args);
this.on('end', function () { process.exit(); });
break;
case 'message':
this._parent.emit('message', cmd.value);
break;
case '_disconnect':
console.log('Disconnecting...');
this.end();
break;
case 'exit':
try
{
this._parent.emit('exit');
}
catch (ee)
{ }
process._exit(0);
break;
}
if (cLen < c.length) { this.unshift(c.slice(cLen)); }
});
});
this._ipcClient._parent = this;
require('events').EventEmitter.call(this, true)
.createEvent('message')
.createEvent('exit')
.addMethod('message', function (msg)
{
this.send({ command: 'message', value: msg });
})
.addMethod('send', function (data)
{
if (!this._ipcClient) { throw ('Not Connected'); }
var d, h = Buffer.alloc(4);
d = Buffer.from(JSON.stringify(data));
h.writeUInt32LE(d.length + 4);
this._ipcClient.write(h);
this._ipcClient.write(d);
});
};
}
module.exports = new childContainer();

View File

@@ -1,5 +1,5 @@
/*
Copyright 2019 Intel Corporation
Copyright 2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ const MB_YESNO = 0x00000004;
const MB_RETRYCANCEL = 0x00000005;
const MB_TOPMOST = 0x00040000;
const MB_SETFOREGROUND = 0x00010000;
const MB_SYSTEMMODAL = 0x00001000;
const MB_DEFBUTTON1 = 0x00000000;
const MB_DEFBUTTON2 = 0x00000100;
@@ -39,110 +40,126 @@ const IDRETRY = 4;
const IDIGNORE = 5;
const IDYES = 6;
const IDNO = 7;
const WM_CLOSE = 0x0010;
var promise = require('promise');
var childScript = "\
require('ScriptContainer').on('data', function (j)\
{\
switch(j.command)\
{\
case 'messageBox':\
if(process.platform == 'win32')\
{\
var GM = require('_GenericMarshal');\
var user32 = GM.CreateNativeProxy('user32.dll');\
user32.CreateMethod('MessageBoxA');\
user32.MessageBoxA.async(0, GM.CreateVariable(j.caption), GM.CreateVariable(j.title), j.layout).then(\
function(r)\
{\
switch(r.Val)\
{\
case " + IDOK.toString() + ":\
case " + IDCANCEL.toString() + ":\
case " + IDABORT.toString() + ":\
case " + IDRETRY.toString() + ":\
case " + IDIGNORE.toString() + ":\
case " + IDYES.toString() + ":\
require('ScriptContainer').send(r.Val);\
break;\
default:\
require('ScriptContainer').send(" + IDNO.toString() + ");\
break;\
}\
process.exit();\
});\
}\
break;\
}\
});\
";
function messageBox()
{
this._ObjectID = 'message-box';
this.create = function create(title, caption, timeout, layout)
this.create = function create(title, caption, timeout, layout, sid)
{
if (layout == null)
{
layout = (MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION | MB_TOPMOST);
}
else
{
layout = (MB_OK | MB_DEFBUTTON2 | MB_ICONEXCLAMATION | MB_TOPMOST);
}
var GM = require('_GenericMarshal');
var kernel32 = GM.CreateNativeProxy('kernel32.dll');
kernel32.CreateMethod('ProcessIdToSessionId');
var psid = GM.CreateVariable(4);
if (kernel32.ProcessIdToSessionId(process.pid, psid).Val == 0)
{
ret._rej('Internal Error');
return (ret);
}
if (timeout == null) { timeout = 10; }
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
var options = { executionTimeout: timeout };
ret.options = { launch: { module: 'message-box', method: 'slave', args: [] } };
ret.title = title;
ret.caption = caption;
ret.timeout = timeout;
ret.layout = layout;
//ret.options._debugIPC = true;
//ret.options._ipcInteger = 1500;
try
{
options.sessionId = require('user-sessions').consoleUid();
if (options.sessionId == psid.toBuffer().readUInt32LE()) { delete options.sessionId; }
ret.options.uid = sid == null ? require('user-sessions').consoleUid() : sid;
if (ret.options.uid == require('user-sessions').getProcessOwnerName(process.pid).tsid) { delete ret.options.uid; }
}
catch(ee)
catch (ee)
{
ret._rej('No logged on users');
return (ret);
}
ret._title = title;
ret._caption = caption;
ret._container = require('ScriptContainer').Create(options);
ret._container.promise = ret;
ret._container.on('data', function (j)
ret._ipc = require('child-container').create(ret.options);
ret._ipc.master = ret;
ret._ipc.on('ready', function ()
{
this.promise._container = null;
if(j == IDYES || j == IDOK)
if (this.master.timeout != null) { this.master._timeout = setTimeout(function (mstr) { mstr._ipc.exit(); }, this.master.timeout * 1000, this.master); }
if (this.master.layout == null)
{
this.promise._res();
this.message({ command: 'YESNO', caption: this.master.caption, title: this.master.title });
}
else
{
this.promise._rej('Denied');
this.message({ command: 'ALERT', caption: this.master.caption, title: this.master.title });
}
});
ret._container.on('exit', function ()
ret._ipc.on('message', function (msg)
{
this.promise._container = null;
this.promise._rej('Timeout');
try
{
switch(msg.command)
{
case 'response':
if (this.master._timeout) { clearTimeout(this.master._timeout); this.master._timeout = null; }
if (msg.response == IDYES || msg.response == IDOK)
{
this.master._res();
}
else
{
this.master._rej(msg.response);
}
break;
default:
break;
}
}
catch(ff)
{
}
});
ret._container.ExecuteString(childScript);
ret._container.send({ command: 'messageBox', caption: caption, title: title, layout: layout });
ret.close = function ()
ret._ipc.on('exit', function (c) { this.master._rej('child exited with code: ' + c); });
ret.close = function close()
{
this._container.exit2();
ret._ipc.exit();
};
return (ret);
};
this.slave = function()
{
var master = require('child-container');
master.on('message', function (msg)
{
switch(msg.command)
{
case 'YESNO':
case 'ALERT':
this.GM = require('_GenericMarshal');
this.user32 = this.GM.CreateNativeProxy('user32.dll');
this.user32.CreateMethod('MessageBoxA');
layout = msg.command == 'YESNO' ? (MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION | MB_TOPMOST | MB_SYSTEMMODAL) : (MB_OK | MB_DEFBUTTON2 | MB_ICONEXCLAMATION | MB_TOPMOST | MB_SYSTEMMODAL);
this.user32.MessageBoxA.async(0, this.GM.CreateVariable(msg.caption), this.GM.CreateVariable(msg.title), layout)
.then(function (r)
{
try
{
switch(r.Val)
{
case IDOK:
case IDCANCEL:
case IDABORT:
case IDRETRY:
case IDIGNORE:
case IDYES:
this.that.message({command: 'response', response: r.Val});
break;
default:
this.that.message({command: 'response', response: IDNO});
break;
}
}
catch(ff)
{
}
process.exit();
}, function () { process.exit(); }).parentPromise.that = this;
break;
default:
break;
}
});
}
}
@@ -180,7 +197,7 @@ function linux_messageBox()
var child = require('child_process').execFile('/bin/sh', ['sh'], { uid: uid, env: { XAUTHORITY: xinfo.xauthority ? xinfo.xauthority : "", DISPLAY: xinfo.display } });
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
child.stdin.write(location + ' --help-all | grep timeout\nexit\n');
child.stderr.on('data', function (e) { console.log(e); });
child.stderr.on('data', function (e) { });
child.waitExit();
return (child.stdout.str.trim() == '' ? false : true);
}
@@ -266,6 +283,7 @@ function linux_messageBox()
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
var uid;
var xinfo;
var min = require('user-sessions').minUid();
try
{
@@ -278,7 +296,7 @@ function linux_messageBox()
xinfo = require('monitor-info').getXInfo(0);
}
if (xinfo == null)
if (xinfo == null || (uid != 0 && uid < min))
{
ret._rej('This system cannot display a user dialog box when a user is not logged in');
return (ret);
@@ -589,8 +607,6 @@ function macos_messageBox()
this.startClient = function startClient(options)
{
// Create the Client
console.log('Starting Client...');
options.osversion = require('service-manager').getOSVersion();
options.uid = require('user-sessions').consoleUid();
this.client = require('net').createConnection(options);

View File

@@ -109,97 +109,142 @@ function monitorinfo()
else if (process.platform == 'linux')
{
// First thing we need to do, is determine where the X11 libraries are
this._check = function _check()
{
var ix;
if(!this.Location_X11LIB)
{
var x11info = getLibInfo('libX11');
for (ix in x11info)
{
if (x11info.length == 1 || x11info[ix].hwcap == "0")
{
try
{
Object.defineProperty(this, 'Location_X11LIB', { value: x11info[ix].path });
break;
}
catch (ex)
{
}
}
}
try
{
if (process.env['Location_X11LIB']) { Object.defineProperty(this, 'Location_X11LIB', { value: process.env['Location_X11LIB'] }); }
}
catch(xx)
{
}
}
if(!this.Location_X11TST)
{
var xtstinfo = getLibInfo('libXtst');
for (ix in xtstinfo)
{
if (xtstinfo.length == 1 || xtstinfo[ix].hwcap == "0")
{
try
{
Object.defineProperty(this, 'Location_X11TST', { value: xtstinfo[ix].path });
break;
}
catch (ex)
{
}
}
}
try
{
if (process.env['Location_X11TST']) { Object.defineProperty(this, 'Location_X11TST', { value: process.env['Location_X11TST'] }); }
}
catch (xx)
{
}
// Sufficient access rights to use ldconfig
var x11info = getLibInfo('libX11');
var xtstinfo = getLibInfo('libXtst');
var xextinfo = getLibInfo('libXext');
var xfixesinfo = getLibInfo('libXfixes');
var ix;
}
if(!this.Location_X11EXT)
{
var xextinfo = getLibInfo('libXext');
for (ix in xextinfo)
{
if (xextinfo.length == 1 || xextinfo[ix].hwcap == "0")
{
try
{
Object.defineProperty(this, 'Location_X11EXT', { value: xextinfo[ix].path });
break;
}
catch (ex)
{
}
}
}
try
{
if (process.env['Location_X11EXT']) { Object.defineProperty(this, 'Location_X11EXT', { value: process.env['Location_X11EXT'] }); }
}
catch(xx)
{
}
for (ix in x11info)
{
if (x11info.length == 1 || x11info[ix].hwcap == "0")
}
if(!this.Location_X11FIXES)
{
var xfixesinfo = getLibInfo('libXfixes');
for (ix in xfixesinfo)
{
if (xfixesinfo.length == 1 || xfixesinfo[ix].hwcap == "0")
{
try
{
Object.defineProperty(this, 'Location_X11FIXES', { value: xfixesinfo[ix].path });
break;
}
catch (ex)
{
}
}
}
try
{
this._gm.CreateNativeProxy(x11info[ix].path);
Object.defineProperty(this, 'Location_X11LIB', { value: x11info[ix].path });
break;
if (process.env['Location_X11FIXES']) { Object.defineProperty(this, 'Location_X11FIXES', { value: process.env['Location_X11FIXES'] }); }
}
catch (ex)
catch(xx)
{
}
}
}
for (ix in xtstinfo)
{
if (xtstinfo.length == 1 || xtstinfo[ix].hwcap == "0")
{
try
{
this._gm.CreateNativeProxy(xtstinfo[ix].path);
Object.defineProperty(this, 'Location_X11TST', { value: xtstinfo[ix].path });
break;
}
catch (ex)
{
}
}
}
for (ix in xextinfo)
{
if (xextinfo.length == 1 || xextinfo[ix].hwcap == "0")
{
try
{
this._gm.CreateNativeProxy(xextinfo[ix].path);
Object.defineProperty(this, 'Location_X11EXT', { value: xextinfo[ix].path });
break;
}
catch (ex)
{
}
}
}
for (ix in xfixesinfo)
{
if (xfixesinfo.length == 1 || xfixesinfo[ix].hwcap == "0")
{
try
{
this._gm.CreateNativeProxy(xfixesinfo[ix].path);
Object.defineProperty(this, 'Location_X11FIXES', { value: xfixesinfo[ix].path });
break;
}
catch (ex)
{
}
}
}
try
{
if (process.env['Location_X11LIB']) { Object.defineProperty(this, 'Location_X11LIB', { value: process.env['Location_X11LIB'] }); }
if (process.env['Location_X11TST']) { Object.defineProperty(this, 'Location_X11TST', { value: process.env['Location_X11TST'] }); }
if (process.env['Location_X11EXT']) { Object.defineProperty(this, 'Location_X11EXT', { value: process.env['Location_X11EXT'] }); }
if (process.env['Location_X11FIXES']) { Object.defineProperty(this, 'Location_X11FIXES', { value: process.env['Location_X11FIXES'] }); }
}
catch(ex)
{
}
}
};
}
if(process.platform == 'freebsd')
{
Object.defineProperty(this, 'Location_X11LIB', { value: require('lib-finder')('libX11')[0]?require('lib-finder')('libX11')[0].location: undefined });
Object.defineProperty(this, 'Location_X11TST', { value: require('lib-finder')('libXtst')[0]?require('lib-finder')('libXtst')[0].location:undefined });
Object.defineProperty(this, 'Location_X11EXT', { value: require('lib-finder')('libXext')[0] ? require('lib-finder')('libXext')[0].location : undefined });
Object.defineProperty(this, 'Location_X11FIXES', { value: require('lib-finder')('libXfixes')[0] ? require('lib-finder')('libXfixes')[0].location : undefined });
this._check = function _check()
{
var lib;
if(!this.Location_X11LIB)
{
if ((lib = require('lib-finder')('libX11')[0])) { Object.defineProperty(this, 'Location_X11LIB', { value: lib.location }); }
}
if(!this.Location_X11TST)
{
if ((lib = require('lib-finder')('libXtst')[0])) { Object.defineProperty(this, 'Location_X11TST', { value: lib.location }); }
}
if (!this.Location_X11EXT)
{
if ((lib = require('lib-finder')('libXext')[0])) { Object.defineProperty(this, 'Location_X11EXT', { value: lib.location }); }
}
if (!this.Location_X11FIXES)
{
if ((lib = require('lib-finder')('libXfixes')[0])) { Object.defineProperty(this, 'Location_X11FIXES', { value: lib.location }); }
}
}
}
if(process.platform == 'linux' || process.platform == 'freebsd')
{
require('events').EventEmitter.call(this, true).createEvent('kvmSupportDetected');
this.kvm_x11_serverFound = false;
this.MOTIF_FLAGS =
{
MWM_FUNC_ALL : (1 << 0) ,
@@ -209,13 +254,64 @@ function monitorinfo()
MWM_FUNC_MAXIMIZE : (1 << 4) ,
MWM_FUNC_CLOSE : (1 << 5)
};
if (this.Location_X11LIB && this.Location_X11TST && this.Location_X11EXT)
this._xtries = 0;
this._kvmcheck = function _kvmcheck()
{
this._xtries = 0;
this._kvmCheck = function _kvmCheck()
var retry = false;
if (!(this.Location_X11LIB && this.Location_X11TST && this.Location_X11EXT))
{
this._check();
}
if (this.Location_X11LIB && this.Location_X11TST && this.Location_X11EXT)
{
if (!this._X11)
{
this._X11 = this._gm.CreateNativeProxy(this.Location_X11LIB);
this._X11.CreateMethod('XChangeProperty');
this._X11.CreateMethod('XChangeWindowAttributes');
this._X11.CreateMethod('XCloseDisplay');
this._X11.CreateMethod('XConnectionNumber');
this._X11.CreateMethod('XConvertSelection');
this._X11.CreateMethod('XCreateGC');
this._X11.CreateMethod('XCreateWindow');
this._X11.CreateMethod('XCreateSimpleWindow');
this._X11.CreateMethod('XDefaultColormap');
this._X11.CreateMethod('XDefaultScreen');
this._X11.CreateMethod('XDestroyWindow');
this._X11.CreateMethod('XDrawLine');
this._X11.CreateMethod('XDisplayHeight');
this._X11.CreateMethod('XDisplayWidth');
this._X11.CreateMethod('XFetchName');
this._X11.CreateMethod('XFlush');
this._X11.CreateMethod('XFree');
this._X11.CreateMethod('XCreateGC');
this._X11.CreateMethod('XGetAtomName');
this._X11.CreateMethod('XGetWindowProperty');
this._X11.CreateMethod('XInternAtom');
this._X11.CreateMethod('XMapWindow');
this._X11.CreateMethod({ method: 'XNextEvent', threadDispatch: true });
this._X11.CreateMethod({ method: 'XNextEvent', newName: 'XNextEventSync' });
this._X11.CreateMethod('XOpenDisplay');
this._X11.CreateMethod('XPending');
this._X11.CreateMethod('XRootWindow');
this._X11.CreateMethod('XSelectInput');
this._X11.CreateMethod('XScreenCount');
this._X11.CreateMethod('XScreenOfDisplay');
this._X11.CreateMethod('XSelectInput');
this._X11.CreateMethod('XSendEvent');
this._X11.CreateMethod('XSetForeground');
this._X11.CreateMethod('XSetFunction');
this._X11.CreateMethod('XSetLineAttributes');
this._X11.CreateMethod('XSetNormalHints');
this._X11.CreateMethod('XSetSelectionOwner');
this._X11.CreateMethod('XSetSubwindowMode');
this._X11.CreateMethod('XSetWMProtocols');
this._X11.CreateMethod('XStoreName');
this._X11.CreateMethod('XSync');
this._X11.CreateMethod('XBlackPixel');
this._X11.CreateMethod('XWhitePixel');
}
var ch = require('child_process').execFile('/bin/sh', ['sh']);
ch.stderr.on('data', function () { });
ch.stdout.str = ''; ch.stdout.on('data', function (c) { this.str += c.toString(); });
@@ -230,75 +326,27 @@ function monitorinfo()
}
else
{
if (this._xtries++ < 18)
{
this._xtry = setTimeout(function (that) { that._kvmCheck.call(that); }, 10000, this);
}
retry = true;
}
}
this._kvmCheck();
Object.defineProperty(this, 'kvm_x11_support', { get: function () { return (this.kvm_x11_serverFound); } });
this.on('newListener', function (name, handler)
else
{
if(name == 'kvmSupportDetected' && this.kvm_x11_serverFound)
{
handler.call(this, true);
}
});
}
else
retry = true;
}
if(retry && this._xtries++ < 18)
{
this._xtry = setTimeout(function (that) { that._kvmcheck.call(that); }, 10000, this);
}
};
this._kvmcheck();
Object.defineProperty(this, 'kvm_x11_support', { get: function () { return (this.kvm_x11_serverFound); } });
this.on('newListener', function (name, handler)
{
Object.defineProperty(this, 'kvm_x11_support', { value: false });
}
if (this.Location_X11LIB)
{
this._X11 = this._gm.CreateNativeProxy(this.Location_X11LIB);
this._X11.CreateMethod('XChangeProperty');
this._X11.CreateMethod('XChangeWindowAttributes');
this._X11.CreateMethod('XCloseDisplay');
this._X11.CreateMethod('XConnectionNumber');
this._X11.CreateMethod('XConvertSelection');
this._X11.CreateMethod('XCreateGC');
this._X11.CreateMethod('XCreateWindow');
this._X11.CreateMethod('XCreateSimpleWindow');
this._X11.CreateMethod('XDefaultColormap');
this._X11.CreateMethod('XDefaultScreen');
this._X11.CreateMethod('XDestroyWindow');
this._X11.CreateMethod('XDrawLine');
this._X11.CreateMethod('XDisplayHeight');
this._X11.CreateMethod('XDisplayWidth');
this._X11.CreateMethod('XFetchName');
this._X11.CreateMethod('XFlush');
this._X11.CreateMethod('XFree');
this._X11.CreateMethod('XCreateGC');
this._X11.CreateMethod('XGetAtomName');
this._X11.CreateMethod('XGetWindowProperty');
this._X11.CreateMethod('XInternAtom');
this._X11.CreateMethod('XMapWindow');
this._X11.CreateMethod({ method: 'XNextEvent', threadDispatch: true });
this._X11.CreateMethod({ method: 'XNextEvent', newName: 'XNextEventSync' });
this._X11.CreateMethod('XOpenDisplay');
this._X11.CreateMethod('XPending');
this._X11.CreateMethod('XRootWindow');
this._X11.CreateMethod('XSelectInput');
this._X11.CreateMethod('XScreenCount');
this._X11.CreateMethod('XScreenOfDisplay');
this._X11.CreateMethod('XSelectInput');
this._X11.CreateMethod('XSendEvent');
this._X11.CreateMethod('XSetForeground');
this._X11.CreateMethod('XSetFunction');
this._X11.CreateMethod('XSetLineAttributes');
this._X11.CreateMethod('XSetNormalHints');
this._X11.CreateMethod('XSetSelectionOwner');
this._X11.CreateMethod('XSetSubwindowMode');
this._X11.CreateMethod('XSetWMProtocols');
this._X11.CreateMethod('XStoreName');
this._X11.CreateMethod('XSync');
this._X11.CreateMethod('XBlackPixel');
this._X11.CreateMethod('XWhitePixel');
}
if (name == 'kvmSupportDetected' && this.kvm_x11_serverFound)
{
handler.call(this, true);
}
});
this.isUnity = function isUnity()
{
@@ -419,6 +467,21 @@ function monitorinfo()
return (ret);
}
function xinfo_xdm(info, uid)
{
if (process.platform != 'linux') { return(info); }
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = '';
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
child.stdin.write("ps -e -o uid -o cmd | grep X | grep " + uid + " | tr '\\n' '`' | awk '{ xl=split($2,x,\"/\"); print x[xl]; }'\nexit\n");
child.waitExit();
if(child.stdout.str.trim() != '')
{
if (info == null) { info = {}; }
info.xdm = child.stdout.str.trim().toLowerCase();
}
return (info);
}
this.getXInfo = function getXInfo(consoleuid)
{
var ret = null;
@@ -454,7 +517,7 @@ function monitorinfo()
if(e.XAUTHORITY && e.DISPLAY)
{
ret = { tty: '?', xauthority: e.XAUTHORITY, display: e.DISPLAY, exportEnv: exportEnv };
return (ret);
return (xinfo_xdm(ret, consoleuid));
}
}
}
@@ -470,7 +533,7 @@ function monitorinfo()
if (e.DISPLAY)
{
ret = { tty: '?', display: e.DISPLAY, exportEnv: exportEnv };
return (ret);
return (xinfo_xdm(ret, consoleuid));
}
}
}
@@ -508,7 +571,7 @@ function monitorinfo()
if (v[0] == 'DISPLAY')
{
ret.display = v[1];
return (ret);
return (xinfo_xdm(ret, consoleuid));
}
vs = psx + 1;
}
@@ -516,7 +579,7 @@ function monitorinfo()
}
}
}
return (ret);
return (xinfo_xdm(ret, consoleuid));
};
}
}

View File

@@ -33,7 +33,7 @@ function windows_notifybar_system(title, tsid)
{
var ret = {};
var script = Buffer.from("require('notifybar-desktop')('" + title + "').on('close', function(){process.exit();});").toString('base64');
var script = Buffer.from("require('notifybar-desktop')('" + title + "').on('close', function(){process._exit();});").toString('base64');
require('events').EventEmitter.call(ret, true)
.createEvent('close')
@@ -162,23 +162,63 @@ function windows_notifybar_local(title)
function x_notifybar_check(title)
{
if(require('user-sessions').Self()!=0 || require('user-sessions').consoleUid() == 0)
var script = Buffer.from("require('notifybar-desktop')('" + title + "').on('close', function(){process.exit();});").toString('base64');
var min = require('user-sessions').minUid();
var uid = require('user-sessions').consoleUid();
var self = require('user-sessions').Self();
if (self != 0 || uid == 0)
{
return (x_notifybar(title)); // No Dispatching necessary
}
else
{
// We are root, so we should try to spawn a child into the user's desktop
var uid = require('user-sessions').consoleUid();
if (uid < min && uid != 0)
{
// Lets hook login event, so we can respawn the bars later
var ret = { min: min };
require('events').EventEmitter.call(ret, true)
.createEvent('close')
.addMethod('close', function close()
{
require('user-sessions').removeListener('changed', this._changed);
this._close2();
});
ret._changed = function _changed()
{
var that = _changed.self;
var uid = require('user-sessions').consoleUid();
if (uid >= that.min)
{
that._close2 = function ()
{
this.child.kill();
};
var xinfo = require('monitor-info').getXInfo(uid);
that.child = require('child_process').execFile(process.execPath, [process.execPath.split('/').pop(), '-b64exec', script], { uid: uid, env: xinfo.exportEnv() });
that.child.parent = that;
that.child.stdout.on('data', function (c) { });
that.child.stderr.on('data', function (c) { });
that.child.on('exit', function (code) { this.parent.emit('close', code); });
}
};
ret._changed.self = ret;
require('user-sessions').on('changed', ret._changed);
ret._close2 = function _close2()
{
this.emit('close');
};
return (ret);
}
var xinfo = require('monitor-info').getXInfo(uid);
if (!xinfo)
{
throw('XServer Initialization Error')
}
var ret = {};
var script = Buffer.from("require('notifybar-desktop')('" + title + "').on('close', function(){process.exit();});").toString('base64');
require('events').EventEmitter.call(ret, true)
.createEvent('close')
.addMethod('close', function close() { this.child.kill(); });
@@ -272,10 +312,17 @@ function x_notifybar(title)
this.notifybar.monitors = m;
if (m.length > 0)
{
var ws = m[0].display.getCurrentWorkspace();
var ws = 0;
try
{
ws = m[0].display.getCurrentWorkspace();
this.notifybar.workspaces[ws] = true;
this.createBars(m);
}
catch(wex)
{
}
this.notifybar.workspaces[ws] = true;
this.createBars(m);
m[0].display._notifyBar = this.notifybar;
m[0].display.on('workspaceChanged', function (w)
{

View File

@@ -14,6 +14,96 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
function linux_getProxy()
{
// Check Environment Variabels
if(require('fs').existsSync('/etc/environment'))
{
var e = require('fs').readFileSync('/etc/environment').toString();
var tokens = e.split('\\n');
for(var line in tokens)
{
var val = tokens[line].split('=');
if(val.length == 2 && (val[0].trim() == 'http_proxy' || val[0].trim() == 'https_proxy'))
{
return(val[1].split('//')[1]);
}
}
}
// Check profile.d
if(require('fs').existsSync('/etc/profile.d/proxy_setup'))
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write("cat /etc/profile.d/proxy_setup | awk '" + '{ split($2, tok, "="); if(tok[1]=="http_proxy") { print tok[2]; }}\'\nexit\n');
child.waitExit();
child.ret = child.stdout.str.trim().split('\n')[0].split('//')[1];
if(child.ret != '') { return(child.ret); }
}
// Check gsettings
if (require('fs').existsSync('/usr/bin/gsettings'))
{
var setting;
var ids = require('user-sessions').loginUids();
for (var i in ids)
{
setting = require('linux-gnome-helpers').getProxySettings(ids[i]);
if (setting.mode == 'manual') { return(setting.host + ':' + setting.port);}
}
}
if (require('fs').existsSync('/etc/apt/apt.conf.d/proxy.conf'))
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.on('data', function (c) { console.log(c.toString()); });
child.stdin.write("cat /etc/apt/apt.conf.d/proxy.conf | tr '\\n' '`' | awk -F'`' '{");
child.stdin.write('for(n=1;n<NF;++n) { ln=split($n,tok,"::"); split(tok[ln],px,"\\""); split(px[2],x,"://"); if(x[2]!="") { print x[2]; break; } }');
child.stdin.write("}'\nexit\n");
child.waitExit();
if (child.stdout.str.trim() != "") { return (child.stdout.str.trim()); }
}
if (require('fs').existsSync('/etc/yum.conf'))
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.on('data', function (c) { console.log(c.toString()); });
child.stdin.write('cat /etc/yum.conf | grep "proxy=" | ' + "tr '\\n' '`' | awk -F'`' '{");
child.stdin.write('for(n=1;n<NF;++n) { cl=split($n,c,"#"); split($n,px,"://"); if(px[2]!="" && cl==1) { print px[2]; break; } }');
child.stdin.write("}'\nexit\n");
child.waitExit();
if (child.stdout.str.trim() != "") { return (child.stdout.str.trim()); }
}
if (require('fs').existsSync('/etc/sysconfig/proxy'))
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.on('data', function (c) { console.log(c.toString()); });
child.stdin.write('cat /etc/sysconfig/proxy | grep PROXY_ENABLED= | awk \'{');
child.stdin.write('split($0,res,"\\""); if(res[2]=="yes") { print res[2]; }')
child.stdin.write("}'\nexit\n");
child.waitExit();
if (child.stdout.str.trim() != "")
{
// Enabled
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.on('data', function (c) { console.log(c.toString()); });
child.stdin.write('cat /etc/sysconfig/proxy | grep _PROXY | ' + "tr '\\n' '`' | awk -F'`' '{");
child.stdin.write('for(i=1;i<NF;++i) { if(split($i,r,"HTTP_PROXY=")>1 || split($i,r,"HTTPS_PROXY=")>1) {');
child.stdin.write('cl=split($i,c,"#");');
child.stdin.write('split($i,px,"\\""); split(px[2],pxx,"://"); if(pxx[2]!="" && cl==1) { print pxx[2]; break; }');
child.stdin.write('} }');
child.stdin.write("}'\nexit\n");
child.waitExit();
if (child.stdout.str.trim() != '') { return (child.stdout.str.trim()); }
}
}
throw ('No proxies');
}
function posix_proxyCheck(uid, checkAddr)
{
var g;
@@ -104,7 +194,7 @@ switch (process.platform)
{
case 'linux':
case 'freebsd':
module.exports = { ignoreProxy: posix_proxyCheck };
module.exports = { ignoreProxy: posix_proxyCheck, getProxy: linux_getProxy };
break;
case 'win32':
module.exports = { ignoreProxy: windows_proxyCheck };

View File

@@ -54,6 +54,21 @@ function extractFileSource(filePath)
return (typeof (filePath) == 'string' ? filePath : filePath.source);
}
function perpareFolders(folderPath)
{
var dlmtr = process.platform == 'win32' ? '\\' : '/';
var tokens = folderPath.split(dlmtr);
var path = null;
while (tokens.length>0)
{
path = (path == null ? tokens.shift() : (path + dlmtr + tokens.shift()));
if (path.indexOf(process.platform == 'win32' ? '\\' : '/') < 0) { continue; }
if (!require('fs').existsSync(path)) { require('fs').mkdirSync(path); }
}
}
function parseServiceStatus(token)
{
var j = {};
@@ -580,7 +595,7 @@ function serviceManager()
blockSize += ((ptrSize - (blockSize % ptrSize)) % ptrSize);
var retVal = [];
for (var i = 0; i < servicesReturned.Deref(0, dbName._size).toBuffer().readUInt32LE(); ++i)
{
{
var token = services.Deref(i * blockSize, blockSize);
var j = {};
j.name = token.Deref(0, ptrSize).Deref().Wide2UTF8;
@@ -931,22 +946,22 @@ function serviceManager()
ret.appLocation = function appLocation()
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write("cat " + this.rc + " | grep command= | awk -F= '{ print $2 }' | awk -F\\\" '{ print $2 }'\nexit\n");
child.waitExit();
var tmp = child.stdout.str.trim().split('${name}').join(this.name);
if(tmp=='/usr/sbin/daemon')
{
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('cat ' + this.rc + ' | grep command_args= | awk -F"-f " \'{ $1=""; split($0, res, "\\""); split(res[1], t, " "); print t[1]; }\'\nexit\n');
child.waitExit();
return(child.stdout.str.trim());
}
else
{
var tmp = child.stdout.str.trim().split('${name}').join(this.name);
if(tmp=='/usr/sbin/daemon')
{
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('cat ' + this.rc + ' | grep command_args= | awk -F"-f " \'{ $1=""; split($0, res, "\\""); split(res[1], t, " "); print t[1]; }\'\nexit\n');
child.waitExit();
return(child.stdout.str.trim());
}
else
{
return(tmp);
}
}
};
ret.isRunning = function isRunning()
{
@@ -1552,6 +1567,9 @@ function serviceManager()
{
if (!options.target) { options.target = options.name; }
if (!options.displayName) { options.displayName = options.name; }
if (options.installPath) { if (!options.installPath.endsWith(process.platform == 'win32' ? '\\' : '/')) { options.installPath += (process.platform == 'win32' ? '\\' : '/'); } }
if (options.installPath && options.installInPlace) { throw ('Cannot specify both installPath and installInPlace'); }
if (process.platform != 'win32' && (options.installInPlace || options.installPath)) { throw ('Installation into non standard location is not supported on this platform'); }
if (process.platform == 'win32')
{
@@ -1559,12 +1577,24 @@ function serviceManager()
if (!this.isAdmin()) { throw ('Installing as Service, requires admin'); }
// Before we start, we need to copy the binary to the right place
var folder = this.getServiceFolder();
if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); }
if (!require('fs').existsSync(folder + '\\' + options.name)) { require('fs').mkdirSync(folder + '\\' + options.name); }
var folder = options.installPath == null ? this.getServiceFolder() : options.installPath;
if (folder.endsWith('\\')) { folder = folder.substring(0, folder.length - 1); }
if (!options.installInPlace) { perpareFolders(folder + '\\' + options.name); }
if (options.servicePath == process.execPath) { options._isMeshAgent = true; }
require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '\\' + options.target + '.exe');
options.servicePath = folder + '\\' + options.name + '\\' + options.target + '.exe';
if (!options.installInPlace)
{
require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '\\' + options.target + '.exe');
options.servicePath = folder + '\\' + options.name + '\\' + options.target + '.exe';
if (!options.installPath) { options.installPath = folder + '\\' + options.name + '\\'; }
}
else
{
options.servicePath = process.execPath;
options.installPath = process.execPath.split('\\');
options.installPath.pop();
options.installPath = options.installPath.join('\\') + '\\';
}
var servicePath = this.GM.CreateVariable('"' + options.servicePath + '"', { wide: true });
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
@@ -1631,19 +1661,16 @@ function serviceManager()
if (options.files[i]._buffer)
{
console.log('writing ' + extractFileName(options.files[i]));
require('fs').writeFileSync(folder + '\\' + options.name + '\\' + extractFileName(options.files[i]), options.files[i]._buffer);
require('fs').writeFileSync(options.installPath + extractFileName(options.files[i]), options.files[i]._buffer);
}
else
{
console.log('copying ' + extractFileSource(options.files[i]));
require('fs').copyFileSync(extractFileSource(options.files[i]), folder + '\\' + options.name + '\\' + extractFileName(options.files[i]));
require('fs').copyFileSync(extractFileSource(options.files[i]), options.installPath + extractFileName(options.files[i]));
}
}
}
if (options.parameters)
{
var imagePath = reg.QueryKey(reg.HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Services\\' + options.name, 'ImagePath');
@@ -1670,19 +1697,19 @@ function serviceManager()
try
{
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'DisplayName', options.displayName);
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'DisplayIcon', folder + '\\' + options.name + '\\' + options.target + '.exe');
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'DisplayIcon', options.servicePath);
if (options.publisher) { reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'Publisher', options.publisher); }
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'InstallLocation', folder + '\\' + options.name);
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'EstimatedSize', Math.floor(require('fs').statSync(folder + '\\' + options.name + '\\' + options.target + '.exe').size / 1024));
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'InstallLocation', options.installPath);
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')
{
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'UninstallString', folder + '\\' + options.name + '\\' + options.target + '.exe -funinstall');
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'UninstallString', options.servicePath + ' -funinstall');
}
else
{
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'UninstallString', folder + '\\' + options.name + '\\' + options.target + '.exe -b64exec ' + script);
reg.WriteKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\' + options.name, 'UninstallString', options.servicePath + ' -b64exec ' + script);
}
}
catch (xx)
@@ -2117,7 +2144,7 @@ function serviceManager()
}
catch (e)
{
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/C Y /N /D Y /T 2 & del "' + servicePath + '"'], { type: 4 });
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 });
}
if (this.proxy.DeleteService(service._service) == 0)
{

View File

@@ -24,6 +24,113 @@ function task()
{
this._ObjectID = 'task-scheduler';
if (process.platform == 'win32')
{
this.getTaskXml = function getTaskXml(name)
{
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\schtasks.exe', ['schtasks', '/QUERY', '/TN ' + name, '/XML']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
if (child.stderr.str.trim() != '') { throw ('Unable to fetch task: ' + name); }
return (child.stdout.str.trim());
}
this.getActionCommand = function getActionCommand(name, xml)
{
if (!xml)
{
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\schtasks.exe', ['schtasks', '/QUERY', '/TN ' + name, '/XML']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
if (child.stderr.str.trim() != '') { throw ('Unable to fetch task: ' + name); }
xml = child.stdout.str;
}
var xElement = xml.split('</Exec>')[0].split('<Exec>')[1];
var command = xElement.split('</Command>')[0].split('<Command>')[1];
return (command);
};
this.editActionCommand = function editActionCommand(name, action, argString, xml)
{
if (!xml)
{
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\schtasks.exe', ['schtasks', '/QUERY', '/TN ' + name, '/XML']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
if (child.stderr.str.trim() != '') { throw ('Unable to fetch task: ' + name); }
xml = child.stdout.str;
}
var pt1 = xml.split('</Exec>'); // xml = pt1.join('</Exec>');
var pt2 = pt1[0].split('<Exec>'); // pt1[0] = pt2.join('<Exec>');
var xElement = pt2[1]; // pt2[1] = xElement;
var pt3 = xElement.split('</Command>'); // xElement = pt3.join('</Command>');
var pt4 = pt3[0].split('<Command>'); // pt3[0] = pt4.join('<Command>');
var command = pt4[1]; // pt4[1] = command;
pt4[1] = action;
pt3[0] = pt4.join('<Command>');
xElement = pt3.join('</Command>');
var pt5 = xElement.split('</Arguments>'); // xElement = pt5.join('</Arguments>');
var pt6 = pt5[0].split('<Arguments>'); // pt5[0] = pt6.join('<Arguments>');
var arg = pt6[1]; // pt6[1] = arg;
arg = argString;
pt6[1] = arg;
pt5[0] = pt6.join('<Arguments>');
xElement = pt5.join('</Arguments>');
pt2[1] = xElement;
pt1[0] = pt2.join('<Exec>');
xml = pt1.join('</Exec>');
var s = require('fs').createWriteStream(require('os').tmpdir() + name + '.xml', { flags: 'wb' });
var b = Buffer.alloc(2);
b[0] = 0xFF;
b[1] = 0xFE;
s.write(b);
s.write(Buffer.from(xml).toString('utf16'));
s.end();
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['cmd']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('SCHTASKS /DELETE /TN ' + name + ' /F \n');
child.stdin.write('SCHTASKS /CREATE /TN ' + name + ' /XML ' + require('os').tmpdir() + name + '.xml\n');
child.stdin.write('erase ' + require('os').tmpdir() + name + '.xml\nexit\n');
child.waitExit();
//console.log(child.stdout.str.trim());
//console.log(child.stderr.str.trim());
};
this.advancedEditActionCommand = function advancedEditActionCommand(name, action, argString)
{
var child = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['powershell.exe']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('$Act1 = New-ScheduledTaskAction -Execute "' + action + '" -Argument "' + argString + '"\n');
child.stdin.write('Set-ScheduledTask "' + name + '" -Action $Act1\nexit\n');
child.waitExit();
console.log(child.stdout.str.trim());
};
Object.defineProperty(this, "advancedSupport", {
value: (function ()
{
var child = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['/C "Get-Module -ListAvailable -Name ScheduledTasks"']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
return (child.stdout.str.trim() != '');
})()
});
}
this.create = function create(options)
{
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });

View File

@@ -51,58 +51,54 @@ function Toaster()
{
case 'win32':
{
var id = require('user-sessions').getProcessOwnerName(process.pid).tsid;
var consoleUid = 0;
var cid;
retVal.options = { };
try
{
consoleUid = require('user-sessions').consoleUid();
retVal.options.uid = tsid == null ? require('user-sessions').consoleUid() : tsid;
if (retVal.options.uid == (cid = require('user-sessions').getProcessOwnerName(process.pid).tsid))
{
delete retVal.options.uid;
}
else
{
if(tsid != null && cid != 0)
{
retVal._rej('Insufficient permission to display toast as uid: ' + tsid);
return (retVal);
}
retVal.options.type = require('child_process').SpawnTypes.USER;
}
}
catch (e)
catch (ee)
{
retVal._rej('Cannot display user notification when a user is not logged in');
return (retVal);
}
if (id != 0)
retVal.child = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['powershell', '-noprofile', '-nologo', '-command', '-'], retVal.options);
retVal.child.toast = retVal;
retVal.child.stdout.stdin = retVal.child.stdin;
retVal.child.stderr.stdin = retVal.child.stdin;
retVal.child.stdout.on('data', function (c) { if (c.toString().includes('<DISMISSED>')) { this.stdin.write('exit\n'); } });
retVal.child.stderr.once('data', function (c) { this.stdin.write('$objBalloon.dispose();exit\n'); });
retVal.child.stdin.write('[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")\r\n');
retVal.child.stdin.write('$objBalloon = New-Object System.Windows.Forms.NotifyIcon\r\n');
retVal.child.stdin.write('$objBalloon.Icon = [System.Drawing.SystemIcons]::Information\r\n');
retVal.child.stdin.write('$objBalloon.Visible = $True\r\n');
retVal.child.stdin.write('Register-ObjectEvent -InputObject $objBalloon -EventName BalloonTipClosed -Action { $objBalloon.dispose();Write-Host "<`DISMISSED`>" }')
retVal.child.stdin.write('$objBalloon.ShowBalloonTip(10000,"' + title + '", "' + caption + '", 0)\r\n');
retVal.child.timeout = setTimeout(function (c)
{
// We are running as user
if(tsid != null && tsid != id)
{
// If we aren't LocalSystem, we cannot spawn as a different user
retVal._rej('Cannot display user notification to TSID: ' + tsid + ' from TSID: ' + id);
return (retVal);
}
retVal._child = require('ScriptContainer').Create({ processIsolation: true });
}
else
c.timeout = null;
c.stdin.write('$objBalloon.dispose();exit\n');
}, 10000, retVal.child);
retVal.child.on('exit', function ()
{
// We are running as LocalSystem
if (tsid == null) { tsid = consoleUid; }
retVal._child = require('ScriptContainer').Create({ processIsolation: true, sessionId: tsid });
}
retVal._child.parent = retVal;
retVal._child.on('exit', function (code) { this.parent._res('DISMISSED'); });
retVal._child.addModule('win-console', getJSModule('win-console'));
retVal._child.addModule('win-message-pump', getJSModule('win-message-pump'));
caption = caption.split("'").join("\\'");
title = title.split("'").join("\\'");
var str = "\
try{\
var toast = require('win-console');\
var balloon = toast.SetTrayIcon({ szInfo: '" + caption + "', szInfoTitle: '" + title + "', balloonOnly: true });\
balloon.on('ToastDismissed', function(){process.exit();});\
}\
catch(e)\
{\
require('ScriptContainer').send(e);\
}\
require('ScriptContainer').send('done');\
";
retVal._child.ExecuteString(str);
if (this.timeout != null) { clearTimeout(this.timeout); }
this.toast._res('DISMISSED');
});
return (retVal);
}
break;
@@ -232,6 +228,34 @@ function Toaster()
return (retVal);
};
if(process.platform == 'win32')
{
this._containerToast = function _containerToast(caption, title)
{
var toast;
var balloon;
try
{
toast = require('win-console');
balloon = toast.SetTrayIcon({ szInfo: caption, szInfoTitle: title, balloonOnly: true });
balloon.on('ToastDismissed', function () { process.exit(); });
}
catch(e)
{
process.exit();
}
try
{
require('child-container').message({ status: 'ok', pid: process.pid});
}
catch(ee)
{
process.exit();
}
var t = setTimeout(function (b) { b.remove(); process.exit(); }, 7000, balloon);
}
}
}
module.exports = new Toaster();

View File

@@ -410,6 +410,28 @@ function UserSessions()
}
else if(process.platform == 'linux' || process.platform == 'freebsd')
{
Object.defineProperty(this, "gdmUid", {
get: function ()
{
var ret = null;
var min = this.minUid();
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('getent passwd | grep "Gnome Display Manager" | ' + "tr '\\n' '`' | awk -F: '{ print $3 }'\nexit\n");
child.waitExit();
if (child.stdout.str.trim() != '' && (ret = parseInt(child.stdout.str.trim())) < min) { return (parseInt(child.stdout.str.trim())); }
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { console.log(c.toString()); });
child.stdin.write('getent passwd | grep gdm | ' + "tr '\\n' '`' | awk -F'`' '" + '{ for(i=1;i<NF;++i) { split($i, f, ":"); if(f[3]+0<' + min + '+0) { print f[3]; break; } } }' + "'\nexit\n");
child.waitExit();
if (child.stdout.str.trim() != '' && (ret = parseInt(child.stdout.str.trim())) < min) { return (parseInt(child.stdout.str.trim())); }
return (0);
}
});
this.getUid = function getUid(username)
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
@@ -605,22 +627,32 @@ function UserSessions()
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
child.stdin.write('who\nexit\n');
child.stdin.write("who | tr '\\n' '\`' | awk '{ print $1 }'\nexit\n");
child.waitExit();
if (child.stderr.str != '') { return (0); }
var lines = child.stdout.str.split('\n');
var tokens, i, j;
for (i in lines) {
tokens = lines[i].split(' ');
for (j = 1; j < tokens.length; ++j) {
if (tokens[j].length > 0) {
return (parseInt(this._users()[tokens[0]]));
}
if (child.stdout.str.trim() != '')
{
try
{
return (this.getUid(child.stdout.str.trim()));
}
catch (e)
{
}
}
throw ('nobody logged into console');
// Before we say nobody is logged on, let's check to see if there is a GDM session
var gdm = this.gdmUid;
var info = require('monitor-info').getXInfo(gdm);
if (info == null || !info.xauthority || !info.display)
{
throw ('nobody logged into console');
}
else
{
return (gdm);
}
}
this.getHomeFolder = function getHomeFolder(id)

View File

@@ -43,7 +43,6 @@ function dispatch(options)
{
}
}
var str = Buffer.from("require('win-console').hide();require('win-dispatcher').connect('" + ipcInteger + "');").toString('base64');
ret._ipc2.once('connection', function onConnect(s)
{
@@ -72,7 +71,6 @@ function dispatch(options)
s.write(h);
s.write(d);
}
d = Buffer.from(JSON.stringify({ command: 'launch', value: { module: this.parent.options.launch.module, method: this.parent.options.launch.method, args: this.parent.options.launch.args } }));
h.writeUInt32LE(d.length + 4);
s.write(h);
@@ -81,30 +79,33 @@ function dispatch(options)
this.parent.emit('connection', s);
});
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['cmd']);
child.stderr.on('data', function (c) { });
child.stdout.on('data', function (c) { });
var parms = '/C SCHTASKS /CREATE /F /TN MeshUserTask /SC ONCE /ST 00:00 ';
if (options.user)
{
child.stdin.write('SCHTASKS /CREATE /F /TN MeshUserTask /SC ONCE /ST 00:00 /RU ' + options.user + ' /TR "\\"' + process.execPath + '\\" -b64exec ' + str + '"\r\n');
// Specified User
parms += ('/RU ' + options.user + ' ');
}
else
{
if (require('user-sessions').getProcessOwnerName(process.pid).tsid == 0)
{
// LocalSystem
child.stdin.write('SCHTASKS /CREATE /F /TN MeshUserTask /SC ONCE /ST 00:00 /RU SYSTEM /TR "\\"' + process.execPath + '\\" -b64exec ' + str + '"\r\n');
}
else
{
// Running as logged in user
child.stdin.write('SCHTASKS /CREATE /F /TN MeshUserTask /SC ONCE /ST 00:00 /TR "\\"' + process.execPath + '\\" -b64exec ' + str + '"\r\n');
parms += ('/RU SYSTEM ');
}
}
parms += ('/TR "\\"' + process.execPath + '\\" -b64exec ' + str + '"');
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', [parms]);
child.stderr.on('data', function (c) { });
child.stdout.on('data', function (c) { });
child.waitExit();
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['cmd']);
child.stderr.on('data', function (c) { });
child.stdout.on('data', function (c) { });
child.stdin.write('SCHTASKS /RUN /TN MeshUserTask\r\n');
child.stdin.write('SCHTASKS /DELETE /F /TN MeshUserTask\r\n');
child.stdin.write('exit\r\n');
child.stdin.write('SCHTASKS /DELETE /F /TN MeshUserTask\r\nexit\r\n');
child.waitExit();
return (ret);
@@ -123,7 +124,6 @@ function connect(ipc)
this.unshift(c);
return;
}
var cmd = JSON.parse(c.slice(4, cLen).toString());
switch (cmd.command)
{
@@ -145,7 +145,6 @@ function connect(ipc)
this.unshift(c);
return;
}
var cmd = JSON.parse(c.slice(4, cLen).toString());
switch (cmd.command)
{