Changeset 3195 for trunk/src/kmk/w32
- Timestamp:
- Mar 27, 2018, 8:09:23 PM (7 years ago)
- Location:
- trunk/src/kmk/w32
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/w32/imagecache.c
r3140 r3195 26 26 /* No GNU coding style here! */ 27 27 28 /******************************************************************************* 29 * Header Files *30 ******************************************************************************* /28 /********************************************************************************************************************************* 29 * Header Files * 30 *********************************************************************************************************************************/ 31 31 #include "makeint.h" 32 32 … … 34 34 35 35 36 /******************************************************************************* 37 * Structures and Typedefs *38 ******************************************************************************* /36 /********************************************************************************************************************************* 37 * Structures and Typedefs * 38 *********************************************************************************************************************************/ 39 39 typedef struct EXECCACHEENTRY 40 40 { … … 42 42 unsigned uHash; 43 43 /** The name length. */ 44 unsigned c chName;44 unsigned cwcName; 45 45 /** Pointer to the next name with the same hash. */ 46 46 struct EXECCACHEENTRY *pNext; 47 47 /** When it was last referenced. */ 48 48 unsigned uLastRef; 49 /** The module handle . */49 /** The module handle, LOAD_LIBRARY_AS_DATAFILE. */ 50 50 HMODULE hmod1; 51 /** The module handle . */51 /** The module handle, DONT_RESOLVE_DLL_REFERENCES. */ 52 52 HMODULE hmod2; 53 53 /** The executable path. */ 54 charszName[1];54 wchar_t wszName[1]; 55 55 } EXECCACHEENTRY; 56 56 typedef EXECCACHEENTRY *PEXECCACHEENTRY; 57 57 58 /******************************************************************************* 59 * Global Variables * 60 *******************************************************************************/ 58 59 /********************************************************************************************************************************* 60 * Global Variables * 61 *********************************************************************************************************************************/ 62 /** Critical section serializing all access. */ 63 static CRITICAL_SECTION g_CritSect; 64 /** Set if initialized. */ 65 static int volatile g_fInitialized = 0; 61 66 /** The number of cached images. */ 62 67 static unsigned g_cCached; … … 69 74 /** The hash table. */ 70 75 static PEXECCACHEENTRY g_apHashTab[EXECCACHE_HASHTAB_SIZE]; 76 77 78 /** A sleepy approach to do-once. */ 79 static void kmk_cache_lazy_init(void) 80 { 81 if (_InterlockedCompareExchange(&g_fInitialized, -1, 0) == 0) 82 { 83 InitializeCriticalSection(&g_CritSect); 84 _InterlockedExchange(&g_fInitialized, 1); 85 } 86 else 87 while (g_fInitialized != 1) 88 Sleep(1); 89 } 71 90 72 91 … … 83 102 elsewhere. */ 84 103 85 static unsigned execcache_calc_hash(const char *psz, unsigned*pcch)86 { 87 unsigned char *puch = (unsigned char *)psz;88 unsigned hash = 0;89 int ch;90 91 while ((ch = *p uch++))104 static unsigned execcache_calc_hash(const wchar_t *pwsz, size_t *pcch) 105 { 106 wchar_t const * const pwszStart = pwsz; 107 unsigned hash = 0; 108 int ch; 109 110 while ((ch = *pwsz++) != L'\0') 92 111 hash = ch + (hash << 6) + (hash << 16) - hash; 93 112 94 *pcch = ( unsigned)(puch - psz- 1);113 *pcch = (size_t)(pwsz - pwszStart - 1); 95 114 return hash; 96 115 } 97 116 98 99 extern void kmk_cache_exec_image(const char *pszExec) 100 { 101 /* 102 * Lookup the name. 103 */ 104 unsigned cchName; 105 const unsigned uHash = execcache_calc_hash(pszExec, &cchName); 117 /** 118 * Caches two memory mappings of the specified image so that it isn't flushed 119 * from the kernel's cache mananger. 120 * 121 * Not sure exactly how much this actually helps, but whatever... 122 * 123 * @param pwszExec The executable. 124 */ 125 extern void kmk_cache_exec_image_w(const wchar_t *pwszExec) 126 { 127 /* 128 * Prepare name lookup and to lazy init. 129 */ 130 size_t cwcName; 131 const unsigned uHash = execcache_calc_hash(pwszExec, &cwcName); 106 132 PEXECCACHEENTRY *ppCur = &g_apHashTab[uHash % EXECCACHE_HASHTAB_SIZE]; 107 PEXECCACHEENTRY pCur = *ppCur; 133 PEXECCACHEENTRY pCur; 134 135 if (g_fInitialized != 1) 136 kmk_cache_lazy_init(); 137 138 /* 139 * Do the lookup. 140 */ 141 EnterCriticalSection(&g_CritSect); 142 pCur = *ppCur; 108 143 while (pCur) 109 144 { 110 145 if ( pCur->uHash == uHash 111 && pCur->c chName == cchName112 && !memcmp(pCur-> szName, pszExec, cchName))146 && pCur->cwcName == cwcName 147 && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t))) 113 148 { 114 149 pCur->uLastRef = ++g_uNow; 150 LeaveCriticalSection(&g_CritSect); 115 151 return; 116 152 } … … 118 154 pCur = pCur->pNext; 119 155 } 156 LeaveCriticalSection(&g_CritSect); 120 157 121 158 /* 122 159 * Not found, create a new entry. 123 160 */ 124 pCur = xmalloc(sizeof(*pCur) + c chName);161 pCur = xmalloc(sizeof(*pCur) + cwcName * sizeof(wchar_t)); 125 162 pCur->uHash = uHash; 126 pCur->c chName = cchName;163 pCur->cwcName = (unsigned)cwcName; 127 164 pCur->pNext = NULL; 128 165 pCur->uLastRef = ++g_uNow; 129 memcpy(pCur-> szName, pszExec, cchName + 1);130 pCur->hmod1 = LoadLibraryEx (pszExec, NULL, LOAD_LIBRARY_AS_DATAFILE);166 memcpy(pCur->wszName, pwszExec, (cwcName + 1) * sizeof(wchar_t)); 167 pCur->hmod1 = LoadLibraryExW(pwszExec, NULL, LOAD_LIBRARY_AS_DATAFILE); 131 168 if (pCur->hmod1 != NULL) 132 pCur->hmod2 = LoadLibraryEx (pszExec, NULL, DONT_RESOLVE_DLL_REFERENCES);169 pCur->hmod2 = LoadLibraryExW(pwszExec, NULL, DONT_RESOLVE_DLL_REFERENCES); 133 170 else 134 171 pCur->hmod2 = NULL; 135 172 136 *ppCur = pCur; 137 g_cCached++; 138 } 139 173 /* 174 * Insert it. 175 * Take into account that we might've been racing other threads, 176 * fortunately we don't evict anything from the cache. 177 */ 178 EnterCriticalSection(&g_CritSect); 179 if (*ppCur != NULL) 180 { 181 /* Find new end of chain and check for duplicate. */ 182 PEXECCACHEENTRY pCur2 = *ppCur; 183 while (pCur2) 184 { 185 if ( pCur->uHash == uHash 186 && pCur->cwcName == cwcName 187 && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t))) 188 break; 189 ppCur = &pCur->pNext; 190 pCur = pCur->pNext; 191 } 192 193 } 194 if (*ppCur == NULL) 195 { 196 *ppCur = pCur; 197 g_cCached++; 198 LeaveCriticalSection(&g_CritSect); 199 } 200 else 201 { 202 LeaveCriticalSection(&g_CritSect); 203 204 if (pCur->hmod1 != NULL) 205 FreeLibrary(pCur->hmod1); 206 if (pCur->hmod2 != NULL) 207 FreeLibrary(pCur->hmod2); 208 free(pCur); 209 } 210 } 211 212 extern void kmk_cache_exec_image_a(const char *pszExec) 213 { 214 wchar_t wszExec[260]; 215 int cwc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszExec, strlen(pszExec) + 1, wszExec, 260); 216 if (cwc > 0) 217 kmk_cache_exec_image_w(wszExec); 218 } 219 -
trunk/src/kmk/w32/subproc/sub_proc.c
r3140 r3195 40 40 # include <assert.h> 41 41 # include "kmkbuiltin.h" 42 extern void kmk_cache_exec_image (const char *); /* imagecache.c */42 extern void kmk_cache_exec_image_a(const char *); /* imagecache.c */ 43 43 #endif 44 44 … … 844 844 #ifdef KMK 845 845 if (exec_fname[0]) 846 kmk_cache_exec_image (exec_fname);846 kmk_cache_exec_image_a(exec_fname); 847 847 else if (exec_path) 848 kmk_cache_exec_image (exec_path);848 kmk_cache_exec_image_a(exec_path); 849 849 else if (argv[0]) 850 kmk_cache_exec_image (argv[0]);850 kmk_cache_exec_image_a(argv[0]); 851 851 852 852 switch (process_priority) { -
trunk/src/kmk/w32/winchildren.c
r3192 r3195 101 101 102 102 #include "nt/nt_child_inject_standard_handles.h" 103 104 #ifndef KMK_BUILTIN_STANDALONE 105 extern void kmk_cache_exec_image_w(const wchar_t *); /* imagecache.c */ 106 #endif 103 107 104 108 … … 805 809 * Commmon worker for waiting on a child process and retrieving the exit code. 806 810 * 811 * @returns Child exit code. 807 812 * @param pWorker The worker. 808 813 * @param pChild The child. … … 812 817 * associated with the worker. 813 818 */ 814 static voidmkWinChildcareWorkerWaitForProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, HANDLE hProcess,815 819 static int mkWinChildcareWorkerWaitForProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, HANDLE hProcess, 820 WCHAR const *pwszJob, BOOL fCatchOutput) 816 821 { 817 822 DWORD const msStart = GetTickCount(); … … 850 855 mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, TRUE /*fFlushing*/); 851 856 } 852 return ;857 return dwExitCode; 853 858 } 854 859 } … … 891 896 if (pChild->iExitCode == 0) 892 897 pChild->iExitCode = -4242; 893 return ;898 return pChild->iExitCode; 894 899 } 895 900 } … … 930 935 * @param pwszzEnvironment The enviornment block. 931 936 */ 932 static int mkWinChildcareWorkerCreateProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, WCHAR const *pwszImageName, 933 WCHAR const *pwszCommandLine, WCHAR const *pwszzEnvironment) 937 static int mkWinChildcareWorkerCreateProcess(PWINCHILDCAREWORKER pWorker, WCHAR const *pwszImageName, 938 WCHAR const *pwszCommandLine, WCHAR const *pwszzEnvironment, WCHAR const *pwszCwd, 939 BOOL pafReplace[3], HANDLE pahChild[3], BOOL fCatchOutput, HANDLE *phProcess) 934 940 { 935 941 PROCESS_INFORMATION ProcInfo; 936 942 STARTUPINFOW StartupInfo; 937 943 DWORD fFlags = CREATE_UNICODE_ENVIRONMENT; 938 BOOL const fHaveHandles = pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE 939 || pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE; 944 BOOL const fHaveHandles = pafReplace[0] | pafReplace[1] | pafReplace[2]; 940 945 BOOL fRet; 941 946 DWORD dwErr; … … 965 970 StartupInfo.cbReserved2 = 0; 966 971 if ( !fHaveHandles 967 && ! pChild->u.Process.fCatchOutput)972 && !fCatchOutput) 968 973 StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES; 969 974 else … … 999 1004 1000 1005 fRet = CreateProcessW((WCHAR *)pwszImageName, (WCHAR *)pwszCommandLine, NULL /*pProcSecAttr*/, NULL /*pThreadSecAttr*/, 1001 FALSE /*fInheritHandles*/, fFlags, (WCHAR *)pwszzEnvironment, NULL /*pwsz*/, &StartupInfo, &ProcInfo);1006 FALSE /*fInheritHandles*/, fFlags, (WCHAR *)pwszzEnvironment, pwszCwd, &StartupInfo, &ProcInfo); 1002 1007 dwErr = GetLastError(); 1003 1008 … … 1006 1011 #endif 1007 1012 if (fRet) 1008 pChild->u.Process.hProcess = ProcInfo.hProcess;1013 *phProcess = ProcInfo.hProcess; 1009 1014 else 1010 1015 { 1011 1016 fprintf(stderr, "CreateProcess(%ls) failed: %u\n", pwszImageName, dwErr); 1012 return pChild->iExitCode =(int)dwErr;1017 return (int)dwErr; 1013 1018 } 1014 1019 … … 1022 1027 * First do handle inhertiance as that's the most complicated. 1023 1028 */ 1024 if (fHaveHandles || pChild->u.Process.fCatchOutput) 1025 { 1026 char szErrMsg[128]; 1027 BOOL afReplace[3]; 1028 HANDLE ahChild[3]; 1029 1030 afReplace[0] = FALSE; 1031 ahChild[0] = INVALID_HANDLE_VALUE; 1032 if (fHaveHandles) 1033 { 1034 afReplace[1] = pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE; 1035 ahChild[1] = pChild->u.Process.hStdOut; 1036 afReplace[2] = pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE; 1037 ahChild[2] = pChild->u.Process.hStdErr; 1038 } 1039 else 1040 { 1041 afReplace[1] = TRUE; 1042 ahChild[1] = pWorker->StdOut.hPipeChild; 1043 afReplace[2] = TRUE; 1044 ahChild[2] = pWorker->StdErr.hPipeChild; 1045 } 1046 1047 dwErr = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahChild, szErrMsg, sizeof(szErrMsg)); 1029 if (fHaveHandles || fCatchOutput) 1030 { 1031 char szErrMsg[128]; 1032 if (fCatchOutput) 1033 { 1034 if (!pafReplace[1]) 1035 { 1036 pafReplace[1] = TRUE; 1037 pahChild[1] = pWorker->StdOut.hPipeChild; 1038 } 1039 if (!pafReplace[2]) 1040 { 1041 pafReplace[2] = TRUE; 1042 pahChild[2] = pWorker->StdErr.hPipeChild; 1043 } 1044 } 1045 dwErr = nt_child_inject_standard_handles(ProcInfo.hProcess, pafReplace, pahChild, szErrMsg, sizeof(szErrMsg)); 1048 1046 if (dwErr != 0) 1049 1047 fprintf(stderr, "%s\n", szErrMsg); … … 1094 1092 1095 1093 /* 1096 * Close unnecessary handles. 1097 */ 1098 mkWinChildcareWorkerCloseStandardHandles(pChild); 1094 * Close unnecessary handles and cache the image. 1095 */ 1099 1096 CloseHandle(ProcInfo.hThread); 1097 kmk_cache_exec_image_w(pwszImageName); 1098 return 0; 1099 } 1100 1101 /** 1102 * Converts a argument vector that has already been quoted correctly. 1103 * 1104 * The argument vector is typically the result of quote_argv(). 1105 * 1106 * @returns 0 on success, non-zero on failure. 1107 * @param papszArgs The argument vector to convert. 1108 * @param ppwszCommandLine Where to return the command line. 1109 */ 1110 static int mkWinChildcareWorkerConvertQuotedArgvToCommandline(char **papszArgs, WCHAR **ppwszCommandLine) 1111 { 1112 WCHAR *pwszCmdLine; 1113 WCHAR *pwszDst; 1114 1115 /* 1116 * Calc length the converted length. 1117 */ 1118 unsigned cwcNeeded = 1; 1119 unsigned i = 0; 1120 const char *pszSrc; 1121 while ((pszSrc = papszArgs[i]) != NULL) 1122 { 1123 int cwcThis = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, -1, NULL, 0); 1124 if (cwcThis > 0 || *pszSrc == '\0') 1125 cwcNeeded += cwcThis + 1; 1126 else 1127 { 1128 DWORD dwErr = GetLastError(); 1129 fprintf(stderr, _("MultiByteToWideChar failed to convert argv[%u] (%s): %u\n"), i, pszSrc, dwErr); 1130 return dwErr; 1131 } 1132 i++; 1133 } 1134 1135 /* 1136 * Allocate and do the conversion. 1137 */ 1138 pwszCmdLine = pwszDst = (WCHAR *)xmalloc(cwcNeeded * sizeof(WCHAR)); 1139 i = 0; 1140 while ((pszSrc = papszArgs[i]) != NULL) 1141 { 1142 int cwcThis; 1143 if (i > 0) 1144 { 1145 *pwszDst++ = ' '; 1146 cwcNeeded--; 1147 } 1148 1149 cwcThis = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, -1, pwszDst, cwcNeeded); 1150 if (!cwcThis && *pszSrc != '\0') 1151 { 1152 DWORD dwErr = GetLastError(); 1153 fprintf(stderr, _("MultiByteToWideChar failed to convert argv[%u] (%s): %u\n"), i, pszSrc, dwErr); 1154 free(pwszCmdLine); 1155 return dwErr; 1156 } 1157 if (cwcThis > 0 && pwszDst[cwcThis - 1] == '\0') 1158 cwcThis--; 1159 pwszDst += cwcThis; 1160 cwcNeeded -= cwcThis; 1161 i++; 1162 } 1163 *pwszDst++ = '\0'; 1164 1165 *ppwszCommandLine = pwszCmdLine; 1100 1166 return 0; 1101 1167 } … … 1707 1773 { 1708 1774 fprintf(stderr, "%s: not found!\n", pszArg0); 1709 //__debugbreak();1710 1775 dwErr = ERROR_FILE_NOT_FOUND; 1711 1776 } … … 1920 1985 if (rc == 0) 1921 1986 { 1922 rc = mkWinChildcareWorkerCreateProcess(pWorker, pChild, pwszImageName, pwszCommandLine, pwszzEnvironment); 1987 BOOL afReplace[3] = { FALSE, pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE, pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE }; 1988 HANDLE ahChild[3] = { INVALID_HANDLE_VALUE, pChild->u.Process.hStdOut, pChild->u.Process.hStdErr }; 1989 rc = mkWinChildcareWorkerCreateProcess(pWorker, pwszImageName, pwszCommandLine, pwszzEnvironment, 1990 NULL /*pwszCwd*/, afReplace, ahChild, pChild->u.Process.fCatchOutput, 1991 &pChild->u.Process.hProcess); 1992 mkWinChildcareWorkerCloseStandardHandles(pChild); 1923 1993 if (rc == 0) 1924 1994 { … … 1958 2028 { 1959 2029 PCKMKBUILTINENTRY pBuiltIn = pChild->u.BuiltIn.pBuiltIn; 1960 KMKBUILTINCTX Ctx = { pBuiltIn->uName.s.sz, pChild->pMkChild ? &pChild->pMkChild->output : NULL }; 2030 KMKBUILTINCTX Ctx = 2031 { 2032 pBuiltIn->uName.s.sz, 2033 pChild->pMkChild ? &pChild->pMkChild->output : NULL, 2034 pWorker, 2035 }; 1961 2036 if (pBuiltIn->uFnSignature == FN_SIG_MAIN) 1962 2037 pChild->iExitCode = pBuiltIn->u.pfnMain(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs, … … 1964 2039 else if (pBuiltIn->uFnSignature == FN_SIG_MAIN_SPAWNS) 1965 2040 pChild->iExitCode = pBuiltIn->u.pfnMainSpawns(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs, 1966 pChild->u.BuiltIn.papszEnv, &Ctx, pChild->pMkChild, NULL );2041 pChild->u.BuiltIn.papszEnv, &Ctx, pChild->pMkChild, NULL /*pPid*/); 1967 2042 else 1968 2043 { … … 2115 2190 PWINCHILD pTailExpect; 2116 2191 2192 pWorker->pCurChild = pChild; 2117 2193 switch (pChild->enmType) 2118 2194 { … … 2137 2213 assert(0); 2138 2214 } 2215 pWorker->pCurChild = NULL; 2139 2216 2140 2217 /* … … 2821 2898 } 2822 2899 2900 2901 /** 2902 * New interface used by redirect.c for spawning and waitin on a child. 2903 * 2904 * This interface is only used when kmk_builtin_redirect is already running on 2905 * a worker thread. 2906 * 2907 * @returns exit status. 2908 * @param pvWorker The worker instance. 2909 * @param pszExecutable The executable image to run. 2910 * @param papszArgs Argument vector. 2911 * @param fQuotedArgv Whether the argument vector is already quoted and 2912 * just need some space to be turned into a command 2913 * line. 2914 * @param papszEnvVars Environment vector. 2915 * @param pszCwd The working directory of the child. Optional. 2916 * @param pafReplace Which standard handles to replace. Maybe modified! 2917 * @param pahReplace The replacement handles. Maybe modified! 2918 * 2919 */ 2920 int MkWinChildBuiltInExecChild(void *pvWorker, const char *pszExecutable, char **papszArgs, BOOL fQuotedArgv, 2921 char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3]) 2922 { 2923 PWINCHILDCAREWORKER pWorker = (PWINCHILDCAREWORKER)pvWorker; 2924 WCHAR *pwszSearchPath = NULL; 2925 WCHAR *pwszzEnvironment = NULL; 2926 WCHAR *pwszCommandLine = NULL; 2927 WCHAR *pwszImageName = NULL; 2928 WCHAR *pwszCwd = NULL; 2929 BOOL fNeedShell = FALSE; 2930 int rc; 2931 assert(pWorker->uMagic == WINCHILDCAREWORKER_MAGIC); 2932 assert(pWorker->pCurChild != NULL && pWorker->pCurChild->uMagic == WINCHILD_MAGIC); 2933 2934 /* 2935 * Convert the CWD first since it's optional and we don't need to clean 2936 * up anything here if it fails. 2937 */ 2938 if (pszCwd) 2939 { 2940 size_t cchCwd = strlen(pszCwd); 2941 int cwcCwd = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszCwd, cchCwd + 1, NULL, 0); 2942 pwszCwd = xmalloc((cwcCwd + 1) * sizeof(WCHAR)); /* (+1 in case cwcCwd is 0) */ 2943 cwcCwd = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszCwd, cchCwd + 1, pwszCwd, cwcCwd + 1); 2944 if (!cwcCwd) 2945 { 2946 rc = GetLastError(); 2947 fprintf(stderr, _("MultiByteToWideChar failed to convert CWD (%s): %u\n"), pszCwd, (unsigned)rc); 2948 return rc; 2949 } 2950 } 2951 2952 /* 2953 * Before we search for the image, we convert the environment so we don't 2954 * have to traverse it twice to find the PATH. 2955 */ 2956 rc = mkWinChildcareWorkerConvertEnvironment(papszEnvVars ? papszEnvVars : environ, 0/*cbEnvStrings*/, 2957 &pwszzEnvironment, &pwszSearchPath); 2958 /* 2959 * Find the executable and maybe checking if it's a shell script, then 2960 * convert it to a command line. 2961 */ 2962 if (rc == 0) 2963 rc = mkWinChildcareWorkerFindImage(pszExecutable, pwszSearchPath, pwszzEnvironment, 2964 NULL /*pszNull*/, &pwszImageName, &fNeedShell); 2965 if (rc == 0) 2966 { 2967 assert(!fNeedShell); 2968 if (!fQuotedArgv) 2969 rc = mkWinChildcareWorkerConvertCommandline(papszArgs, 0 /*fFlags*/, &pwszCommandLine); 2970 else 2971 rc = mkWinChildcareWorkerConvertQuotedArgvToCommandline(papszArgs, &pwszCommandLine); 2972 2973 /* 2974 * Create the child process. 2975 */ 2976 if (rc == 0) 2977 { 2978 HANDLE hProcess; 2979 rc = mkWinChildcareWorkerCreateProcess(pWorker, pwszImageName, pwszCommandLine, pwszzEnvironment, 2980 pwszCwd, pafReplace, pahReplace, TRUE /*fCatchOutput*/, &hProcess); 2981 if (rc == 0) 2982 { 2983 /* 2984 * Wait for the child to complete. 2985 */ 2986 rc = mkWinChildcareWorkerWaitForProcess(pWorker, pWorker->pCurChild, hProcess, pwszImageName, 2987 TRUE /*fCatchOutput*/); 2988 CloseHandle(hProcess); 2989 } 2990 } 2991 } 2992 2993 free(pwszCwd); 2994 free(pwszCommandLine); 2995 free(pwszImageName); 2996 free(pwszzEnvironment); 2997 2998 return rc; 2999 } 3000 2823 3001 #endif /* CONFIG_NEW_WIN_CHILDREN */ 2824 3002 -
trunk/src/kmk/w32/winchildren.h
r3172 r3195 41 41 int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, pid_t *pPid); 42 42 int MkWinChildCreateRedirect(intptr_t hProcess, pid_t *pPid); 43 # ifdef DECLARE_HANDLE 44 int MkWinChildBuiltInExecChild(void *pvWorker, const char *pszExecutable, char **papszArgs, BOOL fQuotedArgv, 45 char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3]); 46 # endif 43 47 #endif 44 48 int MkWinChildKill(pid_t pid, int iSignal, struct child *pMkChild);
Note:
See TracChangeset
for help on using the changeset viewer.