2 This patch fix #1110 about a problem when executing a program with
5 It can be applied to 2.4.3 (and previous versions) with:
8 patch -p0 <2.4.3-win32-runscript-unicode-path.patch
9 ./configure <your-options>
15 Index: src/win32/compat/compat.cpp
16 ===================================================================
17 --- src/win32/compat/compat.cpp (révision 7772)
18 +++ src/win32/compat/compat.cpp (copie de travail)
19 @@ -1807,6 +1807,97 @@
23 + * Create the process with UTF8 API
26 +CreateChildProcessW(const char *comspec, const char *cmdLine,
27 + PROCESS_INFORMATION *hProcInfo,
28 + HANDLE in, HANDLE out, HANDLE err)
30 + STARTUPINFOW siStartInfo;
31 + BOOL bFuncRetn = FALSE;
33 + // Set up members of the STARTUPINFO structure.
34 + ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
35 + siStartInfo.cb = sizeof(siStartInfo);
36 + // setup new process to use supplied handles for stdin,stdout,stderr
38 + siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
39 + siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
41 + siStartInfo.hStdInput = in;
42 + siStartInfo.hStdOutput = out;
43 + siStartInfo.hStdError = err;
45 + // Convert argument to WCHAR
46 + POOLMEM *cmdLine_wchar = get_pool_memory(PM_FNAME);
47 + POOLMEM *comspec_wchar = get_pool_memory(PM_FNAME);
49 + UTF8_2_wchar(&cmdLine_wchar, cmdLine);
50 + UTF8_2_wchar(&comspec_wchar, comspec);
52 + // Create the child process.
53 + Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec_wchar, cmdLine_wchar);
55 + // try to execute program
56 + bFuncRetn = p_CreateProcessW((WCHAR*)comspec_wchar,
57 + (WCHAR*)cmdLine_wchar,// command line
58 + NULL, // process security attributes
59 + NULL, // primary thread security attributes
60 + TRUE, // handles are inherited
61 + 0, // creation flags
62 + NULL, // use parent's environment
63 + NULL, // use parent's current directory
64 + &siStartInfo, // STARTUPINFO pointer
65 + hProcInfo); // receives PROCESS_INFORMATION
67 + free_pool_memory(cmdLine_wchar);
68 + free_pool_memory(comspec_wchar);
75 + * Create the process with ANSI API
78 +CreateChildProcessA(const char *comspec, char *cmdLine,
79 + PROCESS_INFORMATION *hProcInfo,
80 + HANDLE in, HANDLE out, HANDLE err)
82 + STARTUPINFOA siStartInfo;
83 + BOOL bFuncRetn = FALSE;
85 + // Set up members of the STARTUPINFO structure.
86 + ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
87 + siStartInfo.cb = sizeof(siStartInfo);
88 + // setup new process to use supplied handles for stdin,stdout,stderr
89 + siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
90 + siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
92 + siStartInfo.hStdInput = in;
93 + siStartInfo.hStdOutput = out;
94 + siStartInfo.hStdError = err;
96 + // Create the child process.
97 + Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
99 + // try to execute program
100 + bFuncRetn = p_CreateProcessA(comspec,
101 + cmdLine, // command line
102 + NULL, // process security attributes
103 + NULL, // primary thread security attributes
104 + TRUE, // handles are inherited
105 + 0, // creation flags
106 + NULL, // use parent's environment
107 + NULL, // use parent's current directory
108 + &siStartInfo,// STARTUPINFO pointer
109 + hProcInfo);// receives PROCESS_INFORMATION
114 * OK, so it would seem CreateProcess only handles true executables:
115 * .com or .exe files. So grab $COMSPEC value and pass command line to it.
117 @@ -1815,44 +1906,30 @@
119 static const char *comspec = NULL;
120 PROCESS_INFORMATION piProcInfo;
121 - STARTUPINFOA siStartInfo;
122 BOOL bFuncRetn = FALSE;
124 - if (comspec == NULL) {
125 + if (!p_CreateProcessA || !p_CreateProcessW)
126 + return INVALID_HANDLE_VALUE;
128 + if (comspec == NULL)
129 comspec = getenv("COMSPEC");
131 if (comspec == NULL) // should never happen
132 return INVALID_HANDLE_VALUE;
134 // Set up members of the PROCESS_INFORMATION structure.
135 ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
137 - // Set up members of the STARTUPINFO structure.
139 - ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
140 - siStartInfo.cb = sizeof(STARTUPINFO);
141 - // setup new process to use supplied handles for stdin,stdout,stderr
142 // if supplied handles are not used the send a copy of our STD_HANDLE
144 - siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
145 - siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
146 + if (in == INVALID_HANDLE_VALUE)
147 + in = GetStdHandle(STD_INPUT_HANDLE);
149 - if (in != INVALID_HANDLE_VALUE)
150 - siStartInfo.hStdInput = in;
152 - siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
153 + if (out == INVALID_HANDLE_VALUE)
154 + out = GetStdHandle(STD_OUTPUT_HANDLE);
156 - if (out != INVALID_HANDLE_VALUE)
157 - siStartInfo.hStdOutput = out;
159 - siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
160 - if (err != INVALID_HANDLE_VALUE)
161 - siStartInfo.hStdError = err;
163 - siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
164 + if (err == INVALID_HANDLE_VALUE)
165 + err = GetStdHandle(STD_ERROR_HANDLE);
167 - // Create the child process.
170 const char *argStart;
172 @@ -1860,43 +1937,32 @@
173 return INVALID_HANDLE_VALUE;
176 - int cmdLen = strlen(comspec) + 4 + strlen(exeFile) + strlen(argStart) + 1;
177 + POOL_MEM cmdLine(PM_FNAME);
178 + Mmsg(cmdLine, "%s /c %s%s", comspec, exeFile, argStart);
180 - char *cmdLine = (char *)alloca(cmdLen);
182 - snprintf(cmdLine, cmdLen, "%s /c %s%s", comspec, exeFile, argStart);
186 - Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
187 + if (p_CreateProcessW && p_MultiByteToWideChar) {
188 + bFuncRetn = CreateChildProcessW(comspec, cmdLine.c_str(), &piProcInfo,
191 + bFuncRetn = CreateChildProcessA(comspec, cmdLine.c_str(), &piProcInfo,
195 - // try to execute program
196 - bFuncRetn = CreateProcessA(comspec,
197 - cmdLine, // command line
198 - NULL, // process security attributes
199 - NULL, // primary thread security attributes
200 - TRUE, // handles are inherited
201 - 0, // creation flags
202 - NULL, // use parent's environment
203 - NULL, // use parent's current directory
204 - &siStartInfo, // STARTUPINFO pointer
205 - &piProcInfo); // receives PROCESS_INFORMATION
207 if (bFuncRetn == 0) {
208 ErrorExit("CreateProcess failed\n");
209 const char *err = errorString();
210 - Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n", comspec, cmdLine, err);
211 + Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n",comspec,cmdLine.c_str(),err);
212 LocalFree((void *)err);
213 return INVALID_HANDLE_VALUE;
215 // we don't need a handle on the process primary thread so we close
217 CloseHandle(piProcInfo.hThread);
219 return piProcInfo.hProcess;
224 ErrorExit (LPCSTR lpszMessage)
226 Index: src/win32/compat/winapi.c
227 ===================================================================
228 --- src/win32/compat/winapi.c (révision 7772)
229 +++ src/win32/compat/winapi.c (copie de travail)
232 t_SHGetFolderPath p_SHGetFolderPath = NULL;
234 +t_CreateProcessA p_CreateProcessA = NULL;
235 +t_CreateProcessW p_CreateProcessW = NULL;
242 HMODULE hLib = LoadLibraryA("KERNEL32.DLL");
244 + /* create process calls */
245 + p_CreateProcessA = (t_CreateProcessA)
246 + GetProcAddress(hLib, "CreateProcessA");
247 + p_CreateProcessW = (t_CreateProcessW)
248 + GetProcAddress(hLib, "CreateProcessW");
250 /* create file calls */
251 p_CreateFileA = (t_CreateFileA)
252 GetProcAddress(hLib, "CreateFileA");
253 Index: src/win32/winapi.h
254 ===================================================================
255 --- src/win32/winapi.h (révision 7772)
256 +++ src/win32/winapi.h (copie de travail)
259 typedef BOOL (WINAPI * t_AttachConsole) (DWORD);
261 +typedef BOOL (WINAPI *t_CreateProcessA) (
264 + LPSECURITY_ATTRIBUTES,
265 + LPSECURITY_ATTRIBUTES,
271 + LPPROCESS_INFORMATION);
272 +typedef BOOL (WINAPI *t_CreateProcessW) (
275 + LPSECURITY_ATTRIBUTES,
276 + LPSECURITY_ATTRIBUTES,
282 + LPPROCESS_INFORMATION);
284 +extern t_CreateProcessA DLL_IMP_EXP p_CreateProcessA;
285 +extern t_CreateProcessW DLL_IMP_EXP p_CreateProcessW;
287 extern t_GetFileAttributesA DLL_IMP_EXP p_GetFileAttributesA;
288 extern t_GetFileAttributesW DLL_IMP_EXP p_GetFileAttributesW;