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:
10
makefile
10
makefile
@@ -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
|
||||
#
|
||||
#
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(¤tTime);
|
||||
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(¤tTime, &(((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(¤tTime);
|
||||
memcpy_s(&expirationTime, sizeof(struct timeval), ¤tTime, 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, ¤tTime)) { 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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
242
modules/child-container.js
Normal 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();
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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; });
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user