JNIEXPORT jlong JNICALL Java_io_jxcore_node_jxcore_callCBString(JNIEnv *env, jobject thiz, jstring ev_name, jstring param, jint json) { if (eventCB.type_ == 0) { error_console("event callback is not ready yet."); return 0; } const char *str_ev = env->GetStringUTFChars(ev_name, 0); const char *str_param = env->GetStringUTFChars(param, 0); long ret_val = 0; JXValue args[2]; if (JX_CreateEmptyObject(&args[1])) { JXValue jx_str_param; JX_New(&args[0]); JX_New(&jx_str_param); JX_SetString(&args[0], str_ev, 0); JX_SetString(&jx_str_param, str_param, 0); if (json != 1) JX_SetNamedProperty(&args[1], "str", &jx_str_param); else JX_SetNamedProperty(&args[1], "json", &jx_str_param); JX_Free(&jx_str_param); JXValue out; JX_CallFunction(&eventCB, args, 2, &out); JX_Free(&args[0]); JX_Free(&args[1]); if (!JX_IsNull(&out) && !JX_IsUndefined(&out)) ret_val = JX_StoreValue(&out); else ret_val = -1; } else { error_console("couldn't create JXValue Object"); } env->ReleaseStringUTFChars(ev_name, str_ev); env->ReleaseStringUTFChars(param, str_param); return ret_val; }
static void defineEventCB(JXValue *results, int argc) { if (!JX_IsFunction(results + 1)) { error_console("defineEventCB expects a function"); return; } JX_MakePersistent(results+1); eventCB = *(results + 1); }
static void callback(JXValue *results, int argc) { if (argc != 3) { error_console( "wrong callback received. expected number of parameters was 3. " "received %d", argc); return; } if (!JX_IsString(results + 2)) { error_console( "JXcore-Cordova: Unexpected callback received. Third parameter must " "be a String"); return; } cb_values = results; // results+1 -> err_val jxcore::Callback((JX_IsNull(results + 1) || JX_IsUndefined(results + 1)) ? 0 : 1); cb_values = NULL; }
JNIEXPORT jlong JNICALL Java_io_jxcore_node_jxcore_callCBArray(JNIEnv *env, jobject thiz, jstring ev_name, jobjectArray params, jint size) { if (eventCB.type_ == 0) { error_console("event callback is not ready yet."); return 0; } const char *str_ev = env->GetStringUTFChars(ev_name, 0); long ret_val = 0; JXValue args[2]; if (JX_CreateArrayObject(&args[1])) { JX_New(&args[0]); JX_SetString(&args[0], str_ev, 0); jclass boolClass = env->FindClass("java/lang/Boolean"); jclass doubleClass = env->FindClass("java/lang/Double"); jclass intClass = env->FindClass("java/lang/Integer"); jclass strClass = env->FindClass("java/lang/String"); jclass barrClass = env->FindClass("[B"); for (int i = 0; i < (int)size; i++) { jobject elm = (jobject)env->GetObjectArrayElement(params, i); JXValue val; JX_New(&val); if (elm == NULL) { JX_SetNull(&val); } else if (env->IsInstanceOf(elm, boolClass) == JNI_TRUE) { jmethodID bvalID = env->GetMethodID(boolClass, "booleanValue", "()Z"); bool nval = (bool)env->CallBooleanMethod(elm, bvalID); JX_SetBoolean(&val, nval); } else if (env->IsInstanceOf(elm, intClass) == JNI_TRUE) { jmethodID bvalID = env->GetMethodID(intClass, "intValue", "()I"); int nval = (int)env->CallIntMethod(elm, bvalID); JX_SetInt32(&val, nval); } else if (env->IsInstanceOf(elm, doubleClass) == JNI_TRUE) { jmethodID bvalID = env->GetMethodID(doubleClass, "doubleValue", "()D"); double nval = (double)env->CallDoubleMethod(elm, bvalID); JX_SetDouble(&val, nval); } else if (env->IsInstanceOf(elm, strClass) == JNI_TRUE) { jstring jstr = (jstring)elm; const char *str = env->GetStringUTFChars(jstr, 0); JX_SetString(&val, str, strlen(str)); env->ReleaseStringUTFChars(jstr, str); } else if (env->IsInstanceOf(elm, barrClass) == JNI_TRUE) { jbyteArray jarr = (jbyteArray)elm; int len = env->GetArrayLength(jarr); jbyte *barr = env->GetByteArrayElements(jarr, 0); JX_SetBuffer(&val, (char *)barr, len); env->ReleaseByteArrayElements(jarr, barr, JNI_ABORT); } JX_SetIndexedProperty(&args[1], i, &val); JX_Free(&val); env->DeleteLocalRef(elm); } env->DeleteLocalRef(boolClass); env->DeleteLocalRef(doubleClass); env->DeleteLocalRef(intClass); env->DeleteLocalRef(strClass); env->DeleteLocalRef(barrClass); JXValue out; JX_CallFunction(&eventCB, args, 2, &out); JX_Free(&args[0]); JX_Free(&args[1]); if (!JX_IsNull(&out) && !JX_IsUndefined(&out)) ret_val = JX_StoreValue(&out); else ret_val = -1; } else { error_console("couldn't create JXValue Object"); } env->ReleaseStringUTFChars(ev_name, str_ev); return ret_val; }
int uv_spawn_jx(uv_loop_t* loop, uv_process_t* process, uv_process_options_t* options) { #ifdef WINONECORE error_console("Error: WindowsOneCore does not support spawning a process.\n"); return -1; // not supported #else int i; uv_err_t err = uv_ok_; WCHAR* path = NULL; BOOL result; WCHAR* application_path = NULL, *application = NULL, *arguments = NULL, *env = NULL, *cwd = NULL; STARTUPINFOW startup; PROCESS_INFORMATION info; DWORD process_flags; if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) { uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } if (options->file == NULL || options->args == NULL) { uv__set_artificial_error(loop, UV_EINVAL); return -1; } assert(options->file != NULL); assert(!(options->flags & ~(UV_PROCESS_DETACHED | UV_PROCESS_SETGID | UV_PROCESS_SETUID | UV_PROCESS_WINDOWS_HIDE | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); uv_process_init(loop, process); process->exit_cb = options->exit_cb; err = uv_utf8_to_utf16_alloc(options->file, &application); if (err.code != UV_OK) goto done; err = make_program_args( options->args, options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS, &arguments); if (err.code != UV_OK) goto done; if (options->env) { err = make_program_env(options->env, &env); if (err.code != UV_OK) goto done; } if (options->cwd) { /* Explicit cwd */ err = uv_utf8_to_utf16_alloc(options->cwd, &cwd); if (err.code != UV_OK) goto done; } else { /* Inherit cwd */ DWORD cwd_len, r; cwd_len = GetCurrentDirectoryW(0, NULL); if (!cwd_len) { err = uv__new_sys_error(GetLastError()); goto done; } cwd = (WCHAR*)malloc(cwd_len * sizeof(WCHAR)); if (cwd == NULL) { err = uv__new_artificial_error(UV_ENOMEM); goto done; } r = GetCurrentDirectoryW(cwd_len, cwd); if (r == 0 || r >= cwd_len) { err = uv__new_sys_error(GetLastError()); goto done; } } /* Get PATH environment variable. */ { DWORD path_len, r; path_len = GetEnvironmentVariableW(L"PATH", NULL, 0); if (path_len == 0) { err = uv__new_sys_error(GetLastError()); goto done; } path = (WCHAR*)malloc(path_len * sizeof(WCHAR)); if (path == NULL) { err = uv__new_artificial_error(UV_ENOMEM); goto done; } r = GetEnvironmentVariableW(L"PATH", path, path_len); if (r == 0 || r >= path_len) { err = uv__new_sys_error(GetLastError()); goto done; } } application_path = search_path(application, cwd, path); if (application_path == NULL) { /* Not found. */ err = uv__new_artificial_error(UV_ENOENT); goto done; } err = uv__stdio_create(loop, options, &process->child_stdio_buffer); if (err.code != UV_OK) goto done; startup.cb = sizeof(startup); startup.lpReserved = NULL; startup.lpDesktop = NULL; startup.lpTitle = NULL; startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer); startup.lpReserved2 = (BYTE*)process->child_stdio_buffer; startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0); startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1); startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2); if (options->flags & UV_PROCESS_WINDOWS_HIDE) { /* Use SW_HIDE to avoid any potential process window. */ startup.wShowWindow = SW_HIDE; } else { startup.wShowWindow = SW_SHOWDEFAULT; } process_flags = CREATE_UNICODE_ENVIRONMENT; if (options->flags & UV_PROCESS_DETACHED) { /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That * means that libuv might not let you create a fully deamonized process * when run under job control. However the type of job control that libuv * itself creates doesn't trickle down to subprocesses so they can still * daemonize. * * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the * CreateProcess call fail if we're under job control that doesn't allow * breakaway. */ process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP; } if (CreateProcessW(application_path, arguments, NULL, NULL, 1, process_flags, env, cwd, &startup, &info)) { /* Spawn succeeded */ process->process_handle = info.hProcess; process->pid = info.dwProcessId; /* If the process isn't spawned as detached, assign to the global job */ /* object so windows will kill it when the parent process dies. */ if (!(options->flags & UV_PROCESS_DETACHED)) { uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle); if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) { /* AssignProcessToJobObject might fail if this process is under job * control and the job doesn't have the * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version * that doesn't support nested jobs. * * When that happens we just swallow the error and continue without * establishing a kill-child-on-parent-exit relationship, otherwise * there would be no way for libuv applications run under job control * to spawn processes at all. */ DWORD err = GetLastError(); if (err != ERROR_ACCESS_DENIED) uv_fatal_error(err, "AssignProcessToJobObject"); } } /* Set IPC pid to all IPC pipes. */ for (i = 0; i < options->stdio_count; i++) { const uv_stdio_container_t* fdopt = &options->stdio[i]; if (fdopt->flags & UV_CREATE_PIPE && fdopt->data.stream->type == UV_NAMED_PIPE && ((uv_pipe_t*)fdopt->data.stream)->ipc) { ((uv_pipe_t*)fdopt->data.stream)->ipc_pid = info.dwProcessId; } } /* Setup notifications for when the child process exits. */ result = RegisterWaitForSingleObject( &process->wait_handle, process->process_handle, exit_wait_callback, (void*)process, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); if (!result) { uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); } CloseHandle(info.hThread); } else { /* CreateProcessW failed. */ err = uv__new_sys_error(GetLastError()); } done: JX_FREE(process, application); JX_FREE(process, application_path); JX_FREE(process, arguments); JX_FREE(process, cwd); JX_FREE(process, env); JX_FREE(process, path); process->spawn_error = err; if (process->child_stdio_buffer != NULL) { /* Clean up child stdio handles. */ uv__stdio_destroy(process->child_stdio_buffer); process->child_stdio_buffer = NULL; } /* Make the handle active. It will remain active until the exit callback */ /* is made or the handle is closed, whichever happens first. */ uv__handle_start(process); /* If an error happened, queue the exit req. */ if (err.code != UV_OK) { process->exit_cb_pending = 1; uv_insert_pending_req(loop, (uv_req_t*)&process->exit_req); } return 0; #endif }