From 47a7b507a7f0d4febf94d58368572b4db644856d Mon Sep 17 00:00:00 2001 From: Dimitar Zhekov Date: Mon, 30 Mar 2015 20:33:55 +0300 Subject: [PATCH] Remove the unneeded win32_spawn() and win32_get_exit_status() These are not part of the plugin interface, and are not used in Geany any more after the spawn changes. --- src/win32.c | 493 ---------------------------------------------------- src/win32.h | 5 - 2 files changed, 498 deletions(-) diff --git a/src/win32.c b/src/win32.c index 834dfd3b43..1f28e67886 100644 --- a/src/win32.c +++ b/src/win32.c @@ -57,31 +57,6 @@ #include #include -#define BUFSIZE 4096 -#define CMDSIZE 32768 - -struct _geany_win32_spawn -{ - HANDLE hChildStdinRd; - HANDLE hChildStdinWr; - HANDLE hChildStdoutRd; - HANDLE hChildStdoutWr; - HANDLE hChildStderrRd; - HANDLE hChildStderrWr; - HANDLE hInputFile; - HANDLE hStdout; - HANDLE hStderr; - HANDLE processId; - DWORD dwExitCode; -}; -typedef struct _geany_win32_spawn geany_win32_spawn; - -static gboolean GetContentFromHandle(HANDLE hFile, gchar **content, GError **error); -static HANDLE GetTempFileHandle(GError **error); -static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, - const TCHAR *dir, GError **error); -static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile, GError **error); - /* The timer handle used to refresh windows below modal native dialogs. If * ever more than one dialog can be shown at a time, this needs to be changed @@ -837,17 +812,6 @@ void win32_open_browser(const gchar *uri) } -/* Returns TRUE if the command, which child_pid refers to, returned with a successful exit code, - * otherwise FALSE. */ -gboolean win32_get_exit_status(GPid child_pid) -{ - DWORD exit_code; - GetExitCodeProcess(child_pid, &exit_code); - - return (exit_code == 0); -} - - static FILE *open_std_handle(DWORD handle, const char *mode) { HANDLE lStdHandle; @@ -929,299 +893,7 @@ void win32_init_debug_code(void) /* create a console window to get log messages on Windows, * especially useful when generating tags files */ debug_setup_console(); - /* Enable GLib process spawn debug mode when Geany was started with the debug flag */ - g_setenv("G_SPAWN_WIN32_DEBUG", "1", FALSE); - } -} - - -static gchar *create_temp_file(void) -{ - gchar *name; - gint fd; - - fd = g_file_open_tmp("tmp_XXXXXX", &name, NULL); - if (fd == -1) - name = NULL; - else - close(fd); - - return name; -} - - -/* Sometimes this blocks for 30s before aborting when there are several - * pages of (error) output and sometimes hangs - see the FIXME. - * Also gw_spawn.dwExitCode seems to be not set properly. */ -/* Process spawning implementation for Windows, by Pierre Joye. - * Don't call this function directly, use utils_spawn_[a]sync() instead. */ -static -gboolean _broken_win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags, - gchar **std_out, gchar **std_err, gint *exit_status, GError **error) -{ - TCHAR buffer[CMDSIZE]=TEXT(""); - TCHAR cmdline[CMDSIZE] = TEXT(""); - TCHAR* lpPart[CMDSIZE]={NULL}; - DWORD retval = 0; - gint argc = 0, i; - gint cmdpos = 0; - - SECURITY_ATTRIBUTES saAttr; - BOOL fSuccess; - geany_win32_spawn gw_spawn; - - /* Temp file */ - HANDLE hStdoutTempFile = NULL; - HANDLE hStderrTempFile = NULL; - - gchar *stdout_content = NULL; - gchar *stderr_content = NULL; - - while (argv[argc]) - { - ++argc; - } - g_return_val_if_fail (std_out == NULL || - !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE); - g_return_val_if_fail (std_err == NULL || - !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE); - - if (flags & G_SPAWN_SEARCH_PATH) - { - retval = SearchPath(NULL, argv[0], ".exe", sizeof(buffer), buffer, lpPart); - if (retval > 0) - g_snprintf(cmdline, sizeof(cmdline), "\"%s\"", buffer); - else - g_strlcpy(cmdline, argv[0], sizeof(cmdline)); - cmdpos = 1; - } - - for (i = cmdpos; i < argc; i++) - { - g_snprintf(cmdline, sizeof(cmdline), "%s %s", cmdline, argv[i]); - /*MessageBox(NULL, cmdline, cmdline, MB_OK);*/ - } - - if (std_err != NULL) - { - hStderrTempFile = GetTempFileHandle(error); - if (hStderrTempFile == INVALID_HANDLE_VALUE) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("win32_spawn: Second CreateFile failed (%d)", (gint) GetLastError()); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg); - g_free(msg); - return FALSE; - } - } - - if (std_out != NULL) - { - hStdoutTempFile = GetTempFileHandle(error); - if (hStdoutTempFile == INVALID_HANDLE_VALUE) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("win32_spawn: Second CreateFile failed (%d)", (gint) GetLastError()); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg); - g_free(msg); - return FALSE; - } - } - - /* Set the bInheritHandle flag so pipe handles are inherited. */ - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; - - /* Get the handle to the current STDOUT and STDERR. */ - gw_spawn.hStdout = GetStdHandle(STD_OUTPUT_HANDLE); - gw_spawn.hStderr = GetStdHandle(STD_ERROR_HANDLE); - gw_spawn.dwExitCode = 0; - - /* Create a pipe for the child process's STDOUT. */ - if (! CreatePipe(&(gw_spawn.hChildStdoutRd), &(gw_spawn.hChildStdoutWr), &saAttr, 0)) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("win32_spawn: Stdout pipe creation failed (%d)", (gint) GetLastError()); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_PIPE, "%s", msg); - g_free(msg); - return FALSE; - } - - /* Ensure that the read handle to the child process's pipe for STDOUT is not inherited.*/ - SetHandleInformation(gw_spawn.hChildStdoutRd, HANDLE_FLAG_INHERIT, 0); - - /* Create a pipe for the child process's STDERR. */ - if (! CreatePipe(&(gw_spawn.hChildStderrRd), &(gw_spawn.hChildStderrWr), &saAttr, 0)) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("win32_spawn: Stderr pipe creation failed"); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_PIPE, "%s", msg); - g_free(msg); - return FALSE; - } - - /* Ensure that the read handle to the child process's pipe for STDOUT is not inherited.*/ - SetHandleInformation(gw_spawn.hChildStderrRd, HANDLE_FLAG_INHERIT, 0); - - /* Create a pipe for the child process's STDIN. */ - if (! CreatePipe(&(gw_spawn.hChildStdinRd), &(gw_spawn.hChildStdinWr), &saAttr, 0)) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("win32_spawn: Stdin pipe creation failed"); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_PIPE, "%s", msg); - g_free(msg); - return FALSE; - } - - /* Ensure that the write handle to the child process's pipe for STDIN is not inherited. */ - SetHandleInformation(gw_spawn.hChildStdinWr, HANDLE_FLAG_INHERIT, 0); - - /* Now create the child process. */ - fSuccess = CreateChildProcess(&gw_spawn, cmdline, dir, error); - if (exit_status) - { - *exit_status = gw_spawn.dwExitCode; - } - - if (! fSuccess) - { - geany_debug("win32_spawn: Create process failed"); - return FALSE; - } - - /* Read from pipe that is the standard output for child process. */ - if (std_out != NULL) - { - ReadFromPipe(gw_spawn.hChildStdoutRd, gw_spawn.hChildStdoutWr, hStdoutTempFile, error); - if (! GetContentFromHandle(hStdoutTempFile, &stdout_content, error)) - { - return FALSE; - } - *std_out = stdout_content; - } - - if (std_err != NULL) - { - ReadFromPipe(gw_spawn.hChildStderrRd, gw_spawn.hChildStderrWr, hStderrTempFile, error); - if (! GetContentFromHandle(hStderrTempFile, &stderr_content, error)) - { - return FALSE; - } - *std_err = stderr_content; - } - return TRUE; -} - - -/* Note: g_spawn is broken for receiving both stdio and stderr e.g. when - * running make and there are compile errors. See glib/giowin32.c header - * comment about Windows bugs, e.g. #338943 */ -/* Simple replacement for _broken_win32_spawn(). - * flags is ignored, G_SPAWN_SEARCH_PATH is implied. - * Don't call this function directly, use utils_spawn_[a]sync() instead. - * Adapted from tm_workspace_create_global_tags(). */ -gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags, - gchar **std_out, gchar **std_err, gint *exit_status, GError **error) -{ - gint ret; - gboolean fail; - gchar *tmp_file = create_temp_file(); - gchar *tmp_errfile = create_temp_file(); - gchar *command; - gchar *locale_command; - - if (env != NULL) - { - return _broken_win32_spawn(dir, argv, env, flags, std_out, std_err, - exit_status, error); - } - if (!tmp_file || !tmp_errfile) - { - g_warning("%s: Could not create temporary files!", G_STRFUNC); - return FALSE; - } - command = g_strjoinv(" ", argv); - SETPTR(command, g_strdup_printf("cmd.exe /S /C \"%s >%s 2>%s\"", - command, tmp_file, tmp_errfile)); - locale_command = g_locale_from_utf8(command, -1, NULL, NULL, NULL); - if (! locale_command) - locale_command = g_strdup(command); - geany_debug("WIN32: actually running command:\n%s", command); - g_chdir(dir); - errno = 0; - ret = system(locale_command); - /* the command can return -1 as an exit code, so check errno also */ - fail = ret == -1 && errno; - if (!fail) - { - if (std_out != NULL) - g_file_get_contents(tmp_file, std_out, NULL, NULL); - if (std_err != NULL) - g_file_get_contents(tmp_errfile, std_err, NULL, NULL); - } - else if (error) - g_set_error_literal(error, G_SPAWN_ERROR, errno, g_strerror(errno)); - - g_free(command); - g_free(locale_command); - g_unlink(tmp_file); - g_free(tmp_file); - g_unlink(tmp_errfile); - g_free(tmp_errfile); - if (exit_status) - *exit_status = ret; - - return !fail; -} - - -static gboolean GetContentFromHandle(HANDLE hFile, gchar **content, GError **error) -{ - DWORD filesize; - gchar * buffer; - DWORD dwRead; - - filesize = GetFileSize(hFile, NULL); - if (filesize < 1) - { - *content = NULL; - return TRUE; - } - - buffer = g_malloc(filesize + 1); - if (! buffer) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("GetContentFromHandle: Alloc failed"); - g_set_error(error, G_SPAWN_ERROR, G_SPAWN_ERROR, "%s", msg); - g_free(msg); - return FALSE; - } - - SetFilePointer(hFile, 0, NULL, FILE_BEGIN); - if (! ReadFile(hFile, buffer, filesize, &dwRead, NULL) || dwRead == 0) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("GetContentFromHandle: Cannot read tempfile"); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_FAILED, "%s", msg); - g_free(msg); - return FALSE; - } - - if (! CloseHandle(hFile)) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("GetContentFromHandle: CloseHandle failed (%d)", (gint) GetLastError()); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_FAILED, "%s", msg); - g_free(msg); - g_free(buffer); - *content = NULL; - return FALSE; } - buffer[filesize] = '\0'; - *content = buffer; - return TRUE; } @@ -1236,171 +908,6 @@ gchar *win32_expand_environment_variables(const gchar *str) } -static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, - const TCHAR *dir, GError **error) -{ - PROCESS_INFORMATION piProcInfo; - STARTUPINFOW siStartInfo; - BOOL bFuncRetn = FALSE; - gchar *expandedCmdline; - wchar_t w_commandline[CMDSIZE]; - wchar_t w_dir[MAX_PATH]; - - /* Set up members of the PROCESS_INFORMATION structure. */ - ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); - - /* Set up members of the STARTUPINFO structure.*/ - ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); - - siStartInfo.cb = sizeof(STARTUPINFO); - siStartInfo.hStdError = gw_spawn->hChildStderrWr; - siStartInfo.hStdOutput = gw_spawn->hChildStdoutWr; - siStartInfo.hStdInput = gw_spawn->hChildStdinRd; - siStartInfo.dwFlags |= STARTF_USESTDHANDLES; - - /* Expand environment variables like %blah%. */ - expandedCmdline = win32_expand_environment_variables(szCmdline); - - MultiByteToWideChar(CP_UTF8, 0, expandedCmdline, -1, w_commandline, G_N_ELEMENTS(w_commandline)); - MultiByteToWideChar(CP_UTF8, 0, dir, -1, w_dir, G_N_ELEMENTS(w_dir)); - - /* Create the child process. */ - bFuncRetn = CreateProcessW(NULL, - w_commandline, /* command line */ - NULL, /* process security attributes */ - NULL, /* primary thread security attributes */ - TRUE, /* handles are inherited */ - CREATE_NO_WINDOW, /* creation flags */ - NULL, /* use parent's environment */ - w_dir, /* use parent's current directory */ - &siStartInfo, /* STARTUPINFO pointer */ - &piProcInfo); /* receives PROCESS_INFORMATION */ - - g_free(expandedCmdline); - - if (bFuncRetn == 0) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("CreateChildProcess: CreateProcess failed (%s)", msg); - g_set_error(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, "%s", msg); - g_free(msg); - return FALSE; - } - else - { - gint i; - gsize ms = 30*1000; - - /* FIXME: this seems to timeout when there are many lines - * to read - maybe because the child's pipe is full */ - for (i = 0; i < 2 && - WaitForSingleObject(piProcInfo.hProcess, ms) == WAIT_TIMEOUT; i++) - { - ui_set_statusbar(FALSE, _("Process timed out after %.02f s!"), ms / 1000.0F); - geany_debug("CreateChildProcess: timed out"); - TerminateProcess(piProcInfo.hProcess, WAIT_TIMEOUT); /* NOTE: This will not kill grandkids. */ - } - - if (!GetExitCodeProcess(piProcInfo.hProcess, &gw_spawn->dwExitCode)) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("GetExitCodeProcess failed: %s", msg); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_FAILED, "%s", msg); - g_free(msg); - } - CloseHandle(piProcInfo.hProcess); - CloseHandle(piProcInfo.hThread); - return bFuncRetn; - } - return FALSE; -} - - -static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile, GError **error) -{ - DWORD dwRead, dwWritten; - CHAR chBuf[BUFSIZE]; - - /* Close the write end of the pipe before reading from the - read end of the pipe. */ - if (! CloseHandle(hWrite)) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("ReadFromPipe: Closing handle failed"); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_PIPE, "%s", msg); - g_free(msg); - return; - } - - /* Read output from the child process, and write to parent's STDOUT. */ - for (;;) - { - if (! ReadFile(hRead, chBuf, BUFSIZE, &dwRead, NULL) || dwRead == 0) - break; - - if (! WriteFile(hFile, chBuf, dwRead, &dwWritten, NULL)) - break; - } -} - - -static HANDLE GetTempFileHandle(GError **error) -{ - /* Temp file */ - DWORD dwBufSize = BUFSIZE; - UINT uRetVal; - TCHAR szTempName[BUFSIZE]; - TCHAR lpPathBuffer[BUFSIZE]; - DWORD dwRetVal; - HANDLE hTempFile; - - /* Get the temp path. */ - dwRetVal = GetTempPath(dwBufSize, /* length of the buffer*/ - lpPathBuffer); /* buffer for path */ - - if (dwRetVal > dwBufSize || (dwRetVal == 0)) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("GetTempFileHandle: GetTempPath failed (%d)", (gint) GetLastError()); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg); - g_free(msg); - return NULL; - } - - /* Create a temporary file for STDOUT. */ - uRetVal = GetTempFileName(lpPathBuffer, /* directory for tmp files */ - TEXT("GEANY_VCDIFF_"), /* temp file name prefix */ - 0, /* create unique name */ - szTempName); /* buffer for name */ - if (uRetVal == 0) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("GetTempFileName failed (%d)", (gint) GetLastError()); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg); - g_free(msg); - return NULL; - } - - hTempFile = CreateFile((LPTSTR) szTempName, /* file name */ - GENERIC_READ | GENERIC_WRITE, /* open r-w */ - 0, /* do not share */ - NULL, /* default security */ - CREATE_ALWAYS, /* overwrite existing */ - FILE_ATTRIBUTE_NORMAL,/* normal file */ - NULL); /* no template */ - - if (hTempFile == INVALID_HANDLE_VALUE) - { - gchar *msg = g_win32_error_message(GetLastError()); - geany_debug("GetTempFileHandle: Second CreateFile failed (%d)", (gint) GetLastError()); - g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg); - g_free(msg); - return NULL; - } - return hTempFile; -} - - /* From GDK (they got it from MS Knowledge Base article Q130698) */ static gboolean resolve_link(HWND hWnd, wchar_t *link, gchar **lpszPath) { diff --git a/src/win32.h b/src/win32.h index ad1af903d0..e2ce91d06e 100644 --- a/src/win32.h +++ b/src/win32.h @@ -60,11 +60,6 @@ void win32_init_debug_code(void); void win32_set_working_directory(const gchar *dir); -gboolean win32_get_exit_status(GPid child_pid); - -gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags, - gchar **std_out, gchar **std_err, gint *exit_status, GError **error); - gchar *win32_get_shortcut_target(const gchar *file_name); gchar *win32_get_installation_dir(void);