From: Eric Bollengier Date: Thu, 20 Nov 2008 09:49:54 +0000 (+0000) Subject: ebl Apply 2.4.3-win32-runscript-unicode-path.patch for #1110 X-Git-Tag: Release-2.4.4~29 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=0200d5b5c1377ee6d7399c5c95cde55bc40ccd22;p=bacula%2Fbacula ebl Apply 2.4.3-win32-runscript-unicode-path.patch for #1110 about a problem when executing a program with Unicode path. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/branches/Branch-2.4@8068 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/Patchnotes-2.4 b/bacula/Patchnotes-2.4 index aefda16a41..ce26d19059 100644 --- a/bacula/Patchnotes-2.4 +++ b/bacula/Patchnotes-2.4 @@ -7,6 +7,7 @@ Patches Released to Source Forge: Patches Committed: 20Nov08 2.4.3-unique-inchanger.patch +2.4.3-win32-runscript-unicode-path.patch 18Nov08 2.4.3-purge-bug.patch 2.4.3-getmsg.patch @@ -60,7 +61,3 @@ kes This patch should fix the bug reported on the bacula-users list where ebl This patch corrects a problem when removing a volume from an autochanger and the slot is still empty when running update slots command. #1175 - -2.4.3-win32-runscript-unicode-path.patch -ebl This patch fix #1110 about a problem when executing a program with - Unicode path. diff --git a/bacula/src/win32/compat/compat.cpp b/bacula/src/win32/compat/compat.cpp index a3171c3c30..c31e8465ab 100644 --- a/bacula/src/win32/compat/compat.cpp +++ b/bacula/src/win32/compat/compat.cpp @@ -1806,6 +1806,97 @@ GetApplicationName(const char *cmdline, char **pexe, const char **pargs) return true; } +/** + * 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,43 +1906,29 @@ CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err) { 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) - siStartInfo.hStdInput = in; - else - siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + if (in == INVALID_HANDLE_VALUE) + in = GetStdHandle(STD_INPUT_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 (out == INVALID_HANDLE_VALUE) + out = GetStdHandle(STD_OUTPUT_HANDLE); - // Create the child process. + if (err == INVALID_HANDLE_VALUE) + err = GetStdHandle(STD_ERROR_HANDLE); char *exeFile; const char *argStart; @@ -1860,43 +1937,32 @@ CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err) return INVALID_HANDLE_VALUE; } - int cmdLen = strlen(comspec) + 4 + strlen(exeFile) + strlen(argStart) + 1; - - char *cmdLine = (char *)alloca(cmdLen); - - snprintf(cmdLine, cmdLen, "%s /c %s%s", comspec, exeFile, argStart); + POOL_MEM cmdLine(PM_FNAME); + Mmsg(cmdLine, "%s /c %s%s", comspec, exeFile, argStart); free(exeFile); - Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine); - - // 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 (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); + } 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) { diff --git a/bacula/src/win32/compat/winapi.c b/bacula/src/win32/compat/winapi.c index ed75483388..ce56e3f185 100644 --- a/bacula/src/win32/compat/winapi.c +++ b/bacula/src/win32/compat/winapi.c @@ -88,6 +88,9 @@ t_GetVolumeNameForVolumeMountPointW p_GetVolumeNameForVolumeMountPointW = NULL; t_SHGetFolderPath p_SHGetFolderPath = NULL; +t_CreateProcessA p_CreateProcessA = NULL; +t_CreateProcessW p_CreateProcessW = NULL; + void InitWinAPIWrapper() { @@ -104,6 +107,12 @@ InitWinAPIWrapper() 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"); diff --git a/bacula/src/win32/winapi.h b/bacula/src/win32/winapi.h index 07b46e738b..847d2c0a13 100644 --- a/bacula/src/win32/winapi.h +++ b/bacula/src/win32/winapi.h @@ -138,6 +138,32 @@ typedef BOOL (WINAPI * t_GetVolumeNameForVolumeMountPointW) (LPCWSTR, LPWSTR, DW 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; diff --git a/bacula/technotes-2.4 b/bacula/technotes-2.4 index 102b2dbb90..4730371a34 100644 --- a/bacula/technotes-2.4 +++ b/bacula/technotes-2.4 @@ -2,6 +2,8 @@ General: 20Nov08 +ebl Apply 2.4.3-win32-runscript-unicode-path.patch for #1110 + about a problem when executing a program with Unicode path. ebl Apply 2.4.3-unique-inchanger.patch fix for #1175 about bad slot number if the volume is not in autochanger. 18Nov08