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