--- /dev/null
+
+ 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;
+