]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/2.4.3-win32-runscript-unicode-path.patch
ebl Fix patch to handle unicode in external command
[bacula/bacula] / bacula / patches / 2.4.3-win32-runscript-unicode-path.patch
1
2  This patch fix #1110 about a problem when executing a program with
3  Unicode path.
4
5  It can be applied to 2.4.3 (and previous versions) with:
6
7   cd <bacula-source>
8   patch -p0 <2.4.3-win32-runscript-unicode-path.patch
9   ./configure <your-options>
10   make
11   ...
12   make install
13
14
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 @@
20  }
21  
22  /**
23 + * Create the process with UTF8 API
24 + */
25 +static BOOL
26 +CreateChildProcessW(const char *comspec, const char *cmdLine,
27 +                    PROCESS_INFORMATION *hProcInfo,
28 +                    HANDLE in, HANDLE out, HANDLE err)
29 +{
30 +   STARTUPINFOW siStartInfo;
31 +   BOOL bFuncRetn = FALSE;
32 +
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
37 +
38 +   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
39 +   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
40 +
41 +   siStartInfo.hStdInput = in;
42 +   siStartInfo.hStdOutput = out;
43 +   siStartInfo.hStdError = err;
44 +   
45 +   // Convert argument to WCHAR
46 +   POOLMEM *cmdLine_wchar = get_pool_memory(PM_FNAME);
47 +   POOLMEM *comspec_wchar = get_pool_memory(PM_FNAME);
48 +
49 +   UTF8_2_wchar(&cmdLine_wchar, cmdLine);
50 +   UTF8_2_wchar(&comspec_wchar, comspec);
51 +
52 +   // Create the child process.
53 +   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec_wchar, cmdLine_wchar);
54 +
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
66 +
67 +   free_pool_memory(cmdLine_wchar);
68 +   free_pool_memory(comspec_wchar);
69 +
70 +   return bFuncRetn;
71 +}
72 +
73 +
74 +/**
75 + * Create the process with ANSI API
76 + */
77 +static BOOL
78 +CreateChildProcessA(const char *comspec, char *cmdLine,
79 +                    PROCESS_INFORMATION *hProcInfo,
80 +                    HANDLE in, HANDLE out, HANDLE err)
81 +{
82 +   STARTUPINFOA siStartInfo;
83 +   BOOL bFuncRetn = FALSE;
84 +
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;
91 +
92 +   siStartInfo.hStdInput = in;
93 +   siStartInfo.hStdOutput = out;
94 +   siStartInfo.hStdError = err;
95 +
96 +   // Create the child process.
97 +   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
98 +
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
110 +   return bFuncRetn;
111 +}
112 +
113 +/**
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.
116   */
117 @@ -1815,44 +1906,30 @@
118  {
119     static const char *comspec = NULL;
120     PROCESS_INFORMATION piProcInfo;
121 -   STARTUPINFOA siStartInfo;
122     BOOL bFuncRetn = FALSE;
123  
124 -   if (comspec == NULL) {
125 +   if (!p_CreateProcessA || !p_CreateProcessW)
126 +      return INVALID_HANDLE_VALUE;
127 +
128 +   if (comspec == NULL) 
129        comspec = getenv("COMSPEC");
130 -   }
131     if (comspec == NULL) // should never happen
132        return INVALID_HANDLE_VALUE;
133  
134     // Set up members of the PROCESS_INFORMATION structure.
135     ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
136  
137 -   // Set up members of the STARTUPINFO structure.
138 -
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
143     // as appropriate
144 -   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
145 -   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
146 +   if (in == INVALID_HANDLE_VALUE)
147 +      in = GetStdHandle(STD_INPUT_HANDLE);
148  
149 -   if (in != INVALID_HANDLE_VALUE)
150 -      siStartInfo.hStdInput = in;
151 -   else
152 -      siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
153 +   if (out == INVALID_HANDLE_VALUE)
154 +      out = GetStdHandle(STD_OUTPUT_HANDLE);
155  
156 -   if (out != INVALID_HANDLE_VALUE)
157 -      siStartInfo.hStdOutput = out;
158 -   else
159 -      siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
160 -   if (err != INVALID_HANDLE_VALUE)
161 -      siStartInfo.hStdError = err;
162 -   else
163 -      siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
164 +   if (err == INVALID_HANDLE_VALUE)
165 +      err = GetStdHandle(STD_ERROR_HANDLE);
166  
167 -   // Create the child process.
168 -
169     char *exeFile;
170     const char *argStart;
171  
172 @@ -1860,43 +1937,32 @@
173        return INVALID_HANDLE_VALUE;
174     }
175  
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);
179  
180 -   char *cmdLine = (char *)alloca(cmdLen);
181 -
182 -   snprintf(cmdLine, cmdLen, "%s /c %s%s", comspec, exeFile, argStart);
183 -
184     free(exeFile);
185  
186 -   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
187 +   if (p_CreateProcessW && p_MultiByteToWideChar) {
188 +      bFuncRetn = CreateChildProcessW(comspec, cmdLine.c_str(), &piProcInfo,
189 +                                      in, out, err);
190 +   } else {
191 +      bFuncRetn = CreateChildProcessA(comspec, cmdLine.c_str(), &piProcInfo,
192 +                                      in, out, err);
193 +   }
194  
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
206 -
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;
214     }
215     // we don't need a handle on the process primary thread so we close
216     // this now.
217     CloseHandle(piProcInfo.hThread);
218 -
219     return piProcInfo.hProcess;
220  }
221  
222 -
223  void
224  ErrorExit (LPCSTR lpszMessage)
225  {
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)
230 @@ -88,6 +88,9 @@
231  
232  t_SHGetFolderPath       p_SHGetFolderPath = NULL;
233  
234 +t_CreateProcessA        p_CreateProcessA = NULL;
235 +t_CreateProcessW        p_CreateProcessW = NULL;
236 +
237  void 
238  InitWinAPIWrapper() 
239  {
240 @@ -104,6 +107,12 @@
241  
242     HMODULE hLib = LoadLibraryA("KERNEL32.DLL");
243     if (hLib) {
244 +      /* create process calls */
245 +      p_CreateProcessA = (t_CreateProcessA)
246 +         GetProcAddress(hLib, "CreateProcessA");
247 +      p_CreateProcessW = (t_CreateProcessW)
248 +         GetProcAddress(hLib, "CreateProcessW");
249 +
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)
257 @@ -138,6 +138,32 @@
258  
259  typedef BOOL (WINAPI * t_AttachConsole) (DWORD);
260  
261 +typedef BOOL (WINAPI *t_CreateProcessA) (
262 +   LPCSTR,
263 +   LPSTR,
264 +   LPSECURITY_ATTRIBUTES,
265 +   LPSECURITY_ATTRIBUTES,
266 +   BOOL,
267 +   DWORD,
268 +   PVOID,
269 +   LPCSTR,
270 +   LPSTARTUPINFOA,
271 +   LPPROCESS_INFORMATION);
272 +typedef BOOL (WINAPI *t_CreateProcessW) (
273 +   LPCWSTR,
274 +   LPWSTR,
275 +   LPSECURITY_ATTRIBUTES,
276 +   LPSECURITY_ATTRIBUTES,
277 +   BOOL,
278 +   DWORD,
279 +   PVOID,
280 +   LPCWSTR,
281 +   LPSTARTUPINFOW,
282 +   LPPROCESS_INFORMATION);
283 +
284 +extern t_CreateProcessA DLL_IMP_EXP p_CreateProcessA;
285 +extern t_CreateProcessW DLL_IMP_EXP p_CreateProcessW;
286 +
287  extern t_GetFileAttributesA   DLL_IMP_EXP p_GetFileAttributesA;
288  extern t_GetFileAttributesW   DLL_IMP_EXP p_GetFileAttributesW;
289