-
- This patch fix #1110 about a problem when executing a program with
- Unicode path.
-
- It can be applied to 2.4.3 (and previous versions) with:
-
- cd <bacula-source>
- patch -p0 <2.4.3-win32-runscript-unicode-path.patch
- ./configure <your-options>
- make
- ...
- make install
-
-
-Index: src/win32/compat/compat.cpp
-===================================================================
---- src/win32/compat/compat.cpp (révision 7772)
-+++ src/win32/compat/compat.cpp (copie de travail)
-@@ -1807,6 +1807,97 @@
- }
-
- /**
-+ * Create the process with UTF8 API
-+ */
-+static BOOL
-+CreateChildProcessW(const char *comspec, const char *cmdLine,
-+ PROCESS_INFORMATION *hProcInfo,
-+ HANDLE in, HANDLE out, HANDLE err)
-+{
-+ STARTUPINFOW siStartInfo;
-+ BOOL bFuncRetn = FALSE;
-+
-+ // Set up members of the STARTUPINFO structure.
-+ ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
-+ siStartInfo.cb = sizeof(siStartInfo);
-+ // setup new process to use supplied handles for stdin,stdout,stderr
-+
-+ siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-+ siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
-+
-+ siStartInfo.hStdInput = in;
-+ siStartInfo.hStdOutput = out;
-+ siStartInfo.hStdError = err;
-+
-+ // Convert argument to WCHAR
-+ POOLMEM *cmdLine_wchar = get_pool_memory(PM_FNAME);
-+ POOLMEM *comspec_wchar = get_pool_memory(PM_FNAME);
-+
-+ UTF8_2_wchar(&cmdLine_wchar, cmdLine);
-+ UTF8_2_wchar(&comspec_wchar, comspec);
-+
-+ // Create the child process.
-+ Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec_wchar, cmdLine_wchar);
-+
-+ // try to execute program
-+ bFuncRetn = p_CreateProcessW((WCHAR*)comspec_wchar,
-+ (WCHAR*)cmdLine_wchar,// command line
-+ NULL, // process security attributes
-+ NULL, // primary thread security attributes
-+ TRUE, // handles are inherited
-+ 0, // creation flags
-+ NULL, // use parent's environment
-+ NULL, // use parent's current directory
-+ &siStartInfo, // STARTUPINFO pointer
-+ hProcInfo); // receives PROCESS_INFORMATION
-+
-+ free_pool_memory(cmdLine_wchar);
-+ free_pool_memory(comspec_wchar);
-+
-+ return bFuncRetn;
-+}
-+
-+
-+/**
-+ * Create the process with ANSI API
-+ */
-+static BOOL
-+CreateChildProcessA(const char *comspec, char *cmdLine,
-+ PROCESS_INFORMATION *hProcInfo,
-+ HANDLE in, HANDLE out, HANDLE err)
-+{
-+ STARTUPINFOA siStartInfo;
-+ BOOL bFuncRetn = FALSE;
-+
-+ // Set up members of the STARTUPINFO structure.
-+ ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
-+ siStartInfo.cb = sizeof(siStartInfo);
-+ // setup new process to use supplied handles for stdin,stdout,stderr
-+ siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-+ siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
-+
-+ siStartInfo.hStdInput = in;
-+ siStartInfo.hStdOutput = out;
-+ siStartInfo.hStdError = err;
-+
-+ // Create the child process.
-+ Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
-+
-+ // try to execute program
-+ bFuncRetn = p_CreateProcessA(comspec,
-+ cmdLine, // command line
-+ NULL, // process security attributes
-+ NULL, // primary thread security attributes
-+ TRUE, // handles are inherited
-+ 0, // creation flags
-+ NULL, // use parent's environment
-+ NULL, // use parent's current directory
-+ &siStartInfo,// STARTUPINFO pointer
-+ hProcInfo);// receives PROCESS_INFORMATION
-+ return bFuncRetn;
-+}
-+
-+/**
- * OK, so it would seem CreateProcess only handles true executables:
- * .com or .exe files. So grab $COMSPEC value and pass command line to it.
- */
-@@ -1815,44 +1906,30 @@
- {
- static const char *comspec = NULL;
- PROCESS_INFORMATION piProcInfo;
-- STARTUPINFOA siStartInfo;
- BOOL bFuncRetn = FALSE;
-
-- if (comspec == NULL) {
-+ if (!p_CreateProcessA || !p_CreateProcessW)
-+ return INVALID_HANDLE_VALUE;
-+
-+ if (comspec == NULL)
- comspec = getenv("COMSPEC");
-- }
- if (comspec == NULL) // should never happen
- return INVALID_HANDLE_VALUE;
-
- // 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);
-- // setup new process to use supplied handles for stdin,stdout,stderr
- // if supplied handles are not used the send a copy of our STD_HANDLE
- // as appropriate
-- siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-- siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
-+ if (in == INVALID_HANDLE_VALUE)
-+ in = GetStdHandle(STD_INPUT_HANDLE);
-
-- if (in != INVALID_HANDLE_VALUE)
-- siStartInfo.hStdInput = in;
-- else
-- siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
-+ if (out == INVALID_HANDLE_VALUE)
-+ out = GetStdHandle(STD_OUTPUT_HANDLE);
-
-- if (out != INVALID_HANDLE_VALUE)
-- siStartInfo.hStdOutput = out;
-- else
-- siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
-- if (err != INVALID_HANDLE_VALUE)
-- siStartInfo.hStdError = err;
-- else
-- siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-+ if (err == INVALID_HANDLE_VALUE)
-+ err = GetStdHandle(STD_ERROR_HANDLE);
-
-- // Create the child process.
--
- char *exeFile;
- const char *argStart;
-
-@@ -1860,43 +1937,32 @@
- return INVALID_HANDLE_VALUE;
- }
-
-- int cmdLen = strlen(comspec) + 4 + strlen(exeFile) + strlen(argStart) + 1;
-+ POOL_MEM cmdLine(PM_FNAME);
-+ Mmsg(cmdLine, "%s /c %s%s", comspec, exeFile, argStart);
-
-- char *cmdLine = (char *)alloca(cmdLen);
--
-- snprintf(cmdLine, cmdLen, "%s /c %s%s", comspec, exeFile, argStart);
--
- free(exeFile);
-
-- Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
-+ if (p_CreateProcessW && p_MultiByteToWideChar) {
-+ bFuncRetn = CreateChildProcessW(comspec, cmdLine.c_str(), &piProcInfo,
-+ in, out, err);
-+ } else {
-+ bFuncRetn = CreateChildProcessA(comspec, cmdLine.c_str(), &piProcInfo,
-+ in, out, err);
-+ }
-
-- // try to execute program
-- bFuncRetn = CreateProcessA(comspec,
-- cmdLine, // command line
-- NULL, // process security attributes
-- NULL, // primary thread security attributes
-- TRUE, // handles are inherited
-- 0, // creation flags
-- NULL, // use parent's environment
-- NULL, // use parent's current directory
-- &siStartInfo, // STARTUPINFO pointer
-- &piProcInfo); // receives PROCESS_INFORMATION
--
- if (bFuncRetn == 0) {
- ErrorExit("CreateProcess failed\n");
- const char *err = errorString();
-- Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n", comspec, cmdLine, err);
-+ Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n",comspec,cmdLine.c_str(),err);
- LocalFree((void *)err);
- return INVALID_HANDLE_VALUE;
- }
- // we don't need a handle on the process primary thread so we close
- // this now.
- CloseHandle(piProcInfo.hThread);
--
- return piProcInfo.hProcess;
- }
-
--
- void
- ErrorExit (LPCSTR lpszMessage)
- {
-Index: src/win32/compat/winapi.c
-===================================================================
---- src/win32/compat/winapi.c (révision 7772)
-+++ src/win32/compat/winapi.c (copie de travail)
-@@ -88,6 +88,9 @@
-
- t_SHGetFolderPath p_SHGetFolderPath = NULL;
-
-+t_CreateProcessA p_CreateProcessA = NULL;
-+t_CreateProcessW p_CreateProcessW = NULL;
-+
- void
- InitWinAPIWrapper()
- {
-@@ -104,6 +107,12 @@
-
- HMODULE hLib = LoadLibraryA("KERNEL32.DLL");
- if (hLib) {
-+ /* create process calls */
-+ p_CreateProcessA = (t_CreateProcessA)
-+ GetProcAddress(hLib, "CreateProcessA");
-+ p_CreateProcessW = (t_CreateProcessW)
-+ GetProcAddress(hLib, "CreateProcessW");
-+
- /* create file calls */
- p_CreateFileA = (t_CreateFileA)
- GetProcAddress(hLib, "CreateFileA");
-Index: src/win32/winapi.h
-===================================================================
---- src/win32/winapi.h (révision 7772)
-+++ src/win32/winapi.h (copie de travail)
-@@ -138,6 +138,32 @@
-
- typedef BOOL (WINAPI * t_AttachConsole) (DWORD);
-
-+typedef BOOL (WINAPI *t_CreateProcessA) (
-+ LPCSTR,
-+ LPSTR,
-+ LPSECURITY_ATTRIBUTES,
-+ LPSECURITY_ATTRIBUTES,
-+ BOOL,
-+ DWORD,
-+ PVOID,
-+ LPCSTR,
-+ LPSTARTUPINFOA,
-+ LPPROCESS_INFORMATION);
-+typedef BOOL (WINAPI *t_CreateProcessW) (
-+ LPCWSTR,
-+ LPWSTR,
-+ LPSECURITY_ATTRIBUTES,
-+ LPSECURITY_ATTRIBUTES,
-+ BOOL,
-+ DWORD,
-+ PVOID,
-+ LPCWSTR,
-+ LPSTARTUPINFOW,
-+ LPPROCESS_INFORMATION);
-+
-+extern t_CreateProcessA DLL_IMP_EXP p_CreateProcessA;
-+extern t_CreateProcessW DLL_IMP_EXP p_CreateProcessW;
-+
- extern t_GetFileAttributesA DLL_IMP_EXP p_GetFileAttributesA;
- extern t_GetFileAttributesW DLL_IMP_EXP p_GetFileAttributesW;
-