Module: wine Branch: master Commit: a968a1ad6dccd85548b62b43d7a0e41d2a4058d5 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a968a1ad6dccd85548b62b43d7...
Author: Piotr Caban piotr@codeweavers.com Date: Fri Jan 18 11:03:51 2013 +0100
msvcrt: Return child exit code in _pclose function.
Based on a patch by Borut Ražem.
---
dlls/msvcrt/main.c | 1 + dlls/msvcrt/msvcrt.h | 1 + dlls/msvcrt/process.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c index ca761ad..6df9ccf 100644 --- a/dlls/msvcrt/main.c +++ b/dlls/msvcrt/main.c @@ -118,6 +118,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_THREAD_ATTACH: break; case DLL_PROCESS_DETACH: + msvcrt_free_popen_data(); msvcrt_free_io(); msvcrt_free_mt_locks(); msvcrt_free_console(); diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 4915309..ba67b65 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -269,6 +269,7 @@ extern void msvcrt_init_args(void) DECLSPEC_HIDDEN; extern void msvcrt_free_args(void) DECLSPEC_HIDDEN; extern void msvcrt_init_signals(void) DECLSPEC_HIDDEN; extern void msvcrt_free_signals(void) DECLSPEC_HIDDEN; +extern void msvcrt_free_popen_data(void) DECLSPEC_HIDDEN;
extern unsigned msvcrt_create_io_inherit_block(WORD*, BYTE**) DECLSPEC_HIDDEN;
diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c index d1e8e21..cc64c2d 100644 --- a/dlls/msvcrt/process.c +++ b/dlls/msvcrt/process.c @@ -31,6 +31,7 @@ #include <stdarg.h>
#include "msvcrt.h" +#include "mtdll.h" #include "wine/debug.h" #include "wine/unicode.h"
@@ -1022,6 +1023,17 @@ MSVCRT_intptr_t CDECL _wspawnvp(int flags, const MSVCRT_wchar_t* name, const MSV return MSVCRT__wspawnvpe(flags, name, argv, NULL); }
+static struct popen_handle { + MSVCRT_FILE *f; + HANDLE proc; +} *popen_handles; +static DWORD popen_handles_size; + +void msvcrt_free_popen_data(void) +{ + MSVCRT_free(popen_handles); +} + /********************************************************************* * _wpopen (MSVCRT.@) * @@ -1036,6 +1048,8 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc MSVCRT_wchar_t *comspec, *fullcmd; unsigned int len; static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0}; + struct popen_handle *container; + DWORD i;
TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
@@ -1069,6 +1083,25 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc fdToDup = readPipe ? 1 : 0; fdToOpen = readPipe ? 0 : 1;
+ _mlock(_POPEN_LOCK); + for(i=0; i<popen_handles_size; i++) + { + if (!popen_handles[i].f) + break; + } + if (i==popen_handles_size) + { + i = (popen_handles_size ? popen_handles_size*2 : 8); + container = MSVCRT_realloc(popen_handles, i*sizeof(*container)); + if (!container) goto error; + + popen_handles = container; + container = popen_handles+popen_handles_size; + memset(container, 0, (i-popen_handles_size)*sizeof(*container)); + popen_handles_size = i; + } + else container = popen_handles+i; + if ((fdStdHandle = MSVCRT__dup(fdToDup)) == -1) goto error; if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0) @@ -1089,7 +1122,8 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc strcatW(fullcmd, flag); strcatW(fullcmd, command);
- if (msvcrt_spawn(MSVCRT__P_NOWAIT, comspec, fullcmd, NULL, 1) == -1) + if ((container->proc = (HANDLE)msvcrt_spawn(MSVCRT__P_NOWAIT, comspec, fullcmd, NULL, 1)) + == INVALID_HANDLE_VALUE) { MSVCRT__close(fds[fdToOpen]); ret = NULL; @@ -1099,7 +1133,9 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc ret = MSVCRT__wfdopen(fds[fdToOpen], mode); if (!ret) MSVCRT__close(fds[fdToOpen]); + container->f = ret; } + _munlock(_POPEN_LOCK); HeapFree(GetProcessHeap(), 0, comspec); HeapFree(GetProcessHeap(), 0, fullcmd); MSVCRT__dup2(fdStdHandle, fdToDup); @@ -1107,6 +1143,7 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc return ret;
error: + _munlock(_POPEN_LOCK); if (fdStdHandle != -1) MSVCRT__close(fdStdHandle); MSVCRT__close(fds[0]); MSVCRT__close(fds[1]); @@ -1145,7 +1182,38 @@ MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode) */ int CDECL MSVCRT__pclose(MSVCRT_FILE* file) { - return MSVCRT_fclose(file); + HANDLE h; + DWORD i; + + if (!MSVCRT_CHECK_PMT(file != NULL)) return -1; + + _mlock(_POPEN_LOCK); + for(i=0; i<popen_handles_size; i++) + { + if (popen_handles[i].f == file) + break; + } + if(i == popen_handles_size) + { + _munlock(_POPEN_LOCK); + *MSVCRT__errno() = MSVCRT_EBADF; + return -1; + } + + h = popen_handles[i].proc; + popen_handles[i].f = NULL; + _munlock(_POPEN_LOCK); + + MSVCRT_fclose(file); + if(WaitForSingleObject(h, INFINITE)==WAIT_FAILED || !GetExitCodeProcess(h, &i)) + { + msvcrt_set_errno(GetLastError()); + CloseHandle(h); + return -1; + } + + CloseHandle(h); + return i; }
/*********************************************************************