static switch_xml_t fetch_handler(const char *section, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params, void *user_data) { switch_xml_t xml = NULL; switch_uuid_t uuid; switch_time_t now = 0; ei_xml_agent_t *agent = (ei_xml_agent_t *) user_data; ei_xml_client_t *client; fetch_handler_t *fetch_handler; xml_fetch_reply_t reply, *pending, *prev = NULL; now = switch_micro_time_now(); if (!switch_test_flag(&globals, LFLAG_RUNNING)) { return xml; } /* read-lock the agent */ switch_thread_rwlock_rdlock(agent->lock); /* serialize access to current, used to round-robin requests */ /* TODO: check globals for round-robin boolean or loop all clients */ switch_mutex_lock(agent->current_client_mutex); if (!agent->current_client) { client = agent->clients; } else { client = agent->current_client; } if (client) { agent->current_client = client->next; } switch_mutex_unlock(agent->current_client_mutex); /* no client, no work required */ if (!client || !client->fetch_handlers) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "No %s XML erlang handler currently available\n" ,section); switch_thread_rwlock_unlock(agent->lock); return xml; } /* prepare the reply collector */ switch_uuid_get(&uuid); switch_uuid_format(reply.uuid_str, &uuid); reply.next = NULL; reply.xml_str = NULL; /* add our reply placeholder to the replies list */ switch_mutex_lock(agent->replies_mutex); if (!agent->replies) { agent->replies = &reply; } else { reply.next = agent->replies; agent->replies = &reply; } switch_mutex_unlock(agent->replies_mutex); fetch_handler = client->fetch_handlers; while (fetch_handler != NULL) { ei_send_msg_t *send_msg; switch_malloc(send_msg, sizeof(*send_msg)); memcpy(&send_msg->pid, &fetch_handler->pid, sizeof(erlang_pid)); ei_x_new_with_version(&send_msg->buf); ei_x_encode_tuple_header(&send_msg->buf, 7); ei_x_encode_atom(&send_msg->buf, "fetch"); ei_x_encode_atom(&send_msg->buf, section); _ei_x_encode_string(&send_msg->buf, tag_name ? tag_name : "undefined"); _ei_x_encode_string(&send_msg->buf, key_name ? key_name : "undefined"); _ei_x_encode_string(&send_msg->buf, key_value ? key_value : "undefined"); _ei_x_encode_string(&send_msg->buf, reply.uuid_str); if (params) { ei_encode_switch_event_headers(&send_msg->buf, params); } else { ei_x_encode_empty_list(&send_msg->buf); } if (switch_queue_trypush(client->ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send %s XML request to %s <%d.%d.%d>\n" ,section ,fetch_handler->pid.node ,fetch_handler->pid.creation ,fetch_handler->pid.num ,fetch_handler->pid.serial); ei_x_free(&send_msg->buf); switch_safe_free(send_msg); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending %s XML request (%s) to %s <%d.%d.%d>\n" ,section ,reply.uuid_str ,fetch_handler->pid.node ,fetch_handler->pid.creation ,fetch_handler->pid.num ,fetch_handler->pid.serial); } fetch_handler = fetch_handler->next; } /* wait for a reply (if there isnt already one...amazingly improbable but lets not take shortcuts */ switch_mutex_lock(agent->replies_mutex); switch_thread_rwlock_unlock(agent->lock); if (!reply.xml_str) { switch_time_t timeout; timeout = switch_micro_time_now() + 3000000; while (switch_micro_time_now() < timeout) { /* unlock the replies list and go to sleep, calculate a three second timeout before we started the loop * plus 100ms to add a little hysteresis between the timeout and the while loop */ switch_thread_cond_timedwait(agent->new_reply, agent->replies_mutex, (timeout - switch_micro_time_now() + 100000)); /* if we woke up (and therefore have locked replies again) check if we got our reply * otherwise we either timed-out (the while condition will fail) or one of * our sibling processes got a reply and we should go back to sleep */ if (reply.xml_str) { break; } } } /* find our reply placeholder in the linked list and remove it */ pending = agent->replies; while (pending != NULL) { if (pending->uuid_str == reply.uuid_str) { break; } prev = pending; pending = pending->next; } if (pending) { if (!prev) { agent->replies = reply.next; } else { prev->next = reply.next; } } /* we are done with the replies link-list */ switch_mutex_unlock(agent->replies_mutex); /* after all that did we get what we were after?! */ if (reply.xml_str) { /* HELL YA WE DID */ reply.xml_str = expand_vars(reply.xml_str); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received %s XML (%s) after %dms: %s\n" ,section ,reply.uuid_str ,(unsigned int) (switch_micro_time_now() - now) / 1000 ,reply.xml_str); xml = switch_xml_parse_str_dynamic(reply.xml_str, SWITCH_FALSE); } else { /* facepalm */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Request for %s XML (%s) timed-out after %dms\n" ,section ,reply.uuid_str ,(unsigned int) (switch_micro_time_now() - now) / 1000); } return xml; }
static void __execute_function( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags, char *args[], Bool has_ref_window_moved) { static int func_depth = 0; cond_rc_t *func_rc = NULL; cond_rc_t dummy_rc; Window w; int j; char *function; char *taction; char *trash; char *trash2; char *expaction = NULL; char *arguments[11]; const func_t *bif; Bool set_silent; Bool must_free_string = False; Bool must_free_function = False; Bool do_keep_rc = False; /* needed to be able to avoid resize to use moved windows for base */ extern Window PressedW; Window dummy_w; if (!action) { return; } /* ignore whitespace at the beginning of all config lines */ action = SkipSpaces(action, NULL, 0); if (!action || action[0] == 0) { /* impossibly short command */ return; } if (action[0] == '#') { /* a comment */ return; } func_depth++; if (func_depth > MAX_FUNCTION_DEPTH) { fvwm_msg( ERR, "__execute_function", "Function '%s' called with a depth of %i, " "stopping function execution!", action, func_depth); func_depth--; return; } if (args) { for (j = 0; j < 11; j++) { arguments[j] = args[j]; } } else { for (j = 0; j < 11; j++) { arguments[j] = NULL; } } if (exc->w.fw == NULL || IS_EWMH_DESKTOP(FW_W(exc->w.fw))) { if (exec_flags & FUNC_IS_UNMANAGED) { w = exc->w.w; } else { w = Scr.Root; } } else { FvwmWindow *tw; w = GetSubwindowFromEvent(dpy, exc->x.elast); if (w == None) { w = exc->x.elast->xany.window; } tw = NULL; if (w != None) { if (XFindContext( dpy, w, FvwmContext, (caddr_t *)&tw) == XCNOENT) { tw = NULL; } } if (w == None || tw != exc->w.fw) { w = FW_W(exc->w.fw); } } set_silent = False; if (action[0] == '-') { exec_flags |= FUNC_DONT_EXPAND_COMMAND; action++; } taction = action; /* parse prefixes */ trash = PeekToken(taction, &trash2); while (trash) { if (StrEquals(trash, PRE_SILENT)) { if (Scr.flags.are_functions_silent == 0) { set_silent = 1; Scr.flags.are_functions_silent = 1; } taction = trash2; trash = PeekToken(taction, &trash2); } else if (StrEquals(trash, PRE_KEEPRC)) { do_keep_rc = True; taction = trash2; trash = PeekToken(taction, &trash2); } else { break; } } if (taction == NULL) { if (set_silent) { Scr.flags.are_functions_silent = 0; } func_depth--; return; } if (cond_rc == NULL || do_keep_rc == True) { condrc_init(&dummy_rc); func_rc = &dummy_rc; } else { func_rc = cond_rc; } GetNextToken(taction, &function); if (function) { char *tmp = function; function = expand_vars( function, arguments, False, False, func_rc, exc); free(tmp); } if (function && function[0] != '*') { #if 1 /* DV: with this piece of code it is impossible to have a * complex function with embedded whitespace that begins with a * builtin function name, e.g. a function "echo hello". */ /* DV: ... and without it some of the complex functions will * fail */ char *tmp = function; while (*tmp && !isspace(*tmp)) { tmp++; } *tmp = 0; #endif bif = find_builtin_function(function); must_free_function = True; } else { bif = NULL; if (function) { free(function); } function = ""; } if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor && (!bif || !(bif->flags & FUNC_DECOR))) { fvwm_msg( ERR, "__execute_function", "Command can not be added to a decor; executing" " command now: '%s'", action); } if (!(exec_flags & FUNC_DONT_EXPAND_COMMAND)) { expaction = expand_vars( taction, arguments, (bif) ? !!(bif->flags & FUNC_ADD_TO) : False, (taction[0] == '*'), func_rc, exc); if (func_depth <= 1) { must_free_string = set_repeat_data( expaction, REPEAT_COMMAND, bif); } else { must_free_string = True; } } else { expaction = taction; } #ifdef FVWM_COMMAND_LOG fvwm_msg(INFO, "LOG", "%c: %s", (char)exc->type, expaction); #endif /* Note: the module config command, "*" can not be handled by the * regular command table because there is no required white space after * the asterisk. */ if (expaction[0] == '*') { if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor) { fvwm_msg( WARN, "__execute_function", "Command can not be added to a decor;" " executing command now: '%s'", expaction); } /* process a module config command */ ModuleConfig(expaction); } else { const exec_context_t *exc2; exec_context_changes_t ecc; exec_context_change_mask_t mask; mask = (w != exc->w.w) ? ECC_W : 0; ecc.w.fw = exc->w.fw; ecc.w.w = w; ecc.w.wcontext = exc->w.wcontext; if (bif && bif->func_t != F_FUNCTION) { char *runaction; Bool rc = False; runaction = SkipNTokens(expaction, 1); if ((bif->flags & FUNC_NEEDS_WINDOW) && !(exec_flags & FUNC_DONT_DEFER)) { rc = DeferExecution( &ecc, &mask, bif->cursor, exc->x.elast->type, (bif->flags & FUNC_ALLOW_UNMANAGED)); } else if ((bif->flags & FUNC_NEEDS_WINDOW) && !__context_has_window( exc, bif->flags & FUNC_ALLOW_UNMANAGED)) { /* no context window and not allowed to defer, * skip command */ rc = True; } if (rc == False) { exc2 = exc_clone_context(exc, &ecc, mask); if (has_ref_window_moved && (bif->func_t == F_ANIMATED_MOVE || bif->func_t == F_MOVE || bif->func_t == F_RESIZE || bif->func_t == F_RESIZEMOVE || bif->func_t == F_RESIZE_MAXIMIZE || bif->func_t == F_RESIZEMOVE_MAXIMIZE)) { dummy_w = PressedW; PressedW = None; bif->action(func_rc, exc2, runaction); PressedW = dummy_w; } else { bif->action(func_rc, exc2, runaction); } exc_destroy_context(exc2); } } else { Bool desperate = 1; char *runaction; if (bif) { /* strip "function" command */ runaction = SkipNTokens(expaction, 1); } else { runaction = expaction; } exc2 = exc_clone_context(exc, &ecc, mask); execute_complex_function( func_rc, exc2, runaction, &desperate, has_ref_window_moved); if (!bif && desperate) { if (executeModuleDesperate( func_rc, exc, runaction) == NULL && *function != 0 && !set_silent) { fvwm_msg( ERR, "__execute_function", "No such command '%s'", function); } } exc_destroy_context(exc2); } } if (set_silent) { Scr.flags.are_functions_silent = 0; } if (cond_rc != NULL) { cond_rc->break_levels = func_rc->break_levels; } if (must_free_string) { free(expaction); } if (must_free_function) { free(function); } func_depth--; return; }
static int parse_directive(ssi_buffer* ssib, char* str, int len) { assert(!str[len]); // zero-terminated char* p=str; char* pe=str+len; char* attr_name[SSI_MAX_ATTRS]; char* attr_value[SSI_MAX_ATTRS]; int num_attr=0; while ((unsigned char)*p<=SPACE && p<pe) p++; if (p>=pe) return -1; char* cmd=p; while ((unsigned char)*p>SPACE) p++; *p++='\0'; while (num_attr<SSI_MAX_ATTRS) { attr_name[num_attr]=p; p=strchr(p, '='); if (!p) break; *p++='\0'; attr_name[num_attr]=nxweb_trunc_space(attr_name[num_attr]); while ((unsigned char)*p<=SPACE && p<pe) p++; if (p>=pe) return -1; char q=*p++; if (q!='\"' && q!='\'') return -1; attr_value[num_attr]=p; p=strchr(p, q); if (!p) return -1; *p++='\0'; num_attr++; } if (!strcmp(cmd, "include")) { int i; for (i=0; i<num_attr; i++) { if (!strcmp(attr_name[i], "virtual")) { const char* expanded=expand_vars(ssib, attr_value[i]); if (!expanded) { nxweb_log_warning("ssi variables expansion failure: %s @ %s", attr_value[i], ssib->req->uri); return -1; } // nxweb_log_error("ssi variables expanded: %s -> %s", attr_value[i], expanded); nxweb_composite_stream_append_subrequest(ssib->cs, ssib->cs->req->host, expanded); return 0; } } } else if (!strcmp(cmd, "set")) { int i; const char* var_name=0; const char* var_value=0; nx_simple_map_entry* param; for (i=0; i<num_attr; i++) { if (!strcmp(attr_name[i], "var")) { var_name=attr_value[i]; } else if (!strcmp(attr_name[i], "value")) { var_value=expand_vars(ssib, attr_value[i]); if (!var_value) { nxweb_log_warning("ssi set variable expansion failure: %s @ %s", attr_value[i], ssib->req->uri); return -1; } // nxweb_log_error("ssi variables expanded: %s -> %s", attr_value[i], var_value); } } if (var_name && var_value) { param=nx_simple_map_find(ssib->var_map, var_name); if (!param) { param=nxb_calloc_obj(ssib->nxb, sizeof(nx_simple_map_entry)); ssib->var_map=nx_simple_map_add(ssib->var_map, param); param->name=var_name; } param->value=var_value; return 0; } } else if (!strcmp(cmd, "echo")) { int i; for (i=0; i<num_attr; i++) { if (!strcmp(attr_name[i], "var")) { const char* var_name=attr_value[i]; char expanded[SSI_MAX_EXPR_LEN]; char* end=expand_var(ssib, var_name, strlen(var_name), expanded, SSI_MAX_EXPR_LEN); if (!end) { // nxweb_log_warning("ssi echo variable expansion failure: %s @ %s", var_name, ssib->req->uri); return -1; } int len=end-expanded; char* buf=nxb_copy_obj(ssib->nxb, expanded, len); nxweb_composite_stream_append_bytes(ssib->cs, buf, len); return 0; } } } return -1; }
/* evaluate a simple command (3.9.1) * * this function doesn't put stuff in background, it always wait()s, so * it only needs to fork() real programs * ----------------------------------------------------------------------- */ int eval_simple_command(struct eval *e, struct ncmd *ncmd) { union node *nptr; int argc; char **argv; int status; union node *args = NULL; union node *assigns = NULL; union command cmd = { NULL }; enum hash_id id = H_BUILTIN; struct vartab vars; /* struct fdstack io;*/ union node *r; union node *redir = ncmd->rdir; /* expand arguments, if there are arguments we start a hashed search for the command */ if(expand_args(ncmd->args, &args, 0)) { stralloc_nul(&args->narg.stra); cmd = exec_hash(args->narg.stra.s, &id); } /* expand and set the variables, mark them for export if we're gonna execute a command */ if(expand_vars(ncmd->vars, &assigns)) { /* if we don't exit after the command, have a command and not a special builtin the variable changes should be temporary */ if(!(e->flags & E_EXIT) && cmd.ptr && id != H_SBUILTIN) vartab_push(&vars); for(nptr = assigns; nptr; nptr = nptr->list.next) var_setsa(&nptr->narg.stra, (cmd.ptr ? V_EXPORT : V_DEFAULT)); tree_free(assigns); } /* do redirections if present */ /* if(redir && id != H_SBUILTIN && id != H_EXEC) fdstack_push(&io);*/ if(redir/* && id != H_PROGRAM*/) { for(r = redir; r; r = r->list.next) { struct fd *fd = NULL; /* if its the exec special builtin the new fd needs to be persistent */ if(id != H_EXEC) fd_alloca(fd); /* return if a redirection failed */ if(redir_eval(&r->nredir, fd, (id == H_EXEC ? R_NOW : 0))) { status = 1; goto end; } /* check if we need to initialize fd buffers for the new redirection */ if(fd_needbuf(r->nredir.fd)) { /* if its not exec then set up buffers for temporary redirections on the stack */ if(id != H_EXEC) fd_setbuf(r->nredir.fd, alloca(FD_BUFSIZE), FD_BUFSIZE); else fd_allocbuf(r->nredir.fd, FD_BUFSIZE); } } } /* if there is no command we can return after setting the vars and doing the redirections */ if(args == NULL) { status = 0; goto end; } /* when the command wasn't found we abort */ if(cmd.ptr == NULL) { sh_error(args->narg.stra.s); status = exec_error(); goto end; } /* assemble argument list */ argc = tree_count(args); argv = alloca((argc + 1) * sizeof(char *)); expand_argv(args, argv); /* execute the command, this may or may not return, depending on E_EXIT */ status = exec_command(id, cmd, argc, argv, (e->flags & E_EXIT), redir); end: /* restore variable stack */ if(varstack == &vars) vartab_pop(&vars); if(args) tree_free(args); /* undo redirections */ if(id != H_EXEC) { for(r = redir; r; r = r->list.next) fd_pop(r->nredir.fd); } /* if(fdstack == &io) fdstack_pop(&io);*/ return status; }
/* Runs a handler process specified by full command line <data> (with arguments). * Before running: * Replaces environment variables. * Replaces special MimeRun variables (see above) with the detected values taken from <mres>. * Replaces %* and %N with the appropriate bits of <lpfile> and <einfo>->lpParameters. * If <executable> is TRUE, waits until the handler process terminates, otherwise returns * (almost) immediately. */ int run_handler (wchar_t *logfile, wchar_t *data, MimeResults *mres, LPSHELLEXECUTEINFOW einfo, wchar_t *lpfile, wchar_t *lpdir, int executable, int fix_redir) { BOOL ret = 0; PVOID redir; HMODULE kernel32 = NULL; Wow64DisableWow64FsRedirectionFunction disablewow64 = NULL; Wow64RevertWow64FsRedirectionFunction revertwow64 = NULL; DWORD err; int i; int depth = 0; size_t dupdatalen; wchar_t *exp_data = NULL; wchar_t *dupdata = NULL; wchar_t *dupparams = NULL; wchar_t **old_argv = NULL, **newargv = NULL; STARTUPINFOW si; PROCESS_INFORMATION pi; DWORD applelen, typelen, enclen, namelen; wchar_t *store_apple = NULL, *store_type = NULL, *store_enc = NULL, *store_name = NULL; logtofilew (logfile, L">run_handler\n"); if (einfo->lpParameters != NULL) { i = wcslen (einfo->lpParameters) + 1 + wcslen (lpfile); logtofilew (logfile, L"Fake commandline length is %d + 1 + %d == %d\n", wcslen (einfo->lpParameters), wcslen (lpfile), i); dupparams = (wchar_t *) malloc (sizeof (wchar_t *) * (i + 1)); if (dupparams == NULL) { logtofilew (logfile, L"Failed to allocate %d bytes\n", sizeof (wchar_t *) * (i + 1)); return 1; } dupparams[0] = L'\0'; wcscat (dupparams, lpfile); wcscat (dupparams, L" "); wcscat (dupparams, einfo->lpParameters); logtofilew (logfile, L"Fake commandline is %s\n", dupparams); if (make_argv (dupparams, &i, NULL) == 0 && i >= 1) { old_argv = (wchar_t **) malloc (sizeof (wchar_t *) * (i + 1)); make_argv (dupparams, NULL, old_argv); old_argv[i] = NULL; logtofilew (logfile, L"Old arguments:\n"); for (i = 0; old_argv[i] != NULL; i++) logtofilew (logfile, L"%2d: %s\n", i, old_argv[i]); logtofilew (logfile, L"\n"); } else { logtofilew (logfile, L"First call to make_argv() have failed or argc <= 0\n"); free (dupparams); return 2; } } else { old_argv = (wchar_t **) malloc (sizeof (wchar_t *) * 2); old_argv[0] = lpfile; old_argv[1] = NULL; logtofilew (logfile, L"Old arguments:\n"); for (i = 0; old_argv[i] != NULL; i++) logtofilew (logfile, L"%2d: %s\n", i, old_argv[i]); logtofilew (logfile, L"\n"); } store_name = store_var (NAME_VARW, &namelen); store_type = store_var (TYPE_VARW, &typelen); store_enc = store_var (ENC_VARW, &enclen); store_apple = store_var (APPLE_VARW, &applelen); logtofilew (logfile, L"Backed up variables: {%s}, {%s}, {%s}, {%s}\n", store_name, store_type, store_enc, store_apple); SetEnvironmentVariableW (NAME_VARW, mres->wname == NULL ? L"" : mres->wname); SetEnvironmentVariableW (TYPE_VARW, mres->wtype == NULL ? L"" : mres->wtype); SetEnvironmentVariableW (ENC_VARW, mres->wenc == NULL ? L"" : mres->wenc); SetEnvironmentVariableW (APPLE_VARW, mres->wapple == NULL ? L"" : mres->wapple); exp_data = expand_vars (data, old_argv); logtofilew (logfile, L"Commandline with expanded variables: %s\n", exp_data); if (dupparams != NULL) free (dupparams); if (old_argv != NULL) free (old_argv); SetEnvironmentVariableW (NAME_VARW, store_name); SetEnvironmentVariableW (TYPE_VARW, store_type); SetEnvironmentVariableW (ENC_VARW, store_enc); SetEnvironmentVariableW (APPLE_VARW, store_apple); if (store_apple != NULL) free (store_apple); if (store_type != NULL) free (store_type); if (store_enc != NULL) free (store_enc); if (store_name != NULL) free (store_name); dupdata = (wchar_t *) wcsdup (exp_data); if (make_argv (dupdata, &i, NULL) == 0 && i >= 1) { newargv = (wchar_t **) malloc (sizeof (wchar_t *) * (i + 1)); make_argv (dupdata, NULL, newargv); newargv[i] = NULL; } else { logtofilew (logfile, L"First call to make_argv() have failed or argc <= 0\n"); free (dupdata); return 3; } memset (&si, 0, sizeof (si)); si.cb = sizeof (si); if (einfo->nShow != SW_SHOWDEFAULT) { si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = einfo->nShow; logtofilew (logfile, L"Using nShow == %d\n", si.wShowWindow); } if (einfo->fMask & SEE_MASK_NO_CONSOLE) { logtofilew (logfile, L"We will create new console and will not inherit in/out/err handles\n"); } else { logtofilew (logfile, L"We will not create new console, child process will inherit in/out/err handles\n"); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle (STD_INPUT_HANDLE); si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); si.hStdError = GetStdHandle (STD_ERROR_HANDLE); } if (fix_redir && iam32on64 ()) { kernel32 = LoadLibraryW (L"kernel32.dll"); if (kernel32 != NULL) { disablewow64 = (Wow64DisableWow64FsRedirectionFunction) GetProcAddress (kernel32, "Wow64DisableWow64FsRedirection"); revertwow64 = (Wow64RevertWow64FsRedirectionFunction) GetProcAddress (kernel32, "Wow64RevertWow64FsRedirection"); if (disablewow64 == NULL || revertwow64 == NULL) fix_redir = 0; else fix_redir = disablewow64 (&redir); } else fix_redir = 0; } else fix_redir = 0; ret = CreateProcessW (newargv[0], exp_data, NULL, NULL, TRUE, einfo->fMask & SEE_MASK_NO_CONSOLE ? CREATE_NEW_CONSOLE : 0, NULL, lpdir, &si, &pi); err = GetLastError(); if (fix_redir != 0) revertwow64 (redir); if (kernel32 != NULL) FreeLibrary (kernel32); if (ret != 0) { logtofilew (logfile, L"CreateProcessW() succeeded\n"); ret = 0; if (executable) { logtofilew (logfile, L"Waiting until executable process terminates...\n"); WaitForSingleObject (pi.hProcess, INFINITE); logtofilew (logfile, L"Finished waiting until executable process terminates\n"); } else { if (einfo->fMask & SEE_MASK_NOCLOSEPROCESS) { einfo->hProcess = pi.hProcess; logtofilew (logfile, L"Will return process handle %08X\n", pi.hProcess); } if (einfo->fMask & SEE_MASK_WAITFORINPUTIDLE) { logtofilew (logfile, L"Waiting until non-executable process' input idles...\n"); WaitForInputIdle (pi.hProcess, 60*1000); logtofilew (logfile, L"Finished waiting until non-executable process' input idles\n"); } } einfo->hInstApp = (HINSTANCE) 33; } else { logtofilew (logfile, L"CreateProcessW() have failed with %d\n", err); switch (err) { case ERROR_FILE_NOT_FOUND: einfo->hInstApp = (HINSTANCE) SE_ERR_FNF; break; case ERROR_PATH_NOT_FOUND: einfo->hInstApp = (HINSTANCE) SE_ERR_PNF; break; case ERROR_ACCESS_DENIED: einfo->hInstApp = (HINSTANCE) SE_ERR_ACCESSDENIED; break; case ERROR_NOT_ENOUGH_MEMORY: einfo->hInstApp = (HINSTANCE) SE_ERR_OOM; break; default: einfo->hInstApp = (HINSTANCE) 33; } ret = 1; } logtofilew (logfile, L"hInstApp is set to %d\n", einfo->hInstApp); free (exp_data); if (dupdata != NULL) free (dupdata); if (newargv != NULL) free (newargv); logtofilew (logfile, L"<run_handler %d\n", ret); return ret; }