SF.net SVN: geany: [2279] trunk
eht16 at users.sourceforge.net
eht16 at xxxxx
Sun Feb 24 10:27:40 UTC 2008
Revision: 2279
http://geany.svn.sourceforge.net/geany/?rev=2279&view=rev
Author: eht16
Date: 2008-02-24 02:27:32 -0800 (Sun, 24 Feb 2008)
Log Message:
-----------
Apply patch by Pierre Joye to add new process spawning implementation for Windows.
Make utils_spawn_* available to plugin API.
This makes the VCdiff plugin to work on Windows (thanks).
Modified Paths:
--------------
trunk/ChangeLog
trunk/THANKS
trunk/plugins/vcdiff.c
trunk/src/plugindata.h
trunk/src/plugins.c
trunk/src/utils.c
trunk/src/utils.h
trunk/src/win32.c
trunk/src/win32.h
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2008-02-24 10:22:35 UTC (rev 2278)
+++ trunk/ChangeLog 2008-02-24 10:27:32 UTC (rev 2279)
@@ -5,6 +5,11 @@
* configure.in:
Apply patch Yura Siamashka to add a check for the presence of
fnmatch(), thanks.
+ * THANKS, plugins/vcdiff.c, src/plugindata.h, src/plugins.c,
+ src/utils.c, src/utils.h, src/win32.c, src/win32.h:
+ Apply patch by Pierre Joye to add new process spawning implementation
+ for Windows. Make utils_spawn_* available to plugin API.
+ This makes the VCdiff plugin to work on Windows (thanks).
2008-02-22 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
Modified: trunk/THANKS
===================================================================
--- trunk/THANKS 2008-02-24 10:22:35 UTC (rev 2278)
+++ trunk/THANKS 2008-02-24 10:27:32 UTC (rev 2279)
@@ -41,6 +41,7 @@
Bo Lorentsen <bl(at)lue(dot)dk> - project session patch
Yura Siamashka <yurand2(at)gmail(dot)com> - many patches
Daniel Richard G. <skunk(at)iskunk(dot)org> - some patches
+Pierre Joye <pierre(dot)php(at)gmail(dot)com> - Win32 process spawning patch
Translators:
------------
Modified: trunk/plugins/vcdiff.c
===================================================================
--- trunk/plugins/vcdiff.c 2008-02-24 10:22:35 UTC (rev 2278)
+++ trunk/plugins/vcdiff.c 2008-02-24 10:27:32 UTC (rev 2279)
@@ -36,6 +36,7 @@
#include "project.h"
#include "pluginmacros.h"
+
PluginFields *plugin_fields;
GeanyData *geany_data;
@@ -186,7 +187,7 @@
}
-static void* get_cmd_env(gint cmd_type, gboolean cmd, const gchar* filename)
+static void* get_cmd_env(gint cmd_type, gboolean cmd, const gchar* filename, int *size)
{
int i;
gint len = 0;
@@ -234,6 +235,9 @@
else
ret[i] = g_strdup(argv[i]);
}
+
+ *size = len;
+
g_free(dir);
g_free(base_filename);
return ret;
@@ -312,13 +316,15 @@
{
gchar *std_output = NULL;
gchar *std_error = NULL;
- gint exit_code;
gchar *text = NULL;
gchar *dir;
- gchar **env = get_cmd_env(cmd, FALSE, filename);
- gchar **argv = get_cmd_env(cmd, TRUE, filename);
+ gint argc = 0;
+ gchar **env = get_cmd_env(cmd, FALSE, filename, &argc);
+ gchar **argv = get_cmd_env(cmd, TRUE, filename, &argc);
+ gint exit_code = 0;
+ GError *error = NULL;
- if (!argv)
+ if (! argv)
{
if (env)
g_strfreev(env);
@@ -334,9 +340,10 @@
dir = g_path_get_dirname(filename);
}
- if (g_spawn_sync(dir, argv, env, G_SPAWN_SEARCH_PATH, NULL, NULL, &std_output, &std_error, &exit_code, NULL))
+ if (p_utils->spawn_sync(dir, argv, env, G_SPAWN_SEARCH_PATH, NULL, NULL,
+ &std_output, &std_error, &exit_code, &error))
{
- // CVS dump stuff to stderr when diff nested dirs
+ /* CVS dump stuff to stderr when diff nested dirs */
if (strcmp(argv[0], "cvs") != 0 && NZV(std_error))
{
p_dialogs->show_msgbox(1,
@@ -350,12 +357,29 @@
{
p_ui->set_statusbar(FALSE, _("No changes were made."));
}
+
+ if (NZV(std_error))
+ {
+ p_dialogs->show_msgbox(1, _("VCdiff command sent errors:\n%s\n."), std_error);
+ }
}
else
{
- p_ui->set_statusbar(FALSE,
- _("Something went really wrong."));
+ gchar *msg;
+
+ if (error != NULL)
+ {
+ msg = g_strdup(error->message);
+ g_error_free(error);
+ }
+ else
+ { /* if we don't have an exact error message, print at least the failing command */
+ msg = g_strdup_printf(_("unknown error while trying to spawn a process for %s"),
+ argv[0]);
+ }
+ p_ui->set_statusbar(FALSE, _("An error occurred (%s)."), msg);
}
+
g_free(dir);
g_free(std_error);
g_strfreev(env);
Modified: trunk/src/plugindata.h
===================================================================
--- trunk/src/plugindata.h 2008-02-24 10:22:35 UTC (rev 2278)
+++ trunk/src/plugindata.h 2008-02-24 10:27:32 UTC (rev 2279)
@@ -36,7 +36,7 @@
/* The API version should be incremented whenever any plugin data types below are
* modified or appended to. */
-static const gint api_version = 44;
+static const gint api_version = 45;
/* The ABI version should be incremented whenever existing fields in the plugin
* data types below have to be changed or reordered. It should stay the same if fields
@@ -241,6 +241,12 @@
const gint default_value);
gchar* (*get_setting_string) (GKeyFile *config, const gchar *section, const gchar *key,
const gchar *default_value);
+ gboolean (*spawn_sync) (const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+ GSpawnChildSetupFunc child_setup, gpointer user_data, gchar **std_out,
+ gchar **std_err, gint *exit_status, GError **error);
+ gboolean (*spawn_async) (const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+ GSpawnChildSetupFunc child_setup, gpointer user_data, GPid *child_pid,
+ GError **error);
}
UtilsFuncs;
Modified: trunk/src/plugins.c
===================================================================
--- trunk/src/plugins.c 2008-02-24 10:22:35 UTC (rev 2278)
+++ trunk/src/plugins.c 2008-02-24 10:27:32 UTC (rev 2279)
@@ -153,7 +153,9 @@
&utils_mkdir,
&utils_get_setting_boolean,
&utils_get_setting_integer,
- &utils_get_setting_string
+ &utils_get_setting_string,
+ &utils_spawn_sync,
+ &utils_spawn_async
};
static UIUtilsFuncs uiutils_funcs = {
Modified: trunk/src/utils.c
===================================================================
--- trunk/src/utils.c 2008-02-24 10:22:35 UTC (rev 2278)
+++ trunk/src/utils.c 2008-02-24 10:27:32 UTC (rev 2279)
@@ -1793,3 +1793,111 @@
}
+static gboolean check_error(GError **error)
+{
+ if (error != NULL && *error != NULL)
+ {
+ /* imitate the GLib warning */
+ g_warning(
+ "GError set over the top of a previous GError or uninitialized memory.\n"
+ "This indicates a bug in someone's code. You must ensure an error is NULL "
+ "before it's set.");
+ /* after returning the code may segfault, but we don't care because we should
+ * make sure *error is NULL */
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/**
+ * This is a wrapper function for g_spawn_sync() and internally calls this function on Unix-like
+ * systems. On Win32 platforms, it uses the Windows API.
+ *
+ * @param dir The child's current working directory, or @a NULL to inherit parent's.
+ * @param argv The child's argument vector.
+ * @param env The child's environment, or @a NULL to inherit parent's.
+ * @param flags Flags from GSpawnFlags.
+ * @param child_setup A function to run in the child just before exec().
+ * @param user_data The user data for child_setup.
+ * @param std_out The return location for child output.
+ * @param std_err The return location for child error messages.
+ * @param exit_status The child exit status, as returned by waitpid().
+ * @param error The return location for error or @a NULL.
+ *
+ * @return @a TRUE on success, @a FALSE if an error was set.
+ **/
+gboolean utils_spawn_sync(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+ GSpawnChildSetupFunc child_setup, gpointer user_data, gchar **std_out,
+ gchar **std_err, gint *exit_status, GError **error)
+{
+ gboolean result;
+
+ if (! check_error(error))
+ return FALSE;
+
+ if (argv == NULL)
+ {
+ *error = g_error_new(G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, "argv must not be NULL");
+ return FALSE;
+ }
+
+ if (std_out)
+ *std_out = NULL;
+
+ if (std_err)
+ *std_err = NULL;
+
+#ifdef G_OS_WIN32
+ result = win32_spawn(dir, argv, env, flags, std_out, std_err, exit_status);
+ /** TODO create error messages in win32_spawn with appropriate error message text **/
+ if (! result)
+ *error = g_error_new(G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, _("Process could not be created."));
+#else
+ result = g_spawn_sync(dir, argv, env, flags, NULL, NULL, std_out, std_err, exit_status, error);
+#endif
+
+ return result;
+}
+
+
+/**
+ * This is a wrapper function for g_spawn_async() and internally calls this function on Unix-like
+ * systems. On Win32 platforms, it uses the Windows API.
+ *
+ * @param dir The child's current working directory, or @a NULL to inherit parent's.
+ * @param argv The child's argument vector.
+ * @param env The child's environment, or @a NULL to inherit parent's.
+ * @param flags Flags from GSpawnFlags.
+ * @param child_setup A function to run in the child just before exec().
+ * @param user_data The user data for child_setup.
+ * @param child_pid The return location for child process ID, or NULL.
+ * @param error The return location for error or @a NULL.
+ *
+ * @return @a TRUE on success, @a FALSE if an error was set.
+ **/
+gboolean utils_spawn_async(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+ GSpawnChildSetupFunc child_setup, gpointer user_data, GPid *child_pid,
+ GError **error)
+{
+ gboolean result;
+
+ if (! check_error(error))
+ return FALSE;
+
+ if (argv == NULL)
+ {
+ *error = g_error_new(G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, "argv must not be NULL");
+ return FALSE;
+ }
+
+#ifdef G_OS_WIN32
+ result = win32_spawn(dir, argv, env, flags, NULL, NULL, NULL);
+ /** TODO create error messages in win32_spawn with appropriate error message text **/
+ if (! result)
+ *error = g_error_new(G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, _("Process could not be created."));
+#else
+ result = g_spawn_async(dir, argv, env, flags, NULL, NULL, child_pid, error);
+#endif
+ return result;
+}
Modified: trunk/src/utils.h
===================================================================
--- trunk/src/utils.h 2008-02-24 10:22:35 UTC (rev 2278)
+++ trunk/src/utils.h 2008-02-24 10:27:32 UTC (rev 2279)
@@ -146,4 +146,13 @@
gint utils_is_file_writeable(const gchar *locale_filename);
+
+gboolean utils_spawn_sync(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+ GSpawnChildSetupFunc child_setup, gpointer user_data, gchar **std_out,
+ gchar **std_err, gint *exit_status, GError **error);
+
+gboolean utils_spawn_async(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+ GSpawnChildSetupFunc child_setup, gpointer user_data, GPid *child_pid,
+ GError **error);
+
#endif
Modified: trunk/src/win32.c
===================================================================
--- trunk/src/win32.c 2008-02-24 10:22:35 UTC (rev 2278)
+++ trunk/src/win32.c 2008-02-24 10:27:32 UTC (rev 2279)
@@ -54,8 +54,29 @@
#include "dialogs.h"
#include "filetypes.h"
+#define BUFSIZE 4096
+struct _geany_win32_spawn
+{
+ HANDLE hChildStdinRd;
+ HANDLE hChildStdinWr;
+ HANDLE hChildStdoutRd;
+ HANDLE hChildStdoutWr;
+ HANDLE hChildStderrRd;
+ HANDLE hChildStderrWr;
+ HANDLE hInputFile;
+ HANDLE hStdout;
+ HANDLE hStderr;
+};
+typedef struct _geany_win32_spawn geany_win32_spawn;
+
+static gboolean GetContentFromHandle(HANDLE hFile, gchar **content);
+static HANDLE GetTempFileHandle(void);
+static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, const TCHAR *dir);
+static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile);
+
+
static gchar *get_file_filters()
{
gchar *string;
@@ -313,7 +334,7 @@
if (CommDlgExtendedError())
{
gchar error[100];
- snprintf(error, sizeof error, "File dialog box error (%x)", (int)CommDlgExtendedError());
+ g_snprintf(error, sizeof error, "File dialog box error (%x)", (int)CommDlgExtendedError());
win32_message_dialog(NULL, GTK_MESSAGE_ERROR, error);
}
g_free(fname);
@@ -482,7 +503,7 @@
if (CommDlgExtendedError())
{
gchar error[100];
- snprintf(error, sizeof error, "File dialog box error (%x)", (int)CommDlgExtendedError());
+ g_snprintf(error, sizeof error, "File dialog box error (%x)", (int)CommDlgExtendedError());
win32_message_dialog(NULL, GTK_MESSAGE_ERROR, error);
}
g_strfreev(field);
@@ -712,4 +733,295 @@
return g_strdup("localhost");
}
+
+/* Process spawning implementation for Windows, by Pierre Joye.
+ * Don't call this function directly, use utils_spawn_[a]sync() instead. */
+gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+ gchar **std_out, gchar **std_err, gint *exit_status)
+{
+ TCHAR buffer[MAX_PATH]=TEXT("");
+ TCHAR cmdline[MAX_PATH] = TEXT("");
+ TCHAR* lpPart[MAX_PATH]={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", MAX_PATH, buffer, lpPart);
+ g_snprintf(cmdline, MAX_PATH, "\"%s\"", buffer);
+ cmdpos = 1;
+ }
+
+ for (i = cmdpos; i < argc; i++)
+ {
+ g_snprintf(cmdline, MAX_PATH, "%s %s", cmdline, argv[i]);
+ /*MessageBox(NULL, cmdline, cmdline, MB_OK);*/
+ }
+
+ if (std_err != NULL)
+ {
+ hStderrTempFile = GetTempFileHandle();
+ if (hStderrTempFile == INVALID_HANDLE_VALUE)
+ {
+ geany_debug("win32_spawn: Second CreateFile failed (%d)\n", (gint) GetLastError());
+ return FALSE;
+ }
+ }
+
+ if (std_out != NULL)
+ {
+ hStdoutTempFile = GetTempFileHandle();
+ if (hStdoutTempFile == INVALID_HANDLE_VALUE)
+ {
+ geany_debug("win32_spawn: Second CreateFile failed (%d)\n", (gint) GetLastError());
+ 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);
+
+ /* Create a pipe for the child process's STDOUT. */
+ if (! CreatePipe(&(gw_spawn.hChildStdoutRd), &(gw_spawn.hChildStdoutWr), &saAttr, 0))
+ {
+ geany_debug("win32_spawn: Stdout pipe creation failed\n");
+ 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))
+ {
+ geany_debug("win32_spawn: Stdout pipe creation failed\n");
+ 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))
+ {
+ geany_debug("win32_spawn: Stdin pipe creation failed\n");
+ 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);
+ if (!fSuccess)
+ {
+ geany_debug("win32_spawn: Create process failed with");
+ 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);
+ GetContentFromHandle(hStdoutTempFile, &stdout_content);
+ *std_out = stdout_content;
+ }
+
+ if (std_err != NULL)
+ {
+ ReadFromPipe(gw_spawn.hChildStderrRd, gw_spawn.hChildStderrWr, hStderrTempFile);
+ GetContentFromHandle(hStderrTempFile, &stderr_content);
+ *std_err = stderr_content;
+ }
+
+ return TRUE;
+}
+
+
+static gboolean GetContentFromHandle(HANDLE hFile, gchar **content)
+{
+ DWORD filesize;
+ gchar * buffer;
+ DWORD dwRead;
+
+ filesize = GetFileSize(hFile, NULL);
+ if (filesize < 1)
+ {
+ *content = NULL;
+ return TRUE;
+ }
+
+ buffer = g_malloc(sizeof(gchar*) * (filesize+1));
+ if (!buffer)
+ {
+ geany_debug("GetContentFromHandle: Alloc failed");
+ return FALSE;
+ }
+
+ SetFilePointer(hFile,0, NULL, FILE_BEGIN);
+ if (!ReadFile(hFile, buffer, filesize, &dwRead,
+ NULL) || dwRead == 0)
+ {
+ geany_debug("GetContentFromHandle: Cannot read tempfile");
+ return FALSE;
+ }
+
+ if (!CloseHandle (hFile))
+ {
+ geany_debug("GetContentFromHandle: CloseHandle failed (%d)\n", (gint) GetLastError());
+ g_free(buffer);
+ *content = NULL;
+ return FALSE;
+ }
+ *content = buffer;
+ return TRUE;
+}
+
+
+static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, const TCHAR *dir)
+{
+ PROCESS_INFORMATION piProcInfo;
+ STARTUPINFO siStartInfo;
+ BOOL bFuncRetn = FALSE;
+
+ /* 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;
+
+ /* Create the child process. */
+ bFuncRetn = CreateProcess(NULL,
+ szCmdline, /* 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 */
+ dir, /* use parent's current directory */
+ &siStartInfo, /* STARTUPINFO pointer */
+ &piProcInfo); /* receives PROCESS_INFORMATION */
+
+ if (bFuncRetn == 0)
+ {
+ geany_debug("CreateChildProcess: CreateProcess failed\n");
+ return FALSE;
+ }
+ else
+ {
+ CloseHandle(piProcInfo.hProcess);
+ CloseHandle(piProcInfo.hThread);
+ return bFuncRetn;
+ }
+ return FALSE;
+}
+
+
+static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile)
+{
+ 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))
+ {
+ geany_debug("ReadFromPipe: Closing handle failed");
+ 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(void)
+{
+ /* 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))
+ {
+ geany_debug("GetTempFileHandle: GetTempPath failed (%d)\n", (gint) GetLastError());
+ 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)
+ {
+ geany_debug("GetTempFileName failed (%d)\n", (gint) GetLastError());
+ 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)
+ {
+ geany_debug("GetTempFileHandle: Second CreateFile failed (%d)\n", (gint) GetLastError());
+ return NULL;
+ }
+ return hTempFile;
+}
+
#endif
Modified: trunk/src/win32.h
===================================================================
--- trunk/src/win32.h 2008-02-24 10:22:35 UTC (rev 2278)
+++ trunk/src/win32.h 2008-02-24 10:27:32 UTC (rev 2279)
@@ -61,4 +61,7 @@
gchar *win32_get_hostname();
+gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+ gchar **std_out, gchar **std_err, gint *exit_status);
+
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Commits
mailing list