Changeset 3313 for trunk/src/kWorker/kWorker.c
- Timestamp:
- Mar 16, 2020, 3:31:38 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kWorker/kWorker.c
r3200 r3313 195 195 196 196 197 /** 198 * Generate CRT slot wrapper functions. 199 */ 200 #define CRT_SLOT_FUNCTION_WRAPPER(a_RetTypeAndCallConv, a_FnName, a_aArgsDecl, a_aArgCall) \ 201 static a_RetTypeAndCallConv a_FnName##00 a_aArgsDecl { const unsigned iCrtSlot = 0; return a_FnName##_wrapped a_aArgCall; } \ 202 static a_RetTypeAndCallConv a_FnName##01 a_aArgsDecl { const unsigned iCrtSlot = 1; return a_FnName##_wrapped a_aArgCall; } \ 203 static a_RetTypeAndCallConv a_FnName##02 a_aArgsDecl { const unsigned iCrtSlot = 2; return a_FnName##_wrapped a_aArgCall; } \ 204 static a_RetTypeAndCallConv a_FnName##03 a_aArgsDecl { const unsigned iCrtSlot = 3; return a_FnName##_wrapped a_aArgCall; } \ 205 static a_RetTypeAndCallConv a_FnName##04 a_aArgsDecl { const unsigned iCrtSlot = 4; return a_FnName##_wrapped a_aArgCall; } \ 206 static a_RetTypeAndCallConv a_FnName##05 a_aArgsDecl { const unsigned iCrtSlot = 5; return a_FnName##_wrapped a_aArgCall; } \ 207 static a_RetTypeAndCallConv a_FnName##06 a_aArgsDecl { const unsigned iCrtSlot = 6; return a_FnName##_wrapped a_aArgCall; } \ 208 static a_RetTypeAndCallConv a_FnName##07 a_aArgsDecl { const unsigned iCrtSlot = 7; return a_FnName##_wrapped a_aArgCall; } \ 209 static a_RetTypeAndCallConv a_FnName##08 a_aArgsDecl { const unsigned iCrtSlot = 8; return a_FnName##_wrapped a_aArgCall; } \ 210 static a_RetTypeAndCallConv a_FnName##09 a_aArgsDecl { const unsigned iCrtSlot = 9; return a_FnName##_wrapped a_aArgCall; } \ 211 static a_RetTypeAndCallConv a_FnName##10 a_aArgsDecl { const unsigned iCrtSlot = 10; return a_FnName##_wrapped a_aArgCall; } \ 212 static a_RetTypeAndCallConv a_FnName##11 a_aArgsDecl { const unsigned iCrtSlot = 11; return a_FnName##_wrapped a_aArgCall; } \ 213 static a_RetTypeAndCallConv a_FnName##12 a_aArgsDecl { const unsigned iCrtSlot = 12; return a_FnName##_wrapped a_aArgCall; } \ 214 static a_RetTypeAndCallConv a_FnName##13 a_aArgsDecl { const unsigned iCrtSlot = 13; return a_FnName##_wrapped a_aArgCall; } \ 215 static a_RetTypeAndCallConv a_FnName##14 a_aArgsDecl { const unsigned iCrtSlot = 14; return a_FnName##_wrapped a_aArgCall; } \ 216 static a_RetTypeAndCallConv a_FnName##15 a_aArgsDecl { const unsigned iCrtSlot = 15; return a_FnName##_wrapped a_aArgCall; } \ 217 static a_RetTypeAndCallConv a_FnName##16 a_aArgsDecl { const unsigned iCrtSlot = 16; return a_FnName##_wrapped a_aArgCall; } \ 218 static a_RetTypeAndCallConv a_FnName##17 a_aArgsDecl { const unsigned iCrtSlot = 17; return a_FnName##_wrapped a_aArgCall; } \ 219 static a_RetTypeAndCallConv a_FnName##18 a_aArgsDecl { const unsigned iCrtSlot = 18; return a_FnName##_wrapped a_aArgCall; } \ 220 static a_RetTypeAndCallConv a_FnName##19 a_aArgsDecl { const unsigned iCrtSlot = 19; return a_FnName##_wrapped a_aArgCall; } \ 221 static a_RetTypeAndCallConv a_FnName##20 a_aArgsDecl { const unsigned iCrtSlot = 20; return a_FnName##_wrapped a_aArgCall; } \ 222 static a_RetTypeAndCallConv a_FnName##21 a_aArgsDecl { const unsigned iCrtSlot = 21; return a_FnName##_wrapped a_aArgCall; } \ 223 static a_RetTypeAndCallConv a_FnName##22 a_aArgsDecl { const unsigned iCrtSlot = 22; return a_FnName##_wrapped a_aArgCall; } \ 224 static a_RetTypeAndCallConv a_FnName##23 a_aArgsDecl { const unsigned iCrtSlot = 23; return a_FnName##_wrapped a_aArgCall; } \ 225 static a_RetTypeAndCallConv a_FnName##24 a_aArgsDecl { const unsigned iCrtSlot = 24; return a_FnName##_wrapped a_aArgCall; } \ 226 static a_RetTypeAndCallConv a_FnName##25 a_aArgsDecl { const unsigned iCrtSlot = 25; return a_FnName##_wrapped a_aArgCall; } \ 227 static a_RetTypeAndCallConv a_FnName##26 a_aArgsDecl { const unsigned iCrtSlot = 26; return a_FnName##_wrapped a_aArgCall; } \ 228 static a_RetTypeAndCallConv a_FnName##27 a_aArgsDecl { const unsigned iCrtSlot = 27; return a_FnName##_wrapped a_aArgCall; } \ 229 static a_RetTypeAndCallConv a_FnName##28 a_aArgsDecl { const unsigned iCrtSlot = 28; return a_FnName##_wrapped a_aArgCall; } \ 230 static a_RetTypeAndCallConv a_FnName##29 a_aArgsDecl { const unsigned iCrtSlot = 29; return a_FnName##_wrapped a_aArgCall; } \ 231 static a_RetTypeAndCallConv a_FnName##30 a_aArgsDecl { const unsigned iCrtSlot = 30; return a_FnName##_wrapped a_aArgCall; } \ 232 static a_RetTypeAndCallConv a_FnName##31 a_aArgsDecl { const unsigned iCrtSlot = 31; return a_FnName##_wrapped a_aArgCall; } \ 233 static const KUPTR a_FnName[] = \ 234 { \ 235 (KUPTR)a_FnName##00, \ 236 (KUPTR)a_FnName##01, \ 237 (KUPTR)a_FnName##02, \ 238 (KUPTR)a_FnName##03, \ 239 (KUPTR)a_FnName##04, \ 240 (KUPTR)a_FnName##05, \ 241 (KUPTR)a_FnName##06, \ 242 (KUPTR)a_FnName##07, \ 243 (KUPTR)a_FnName##08, \ 244 (KUPTR)a_FnName##09, \ 245 (KUPTR)a_FnName##10, \ 246 (KUPTR)a_FnName##11, \ 247 (KUPTR)a_FnName##12, \ 248 (KUPTR)a_FnName##13, \ 249 (KUPTR)a_FnName##14, \ 250 (KUPTR)a_FnName##15, \ 251 (KUPTR)a_FnName##16, \ 252 (KUPTR)a_FnName##17, \ 253 (KUPTR)a_FnName##18, \ 254 (KUPTR)a_FnName##19, \ 255 (KUPTR)a_FnName##20, \ 256 (KUPTR)a_FnName##21, \ 257 (KUPTR)a_FnName##22, \ 258 (KUPTR)a_FnName##23, \ 259 (KUPTR)a_FnName##24, \ 260 (KUPTR)a_FnName##25, \ 261 (KUPTR)a_FnName##26, \ 262 (KUPTR)a_FnName##27, \ 263 (KUPTR)a_FnName##28, \ 264 (KUPTR)a_FnName##29, \ 265 (KUPTR)a_FnName##30, \ 266 (KUPTR)a_FnName##31, \ 267 } 268 269 197 270 /********************************************************************************************************************************* 198 271 * Structures and Typedefs * … … 221 294 typedef struct KWMODULE 222 295 { 223 /** Pointer to the next image. */ 224 PKWMODULE pNext; 296 /** Pointer to the next image withe the same hash. */ 297 PKWMODULE pNextHash; 298 /** Pointer to the next image in the global list. */ 299 PKWMODULE pNextList; 225 300 /** The normalized path to the image. */ 226 301 const char *pszPath; … … 243 318 /** The of the loaded image bits. */ 244 319 KSIZE cbImage; 320 /** The CRT slot for this module, if applicable (KU8_MAX when not). */ 321 KU8 iCrtSlot; 322 /** Loop prevention when working the tree. */ 323 KBOOL fVisited; 324 /** HACK: Set if re-init is needed (fReInitOnMsPdbSrvEndpointChange). */ 325 KBOOL fNeedReInit; 326 /** HACK: Reinit when _MSPDBSRV_ENDPOINT_ changes, K_FALSE if not applicable. 327 * 1 if applicable but not yet used, 2 if used and have pszMsPdbSrvEndpoint. */ 328 KU8 fReInitOnMsPdbSrvEndpointChange; 329 /** HACK: The old _MSPDBSRV_ENDPOINT_ value. */ 330 char *pszMsPdbSrvEndpoint; 245 331 246 332 union … … 851 937 } KWSANDBOX; 852 938 939 940 /** A CRT slot. */ 941 typedef struct KWCRTSLOT 942 { 943 KU32 iSlot; 944 945 /** The CRT module data. */ 946 PKWMODULE pModule; 947 /** Pointer to the malloc function. */ 948 void * (__cdecl *pfnMalloc)(size_t); 949 950 } KWCRTSLOT; 951 typedef KWCRTSLOT *PKWCRTSLOT; 952 953 853 954 /** Replacement function entry. */ 854 955 typedef struct KWREPLACEMENTFUNCTION … … 860 961 /** The module name (optional). */ 861 962 const char *pszModule; 862 /** The replacement function or data address. */963 /** The replacement function, data address or CRT slot function array. */ 863 964 KUPTR pfnReplacement; 864 965 /** Only replace in the executable. 865 966 * @todo fix the reinitialization of non-native DLLs! */ 866 967 KBOOL fOnlyExe; 968 /** Set if pfnReplacement points to a CRT slot function array. */ 969 KBOOL fCrtSlotArray; 867 970 } KWREPLACEMENTFUNCTION; 868 971 typedef KWREPLACEMENTFUNCTION const *PCKWREPLACEMENTFUNCTION; … … 884 987 #endif 885 988 989 /** 990 * One test job (--full-test). 991 */ 992 typedef struct KWONETEST 993 { 994 /** Where this job originated. */ 995 const char *pszJobSrc; 996 /** The argument number it started with. */ 997 unsigned iJobSrc; 998 /** Set if virgin, clear if modified. */ 999 KBOOL fVirgin; 1000 1001 /** Number of runs to give it. */ 1002 unsigned cRuns; 1003 1004 /** @name kSubmitHandleJobUnpacked arguments 1005 * @{ */ 1006 const char *pszExecutable; 1007 const char *pszCwd; 1008 KU32 cArgs; 1009 const char **papszArgs; 1010 KU32 cEnvVars; 1011 const char **papszEnvVars; 1012 const char *pszSpecialEnv; 1013 KBOOL fWatcomBrainDamange; 1014 KBOOL fNoPchCaching; 1015 KU32 cPostCmdArgs; 1016 const char **papszPostCmdArgs; 1017 /** @} */ 1018 1019 /** Pointer to the next one. */ 1020 struct KWONETEST *pNext; 1021 } KWONETEST; 1022 /** Pointer to one test job. */ 1023 typedef KWONETEST *PKWONETEST; 1024 886 1025 887 1026 /********************************************************************************************************************************* … … 897 1036 static PKWMODULE g_pModPrevInLdBuf = NULL; 898 1037 1038 /** Module list head. */ 1039 static PKWMODULE g_pModuleHead = NULL; 1040 /** Where to insert the next module. */ 1041 static PKWMODULE *g_ppModuleNext = &g_pModuleHead; 1042 899 1043 /** Module hash table. */ 900 1044 static PKWMODULE g_apModules[127]; … … 911 1055 static PKWMODULE g_pModPendingTlsAlloc = NULL; 912 1056 1057 /** CRT slots. 1058 * @note The number of entires here must match CRT_SLOT_FUNCTION_WRAPPER. */ 1059 static KWCRTSLOT g_aCrtSlots[32]; 913 1060 914 1061 /** The file system cache. */ … … 926 1073 /** Whether we should restart the worker. */ 927 1074 static KBOOL g_fRestart = K_FALSE; 1075 1076 /** The process group this worker is tied to (--group option), -1 if none. */ 1077 static KI32 g_iProcessGroup = -1; 928 1078 929 1079 /** Whether control-C/SIGINT or Control-Break/SIGBREAK have been seen. */ … … 1046 1196 static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, 1047 1197 const char *pszSearchPath, PKWMODULE *ppMod); 1198 static PKWMODULE kwLdrModuleForLoadedNative(const char *pszName, KBOOL fEnsureCrtSlot); 1199 static char *kwSandboxDoGetEnvA(PKWSANDBOX pSandbox, const char *pchVar, KSIZE cchVar); 1048 1200 static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle, HANDLE hHandle); 1049 1201 #ifdef WITH_CONSOLE_OUTPUT_BUFFERING … … 1160 1312 fprintf(stderr, "kWorker: error: "); 1161 1313 vfprintf(stderr, pszFormat, va); 1314 fflush(stderr); /* In case it's a pipe. */ 1162 1315 1163 1316 SetLastError(dwSavedErr); … … 1624 1777 if (--pMod->cRefs == 0) 1625 1778 { 1626 /* Unlink it . */1779 /* Unlink it from the hash table. */ 1627 1780 if (!pMod->fExe) 1628 1781 { … … 1630 1783 unsigned idx = pMod->uHashPath % K_ELEMENTS(g_apModules); 1631 1784 if (g_apModules[idx] == pMod) 1632 g_apModules[idx] = pMod->pNext ;1785 g_apModules[idx] = pMod->pNextHash; 1633 1786 else 1634 1787 { 1635 1788 PKWMODULE pPrev = g_apModules[idx]; 1636 1789 kHlpAssert(pPrev != NULL); 1637 while (pPrev->pNext != pMod)1790 while (pPrev->pNextHash != pMod) 1638 1791 { 1639 pPrev = pPrev->pNext ;1792 pPrev = pPrev->pNextHash; 1640 1793 kHlpAssert(pPrev != NULL); 1641 1794 } 1642 pPrev->pNext = pMod->pNext; 1643 } 1795 pPrev->pNextHash = pMod->pNextHash; 1796 } 1797 } 1798 1799 /* Unlink it from the list. */ 1800 if (pMod != g_pModuleHead) 1801 { 1802 PKWMODULE pPrev = g_pModuleHead; 1803 while (pPrev) 1804 { 1805 if (pPrev->pNextList == pMod) 1806 { 1807 pPrev->pNextList = pMod->pNextList; 1808 if (!pMod->pNextList) 1809 g_ppModuleNext = &pPrev->pNextList; 1810 break; 1811 } 1812 pPrev = pPrev->pNextList; 1813 } 1814 kHlpAssert(pPrev != NULL); 1815 } 1816 else 1817 { 1818 g_pModuleHead = pMod->pNextList; 1819 if (!pMod->pNextList) 1820 g_ppModuleNext = &g_pModuleHead; 1644 1821 } 1645 1822 … … 1666 1843 } 1667 1844 1845 if (pMod->iCrtSlot != KU8_MAX) 1846 g_aCrtSlots[pMod->iCrtSlot].pModule = NULL; 1847 1848 if (pMod->pszMsPdbSrvEndpoint) 1849 { 1850 kHlpFree(pMod->pszMsPdbSrvEndpoint); 1851 pMod->pszMsPdbSrvEndpoint = NULL; 1852 } 1853 1668 1854 kHlpFree(pMod); 1669 1855 } … … 1681 1867 static PKWMODULE kwLdrModuleLink(PKWMODULE pMod) 1682 1868 { 1683 unsigned idx = pMod->uHashPath % K_ELEMENTS(g_apModules); 1684 pMod->pNext = g_apModules[idx]; 1685 g_apModules[idx] = pMod; 1869 if (!pMod->fExe) 1870 { 1871 unsigned idx = pMod->uHashPath % K_ELEMENTS(g_apModules); 1872 pMod->pNextHash = g_apModules[idx]; 1873 g_apModules[idx] = pMod; 1874 } 1875 1876 pMod->pNextList = NULL; 1877 *g_ppModuleNext = pMod; 1878 g_ppModuleNext = &pMod->pNextList; 1879 1686 1880 return pMod; 1687 1881 } … … 1748 1942 KU32 iThunk; 1749 1943 const char * const pszImport = (const char *)&pbImage[pImpDesc->Name]; 1944 PKWMODULE pImportMod = NULL; 1750 1945 PIMAGE_THUNK_DATA paThunks = (PIMAGE_THUNK_DATA)&pbImage[pImpDesc->FirstThunk]; 1751 1946 PIMAGE_THUNK_DATA paOrgThunks = (PIMAGE_THUNK_DATA)&pbImage[pImpDesc->OriginalFirstThunk]; … … 1818 2013 } 1819 2014 1820 paThunks[iThunk].u1.AddressOfData = g_aSandboxNativeReplacements[i].pfnReplacement; 2015 /* 2016 * Unslotted replacements are simple. 2017 */ 2018 if (!g_aSandboxNativeReplacements[i].fCrtSlotArray) 2019 paThunks[iThunk].u1.AddressOfData = g_aSandboxNativeReplacements[i].pfnReplacement; 2020 else 2021 { 2022 /* 2023 * Must find our module entry for this module, possibly creating one. 2024 */ 2025 if (!pImportMod) 2026 { 2027 pImportMod = kwLdrModuleForLoadedNative(pszImport, K_TRUE /*fEnsureCrtSlot*/); 2028 if (!pImportMod) 2029 { 2030 kwErrPrintf("Failed to get module '%s' when performing replacements on module '%s'!\n", 2031 pszImport, pMod->pszPath); 2032 break; 2033 } 2034 } 2035 paThunks[iThunk].u1.AddressOfData 2036 = ((KUPTR *)g_aSandboxNativeReplacements[i].pfnReplacement)[pImportMod->iCrtSlot]; 2037 } 1821 2038 break; 1822 2039 } … … 1859 2076 * Create the entry. 1860 2077 */ 1861 PKWMODULE pMod 2078 PKWMODULE pMod = (PKWMODULE)kHlpAllocZ(sizeof(*pMod) + cbPath + cbPath * 2 * sizeof(wchar_t)); 1862 2079 if (pMod) 1863 2080 { … … 1873 2090 pMod->hOurMod = (HMODULE)(KUPTR)pLdrMod->aSegments[0].MapAddress; 1874 2091 pMod->cbImage = (KSIZE)kLdrModSize(pLdrMod); 2092 pMod->iCrtSlot = KU8_MAX; 2093 pMod->fNeedReInit = K_FALSE; 2094 pMod->pszMsPdbSrvEndpoint = NULL; 2095 pMod->fReInitOnMsPdbSrvEndpointChange = kHlpStrNICompAscii(&pMod->pszPath[pMod->offFilename], TUPLE("mspdb")) == 0; 1875 2096 1876 2097 if (fDoReplacements) … … 1906 2127 */ 1907 2128 PKLDRMOD pLdrMod; 1908 int rc = kLdrModOpenNative(pszPath, &pLdrMod);2129 int rc = kLdrModOpenNative(pszPath, KLDRMOD_OPEN_FLAGS_NATIVE_ALLOW_INIT_TERM, &pLdrMod); 1909 2130 if (rc == 0) 1910 2131 { … … 2267 2488 pMod->fNative = K_FALSE; 2268 2489 pMod->pLdrMod = pLdrMod; 2269 pMod->u.Manual.cImpMods = (KU32)cImports; 2490 pMod->iCrtSlot = KU8_MAX; 2491 pMod->fNeedReInit = K_FALSE; 2492 pMod->fReInitOnMsPdbSrvEndpointChange = K_FALSE; 2493 pMod->pszMsPdbSrvEndpoint = NULL; 2494 pMod->u.Manual.cImpMods = (KU32)cImports; 2270 2495 #if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64) 2271 2496 pMod->u.Manual.fRegisteredFunctionTable = K_FALSE; … … 2310 2535 */ 2311 2536 pMod->hOurMod = (HMODULE)pMod->u.Manual.pbLoad; 2312 if (!fExe) 2313 kwLdrModuleLink(pMod); 2537 kwLdrModuleLink(pMod); 2314 2538 KW_LOG(("New module: %p LB %#010x %s (kLdr)\n", 2315 2539 pMod->u.Manual.pbLoad, pMod->cbImage, pMod->pszPath)); … … 2646 2870 && kHlpStrComp(pMod->pszPath, szNormPath) == 0) 2647 2871 return kwLdrModuleRetain(pMod); 2648 pMod = pMod->pNext ;2872 pMod = pMod->pNextHash; 2649 2873 } while (pMod); 2650 2874 } … … 2776 3000 *ppMod = NULL; 2777 3001 return KERR_GENERAL_FAILURE; 3002 } 3003 3004 3005 /** 3006 * Creates a CRT slot for the given module. 3007 * 3008 * @returns 0 on success, non-zero on failure. 3009 * @param pModule The module. 3010 */ 3011 static int kwLdrModuleCreateCrtSlot(PKWMODULE pModule) 3012 { 3013 KSIZE iSlot; 3014 kHlpAssert(pModule->iCrtSlot == KU8_MAX); 3015 for (iSlot = 0; iSlot < K_ELEMENTS(g_aCrtSlots); iSlot++) 3016 if (g_aCrtSlots[iSlot].pModule == NULL) 3017 { 3018 KLDRADDR uAddr; 3019 int rc; 3020 3021 /* Do the linking: */ 3022 g_aCrtSlots[iSlot].pModule = pModule; 3023 g_aCrtSlots[iSlot].iSlot = (KU32)iSlot; 3024 pModule->iCrtSlot = (KU8)iSlot; 3025 3026 /* resolve symbols: */ 3027 rc = kLdrModQuerySymbol(pModule->pLdrMod, NULL /*pvBits*/, KLDRMOD_BASEADDRESS_MAP, KU32_MAX, "malloc", 6, 3028 NULL /*pvszVersion*/, NULL /*pfnGetForwarder*/, NULL /*pvUser*/, &uAddr, NULL); 3029 *(KUPTR *)&g_aCrtSlots[iSlot].pfnMalloc = rc == 0 ? (KUPTR)uAddr : 0; 3030 if (rc != 0) 3031 kwErrPrintf("Failed to resolved 'malloc' in '%s': %d\n", pModule->pszPath, rc); 3032 3033 return 0; 3034 } 3035 kwErrPrintf("Out of CRT slots!\n"); 3036 return KERR_NO_MEMORY; 3037 } 3038 3039 3040 /** 3041 * Locates the module structure for an already loaded native module. 3042 * 3043 * This will create a module structure if needed. 3044 * 3045 * @returns Pointer to the module structure on success, NULL on failure. 3046 * @param pszName The name of the module. 3047 * @param fEnsureCrtSlot Whether to ensure that it has a valid CRT slot. 3048 */ 3049 static PKWMODULE kwLdrModuleForLoadedNative(const char *pszName, KBOOL fEnsureCrtSlot) 3050 { 3051 /* 3052 * Locate the module and get a normalized path for it. 3053 */ 3054 HANDLE hModule = GetModuleHandleA(pszName); 3055 if (hModule) 3056 { 3057 char szModPath[1024]; 3058 if (GetModuleFileNameA(hModule, szModPath, sizeof(szModPath)) > 0) 3059 { 3060 char szNormPath[1024]; 3061 int rc = kwPathNormalize(szModPath, szNormPath, sizeof(szNormPath)); 3062 if (rc == 0) 3063 { 3064 /* 3065 * Hash the path and look it up. 3066 */ 3067 KU32 uHashPath; 3068 KSIZE const cchPath = kwStrHashEx(szNormPath, &uHashPath); 3069 unsigned idxHash = uHashPath % K_ELEMENTS(g_apModules); 3070 PKWMODULE pMod = g_apModules[idxHash]; 3071 if (pMod) 3072 { 3073 do 3074 { 3075 if ( pMod->uHashPath == uHashPath 3076 && kHlpStrComp(pMod->pszPath, szNormPath) == 0) 3077 { 3078 kwLdrModuleRetain(pMod); 3079 break; 3080 } 3081 pMod = pMod->pNextHash; 3082 } while (pMod); 3083 } 3084 3085 /* 3086 * If not in the hash table, so create a module entry. 3087 */ 3088 if (!pMod) 3089 { 3090 PKLDRMOD pLdrMod; 3091 rc = kLdrModOpenNativeByHandle((KUPTR)hModule, KLDRMOD_OPEN_FLAGS_NATIVE_ALLOW_INIT_TERM, &pLdrMod); 3092 if (rc == 0) 3093 { 3094 pMod = kwLdrModuleCreateForNativekLdrModule(pLdrMod, szNormPath, cchPath + 1, uHashPath, 3095 K_FALSE /*fDoReplacements*/); 3096 if (!pMod) 3097 { 3098 kLdrModClose(pLdrMod); 3099 kwErrPrintf("out of memory\n"); 3100 } 3101 } 3102 else 3103 kwErrPrintf("kLdrModOpenNativeByHandle failed for %p / '%s': %d\n", hModule, pszName, rc); 3104 } 3105 if (pMod) 3106 { 3107 /* 3108 * Create a CRT slot for the module if necessary. 3109 */ 3110 if (!fEnsureCrtSlot || pMod->iCrtSlot != KU8_MAX) 3111 return pMod; 3112 rc = kwLdrModuleCreateCrtSlot(pMod); 3113 if (rc == 0) 3114 return pMod; 3115 kwLdrModuleRelease(pMod); 3116 } 3117 } 3118 else 3119 kwErrPrintf("kwPathNormalize failed for '%s' (%s): %u!\n", szModPath, pszName, GetLastError()); 3120 } 3121 else 3122 kwErrPrintf("GetModuleFileNameA failed for '%s': %u!\n", pszName, GetLastError()); 3123 } 3124 else 3125 kwErrPrintf("Module '%s' was not found by GetModuleHandleA!\n", pszName); 3126 return NULL; 2778 3127 } 2779 3128 … … 2942 3291 pMod->u.Manual.enmState = KWMODSTATE_INIT_FAILED; 2943 3292 } 3293 } 3294 /* 3295 * Special hack to disconnect mspdbXXX.dll from mspdbsrv.exe when 3296 * _MSPDBSRV_ENDPOINT_ changes value. 3297 */ 3298 else if (pMod->fNeedReInit) 3299 { 3300 int rc2; 3301 KWLDR_LOG(("kwLdrModuleInitTree: mspdb re-init hack: %s\n", pMod->pszPath)); 3302 //fprintf(stderr, "%d: kwLdrModuleInitTree: mspdb re-init hack: %s\n", getpid(), kwSandboxDoGetEnvA(&g_Sandbox, TUPLE("_MSPDBSRV_ENDPOINT_"))); fflush(stderr); 3303 rc = kLdrModCallTerm(pMod->pLdrMod, pMod->u.Manual.pbLoad, (KUPTR)pMod->hOurMod); 3304 rc2 = kLdrModCallInit(pMod->pLdrMod, pMod->u.Manual.pbLoad, (KUPTR)pMod->hOurMod); 3305 if (!rc && !rc2) 3306 { /* likely */ } 3307 else 3308 { 3309 kwErrPrintf("Re-init of '%s' failed: rc=%d rc2=%d\n", pMod->pszPath, rc, rc2); 3310 if (rc2 && !rc) 3311 rc = rc2; 3312 } 3313 pMod->fNeedReInit = K_FALSE; 2944 3314 } 2945 3315 return rc; … … 4586 4956 4587 4957 4958 /** CRT - _wdupenv_s() (see _tdupenv_s(). */ 4959 static errno_t __cdecl kwSandbox_msvcrt__wdupenv_s_wrapped(wchar_t **ppwszValue, size_t *pcwcValue, const wchar_t *pwszVarName, 4960 PKWCRTSLOT pSlot) 4961 { 4962 errno_t rc; 4963 wchar_t *pwszValue; 4964 kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread); 4965 4966 if (ppwszValue) 4967 { 4968 pwszValue = kwSandboxDoGetEnvW(&g_Sandbox, pwszVarName, wcslen(pwszVarName)); 4969 if (pwszValue) 4970 { 4971 size_t cwcValue = wcslen(pwszValue); 4972 wchar_t *pwszDst = pSlot->pfnMalloc ? (wchar_t *)pSlot->pfnMalloc((cwcValue + 1) * sizeof(wchar_t)) : NULL; 4973 if (pwszDst) 4974 { 4975 memcpy(pwszDst, pwszValue, cwcValue * sizeof(wchar_t)); 4976 pwszDst[cwcValue] = '\0'; 4977 *ppwszValue = pwszDst; 4978 if (pcwcValue) 4979 *pcwcValue = cwcValue; 4980 rc = 0; 4981 } 4982 else 4983 { 4984 *ppwszValue = NULL; 4985 if (pcwcValue) 4986 *pcwcValue = 0; 4987 rc = ENOMEM; 4988 } 4989 } 4990 else 4991 { 4992 *ppwszValue = NULL; 4993 if (pcwcValue) 4994 *pcwcValue = 0; 4995 rc = 0; 4996 } 4997 KW_LOG(("_wdupenv_s(,,%ls) -> %d '%ls'\n", pwszVarName, rc, *ppwszValue ? *ppwszValue : L"<null>")); 4998 //fprintf(stderr, "%d: _wdupenv_s(,,%ls) -> %d '%ls'\n", getpid(), pwszVarName, rc, *ppwszValue ? *ppwszValue : L"<null>"); fflush(stderr); // HACKING 4999 } 5000 else 5001 { 5002 /* 5003 * Warning! If mspdb100.dll ends up here, it won't reinitialize the event name 5004 * and continue to use the one it constructed when _MSPDBSRV_ENDPOINT_ 5005 * was set to a value. 5006 */ 5007 if (pcwcValue) 5008 *pcwcValue = 0; 5009 rc = EINVAL; 5010 KW_LOG(("_wdupenv_s(,,%ls) -> EINVAL\n", pwszVarName)); 5011 //fprintf(stderr, "%d: _wdupenv_s(,,%ls) -> EINVAL\n", getpid(), pwszVarName); fflush(stderr); // HACKING 5012 } 5013 return rc; 5014 } 5015 CRT_SLOT_FUNCTION_WRAPPER(errno_t __cdecl, kwSandbox_msvcrt__wdupenv_s, 5016 (wchar_t **ppwszValue, size_t *pcwcValue, const wchar_t *pwszVarName), 5017 (ppwszValue, pcwcValue, pwszVarName, &g_aCrtSlots[iCrtSlot])); 5018 5019 4588 5020 4589 5021 /* … … 4665 5097 return pDynLoad->hmod; 4666 5098 } 4667 pMod = pMod->pNext ;5099 pMod = pMod->pNextHash; 4668 5100 } while (pMod); 4669 5101 } … … 4677 5109 { 4678 5110 PKLDRMOD pLdrMod; 4679 int rc = kLdrModOpenNativeByHandle((KUPTR)hmod, &pLdrMod);5111 int rc = kLdrModOpenNativeByHandle((KUPTR)hmod, KLDRMOD_OPEN_FLAGS_NATIVE_ALLOW_INIT_TERM, &pLdrMod); 4680 5112 if (rc == 0) 4681 5113 { … … 7790 8222 7791 8223 /* 7792 * Flush the two line buffer, the the combined buffer.8224 * Flush the two line buffer, then the combined buffer. 7793 8225 */ 7794 8226 kwSandboxConsoleFinalFlushLineBuf(pSandbox, &pSandbox->StdErr, "StdErr"); … … 9508 9940 { TUPLE("_amsg_exit"), NULL, (KUPTR)kwSandbox_msvcrt__amsg_exit }, 9509 9941 { TUPLE("terminate"), NULL, (KUPTR)kwSandbox_msvcrt_terminate }, 9942 { TUPLE("_wdupenv_s"), NULL, (KUPTR)kwSandbox_msvcrt__wdupenv_s, K_FALSE /*fOnlyExe*/, K_TRUE /*fCrtSlotArray*/ }, 9510 9943 9511 9944 #if 0 /* used by mspdbXXX.dll */ … … 9604 10037 9605 10038 /** 10039 * Resets the KWMODULE::fVisited flag for _all_ known modules. 10040 */ 10041 static void kwSandboxResetModuleVisited(void) 10042 { 10043 PKWMODULE pMod = g_pModuleHead; 10044 while (pMod) 10045 { 10046 pMod->fVisited = K_FALSE; 10047 pMod = pMod->pNextList; 10048 } 10049 } 10050 10051 10052 /** 9606 10053 * Used by kwSandboxExec to reset the state of the module tree. 9607 10054 * … … 9612 10059 static void kwSandboxResetModuleState(PKWMODULE pMod) 9613 10060 { 9614 if ( !pMod->fNative 9615 && pMod->u.Manual.enmState != KWMODSTATE_NEEDS_BITS) 9616 { 9617 KSIZE iImp; 10061 KWLDR_LOG(("kwSandboxResetModuleState: %d %d %s\n", pMod->fNative, pMod->fVisited, pMod->pszPath)); 10062 if (!pMod->fNative) 10063 { 9618 10064 pMod->u.Manual.enmState = KWMODSTATE_NEEDS_BITS; 9619 iImp = pMod->u.Manual.cImpMods; 9620 while (iImp-- > 0) 9621 kwSandboxResetModuleState(pMod->u.Manual.apImpMods[iImp]); 10065 if (!pMod->fVisited) /* Avoid loops. */ 10066 { 10067 KSIZE iImp; 10068 pMod->fVisited = K_TRUE; 10069 iImp = pMod->u.Manual.cImpMods; 10070 while (iImp-- > 0) 10071 kwSandboxResetModuleState(pMod->u.Manual.apImpMods[iImp]); 10072 } 10073 } 10074 /* Hack: Re-init mspdbXXX.dll when we want to use a different mspdbsrv.exe instance. */ 10075 else if (pMod->fReInitOnMsPdbSrvEndpointChange) 10076 { 10077 const char *pszValue = kwSandboxDoGetEnvA(&g_Sandbox, TUPLE("_MSPDBSRV_ENDPOINT_")); 10078 if (pMod->fReInitOnMsPdbSrvEndpointChange == 1) 10079 { 10080 pMod->fReInitOnMsPdbSrvEndpointChange = 2; 10081 pMod->pszMsPdbSrvEndpoint = pszValue ? kHlpStrDup(pszValue) : NULL; 10082 KWLDR_LOG(("Not re-initing '%s': first time used (_MSPDBSRV_ENDPOINT_ is '%s')\n", 10083 pMod->pszPath, pszValue ? pszValue : "<null>")); 10084 } 10085 else if ( (pszValue == NULL && pMod->pszMsPdbSrvEndpoint == NULL) 10086 || (pszValue != NULL && pMod->pszMsPdbSrvEndpoint != NULL && kHlpStrComp(pszValue, pMod->pszMsPdbSrvEndpoint) == 0)) 10087 KWLDR_LOG(("Not re-initing '%s': _MSPDBSRV_ENDPOINT_ unchanged ('%s')\n", 10088 pMod->pszPath, pszValue ? pszValue : "<null>")); 10089 else 10090 { 10091 KWLDR_LOG(("Re-initing '%s': _MSPDBSRV_ENDPOINT_ changed from '%s' to '%s'\n", pMod->pszPath, 10092 pMod->pszMsPdbSrvEndpoint ? pMod->pszMsPdbSrvEndpoint : "<null>", pszValue ? pszValue : "<null>")); 10093 kHlpFree(pMod->pszMsPdbSrvEndpoint); 10094 if (pszValue != NULL) 10095 pMod->pszMsPdbSrvEndpoint = kHlpStrDup(pszValue); 10096 else 10097 pMod->pszMsPdbSrvEndpoint = NULL; 10098 pMod->fNeedReInit = K_TRUE; 10099 } 9622 10100 } 9623 10101 } … … 10207 10685 * Do module initialization. 10208 10686 */ 10687 kwSandboxResetModuleVisited(); 10209 10688 kwSandboxResetModuleState(pTool->u.Sandboxed.pExe); 10210 10689 rc = kwLdrModuleInitTree(pTool->u.Sandboxed.pExe); … … 10292 10771 #endif 10293 10772 kwSandboxCleanup(&g_Sandbox); 10773 /** @todo Flush sandboxed native CRTs too. */ 10294 10774 } 10295 10775 else … … 10323 10803 } 10324 10804 10325 return kwErrPrintfRc(42 + 5 , "Unknown post command: '%s'\n", pszCmd); 10805 return kwErrPrintfRc(42 + 5, "Unknown post command: '%s'\n", pszCmd); 10806 } 10807 10808 10809 /** 10810 * Helper for kSubmitHandleSpecialEnvVar that gets the current process group. 10811 */ 10812 static unsigned kwGetCurrentProcessorGroup(void) 10813 { 10814 typedef BOOL (WINAPI *PFNGETTHREADGROUPAFFINITY)(HANDLE, GROUP_AFFINITY *); 10815 HMODULE hmodKernel32 = GetModuleHandleW(L"KERNEL32.DLL"); 10816 PFNGETTHREADGROUPAFFINITY pfnGetter = (PFNGETTHREADGROUPAFFINITY)GetProcAddress(hmodKernel32, "GetThreadGroupAffinity"); 10817 if (pfnGetter) 10818 { 10819 GROUP_AFFINITY GroupAffinity; 10820 memset(&GroupAffinity, 0, sizeof(GroupAffinity)); 10821 if (pfnGetter(GetCurrentThread(), &GroupAffinity)) 10822 return GroupAffinity.Group; 10823 } 10824 return 0; 10825 } 10826 10827 10828 /** 10829 * Helper for kSubmitHandleSpecialEnvVar that gets the current process group. 10830 */ 10831 static KSIZE kwGetCurrentAuthenticationIdAsString(char *pszValue) 10832 { 10833 KSIZE cchRet = 0; 10834 HANDLE hToken; 10835 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) 10836 { 10837 DWORD cbRet; 10838 TOKEN_STATISTICS TokenStats; 10839 memset(&TokenStats, 0, sizeof(TokenStats)); 10840 if (GetTokenInformation(hToken, TokenStatistics, &TokenStats, sizeof(TokenStats), &cbRet)) 10841 cchRet = sprintf(pszValue, "%" KX64_PRI, 10842 ((KU64)TokenStats.AuthenticationId.HighPart << 32) | TokenStats.AuthenticationId.LowPart); 10843 else 10844 kwErrPrintf("GetTokenInformation/TokenStatistics failed: %u\n", GetLastError()); 10845 CloseHandle(hToken); 10846 } 10847 else 10848 kwErrPrintf("OpenProcessToken failed: %u\n", GetLastError()); 10849 return cchRet; 10850 } 10851 10852 10853 /** 10854 * Look for and expand the special environment variable. 10855 * 10856 * We the special variable contains elements like "@@VAR_NAME@@" that kmk 10857 * couldn't accuratly determine. Currently the following variables are 10858 * implemented: 10859 * - "@@PROCESSOR_GROUP@@" - The processor group number. 10860 * - "@@AUTHENTICATION_ID@@" - The authentication ID from the process token. 10861 * - "@@PID@@" - The kWorker process ID. 10862 * - "@@@@" - Escaped "@@". 10863 * - "@@DEBUG_COUNTER@@" - An ever increasing counter (starts at zero). 10864 */ 10865 static int kSubmitHandleSpecialEnvVar(KU32 cEnvVars, const char **papszEnvVars, const char *pszSpecialEnv, char **ppszToFree) 10866 { 10867 KSIZE const cchSpecialEnv = kHlpStrLen(pszSpecialEnv); 10868 KU32 i = cEnvVars; 10869 while (i-- > 0) 10870 if ( kHlpStrNComp(papszEnvVars[i], pszSpecialEnv, cchSpecialEnv) == 0 10871 && papszEnvVars[i][cchSpecialEnv] == '=') 10872 { 10873 /* We will expand stuff like @@NAME@@ */ 10874 const char *pszValue = papszEnvVars[i]; 10875 KSIZE offDst = 0; 10876 char szTmp[1024]; 10877 for (;;) 10878 { 10879 const char *pszAt = kHlpStrChr(pszValue, '@'); 10880 while (pszAt && pszAt[1] != '@') 10881 pszAt = kHlpStrChr(pszAt + 1, '@'); 10882 if (pszAt) 10883 { 10884 KSIZE cchSrc = pszAt - pszValue; 10885 if (offDst + cchSrc < sizeof(szTmp)) 10886 { 10887 char szSrc[64]; 10888 10889 kHlpMemCopy(&szTmp[offDst], pszValue, cchSrc); 10890 offDst += cchSrc; 10891 pszValue = pszAt + 2; 10892 10893 if (kHlpStrNComp(pszValue, "PROCESS_GROUP@@", 15) == 0) 10894 { 10895 pszValue += 15; 10896 if (g_iProcessGroup == -1) 10897 g_iProcessGroup = kwGetCurrentProcessorGroup(); 10898 cchSrc = sprintf(szSrc, "%u", g_iProcessGroup); 10899 } 10900 else if (kHlpStrNComp(pszValue, "AUTHENTICATION_ID@@", 19) == 0) 10901 { 10902 pszValue += 19; 10903 cchSrc = kwGetCurrentAuthenticationIdAsString(szSrc); 10904 } 10905 else if (kHlpStrNComp(pszValue, "PID@@", 5) == 0) 10906 { 10907 pszValue += 5; 10908 cchSrc = sprintf(szSrc, "%d", getpid()); 10909 } 10910 else if (kHlpStrNComp(pszValue, "@@", 2) == 0) 10911 { 10912 pszValue += 2; 10913 szSrc[0] = '@'; 10914 szSrc[1] = '@'; 10915 szSrc[2] = '\0'; 10916 cchSrc = 2; 10917 } 10918 else if (kHlpStrNComp(pszValue, "DEBUG_COUNTER@@", 15) == 0) 10919 { 10920 static unsigned int s_iCounter = 0; 10921 pszValue += 15; 10922 cchSrc = sprintf(szSrc, "%u", s_iCounter++); 10923 } 10924 else 10925 return kwErrPrintfRc(42 + 6, "Special environment variable contains unknown reference: '%s'!\n", 10926 pszValue - 2); 10927 if (offDst + cchSrc < sizeof(szTmp)) 10928 { 10929 kHlpMemCopy(&szTmp[offDst], szSrc, cchSrc); 10930 offDst += cchSrc; 10931 continue; 10932 } 10933 } 10934 } 10935 else 10936 { 10937 KSIZE cchSrc = kHlpStrLen(pszValue); 10938 if (offDst + cchSrc < sizeof(szTmp)) 10939 { 10940 kHlpMemCopy(&szTmp[offDst], pszValue, cchSrc); 10941 offDst += cchSrc; 10942 break; 10943 } 10944 } 10945 return kwErrPrintfRc(42 + 6, "Special environment variable value too long!\n"); 10946 } 10947 szTmp[offDst] = '\0'; 10948 10949 /* Return a copy of it: */ 10950 papszEnvVars[i] = *ppszToFree = kHlpDup(szTmp, offDst + 1); 10951 if (papszEnvVars[i]) 10952 { 10953 SetEnvironmentVariableA(pszSpecialEnv, kHlpStrChr(papszEnvVars[i], '=') + 1); /* hack */ 10954 return 0; 10955 } 10956 return kwErrPrintfRc(42 + 6, "Special environment variable: out of memory\n"); 10957 } 10958 10959 return kwErrPrintfRc(42 + 6, "Special environment variable not found: '%s'\n", pszSpecialEnv); 10326 10960 } 10327 10961 … … 10338 10972 * @param cEnvVars The number of environment variables. 10339 10973 * @param papszEnvVars The environment vector. 10974 * @param pszSpecialEnv Name of special environment variable that 10975 * requires selective expansion here. 10340 10976 * @param fNoPchCaching Whether to disable precompiled header file 10341 10977 * caching. Avoid trouble when creating them. … … 10345 10981 static int kSubmitHandleJobUnpacked(const char *pszExecutable, const char *pszCwd, 10346 10982 KU32 cArgs, const char **papszArgs, KBOOL fWatcomBrainDamange, 10347 KU32 cEnvVars, const char **papszEnvVars, KBOOL fNoPchCaching,10348 K U32 cPostCmdArgs, const char **papszPostCmdArgs)10983 KU32 cEnvVars, const char **papszEnvVars, const char *pszSpecialEnv, 10984 KBOOL fNoPchCaching, KU32 cPostCmdArgs, const char **papszPostCmdArgs) 10349 10985 { 10350 10986 int rcExit; 10351 10987 PKWTOOL pTool; 10988 char *pszSpecialEnvFree = NULL; 10352 10989 10353 10990 KW_LOG(("\n\nkSubmitHandleJobUnpacked: '%s' in '%s' cArgs=%u cEnvVars=%u cPostCmdArgs=%u\n", … … 10363 11000 #endif 10364 11001 g_cJobs++; 11002 11003 /* 11004 * Expand pszSpecialEnv if present. 11005 */ 11006 if (*pszSpecialEnv) 11007 { 11008 rcExit = kSubmitHandleSpecialEnvVar(cEnvVars, papszEnvVars, pszSpecialEnv, &pszSpecialEnvFree); 11009 if (!rcExit) 11010 { /* likely */ } 11011 else 11012 return rcExit; 11013 } 10365 11014 10366 11015 /* … … 10434 11083 else 10435 11084 rcExit = 42 + 1; 11085 if (pszSpecialEnvFree) 11086 { 11087 SetEnvironmentVariableA(pszSpecialEnv, NULL); /* hack */ 11088 kHlpFree(pszSpecialEnvFree); 11089 } 10436 11090 return rcExit; 10437 11091 } … … 10544 11198 cbMsg -= 2; 10545 11199 10546 /* Post command argument count (can be zero). */10547 if (cbMsg >= sizeof(KU32))11200 /* Name of special enviornment variable requiring selective expansion. */ 11201 if (cbMsg >= 1) 10548 11202 { 10549 KU32 cPostCmdArgs; 10550 kHlpMemCopy(&cPostCmdArgs, pszMsg, sizeof(cPostCmdArgs)); 10551 pszMsg += sizeof(cPostCmdArgs); 10552 cbMsg -= sizeof(cPostCmdArgs); 10553 10554 if (cPostCmdArgs >= 0 && cPostCmdArgs < 32) 11203 const char *pszSpecialEnv = pszMsg; 11204 cbTmp = kHlpStrLen(pszMsg); 11205 pszMsg += cbTmp + 1; 11206 cbMsg -= K_MIN(cbMsg, cbTmp + 1); 11207 11208 /* Post command argument count (can be zero). */ 11209 if (cbMsg >= sizeof(KU32)) 10555 11210 { 10556 char const *apszPostCmdArgs[32+1]; 10557 for (i = 0; i < cPostCmdArgs; i++) 11211 KU32 cPostCmdArgs; 11212 kHlpMemCopy(&cPostCmdArgs, pszMsg, sizeof(cPostCmdArgs)); 11213 pszMsg += sizeof(cPostCmdArgs); 11214 cbMsg -= sizeof(cPostCmdArgs); 11215 11216 if (cPostCmdArgs >= 0 && cPostCmdArgs < 32) 10558 11217 { 10559 apszPostCmdArgs[i] = pszMsg; 10560 cbTmp = kHlpStrLen(pszMsg) + 1; 10561 pszMsg += cbTmp; 10562 if ( cbTmp < cbMsg 10563 || (cbTmp == cbMsg && i + 1 == cPostCmdArgs)) 10564 cbMsg -= cbTmp; 11218 char const *apszPostCmdArgs[32+1]; 11219 for (i = 0; i < cPostCmdArgs; i++) 11220 { 11221 apszPostCmdArgs[i] = pszMsg; 11222 cbTmp = kHlpStrLen(pszMsg) + 1; 11223 pszMsg += cbTmp; 11224 if ( cbTmp < cbMsg 11225 || (cbTmp == cbMsg && i + 1 == cPostCmdArgs)) 11226 cbMsg -= cbTmp; 11227 else 11228 { 11229 cbMsg = KSIZE_MAX; 11230 break; 11231 } 11232 } 11233 if (cbMsg == 0) 11234 { 11235 apszPostCmdArgs[cPostCmdArgs] = NULL; 11236 11237 /* 11238 * The next step. 11239 */ 11240 rcExit = kSubmitHandleJobUnpacked(pszExecutable, pszCwd, 11241 cArgs, papszArgs, fWatcomBrainDamange, 11242 cEnvVars, papszEnvVars, pszSpecialEnv, 11243 fNoPchCaching, 11244 cPostCmdArgs, apszPostCmdArgs); 11245 } 11246 else if (cbMsg == KSIZE_MAX) 11247 kwErrPrintf("Detected bogus message unpacking post command and its arguments!\n"); 10565 11248 else 10566 { 10567 cbMsg = KSIZE_MAX; 10568 break; 10569 } 11249 kwErrPrintf("Message has %u bytes unknown trailing bytes\n", cbMsg); 10570 11250 } 10571 if (cbMsg == 0)10572 {10573 apszPostCmdArgs[cPostCmdArgs] = NULL;10574 10575 /*10576 * The next step.10577 */10578 rcExit = kSubmitHandleJobUnpacked(pszExecutable, pszCwd,10579 cArgs, papszArgs, fWatcomBrainDamange,10580 cEnvVars, papszEnvVars, fNoPchCaching,10581 cPostCmdArgs, apszPostCmdArgs);10582 }10583 else if (cbMsg == KSIZE_MAX)10584 kwErrPrintf("Detected bogus message unpacking post command and its arguments!\n");10585 11251 else 10586 kwErrPrintf(" Message has %u bytes unknown trailing bytes\n", cbMsg);11252 kwErrPrintf("Bogus post command argument count: %u %#x\n", cPostCmdArgs, cPostCmdArgs); 10587 11253 } 10588 11254 else 10589 kwErrPrintf(" Bogus post command argument count: %u %#x\n", cPostCmdArgs, cPostCmdArgs);11255 kwErrPrintf("Detected bogus message looking for the post command argument count!\n"); 10590 11256 } 10591 11257 else 10592 kwErrPrintf("Detected bogus message looking for the post command argument count!\n");11258 kwErrPrintf("Detected bogus message unpacking special environment variable!\n"); 10593 11259 } 10594 11260 else 10595 kwErrPrintf("Detected bogus message unpacking environment variables!\n");11261 kwErrPrintf("Detected bogus message unpacking flags!\n"); 10596 11262 kHlpFree((void *)papszEnvVars); 10597 11263 } … … 10889 11555 const char *pszCwd = getcwd(szCwd, sizeof(szCwd)); 10890 11556 KU32 cEnvVars; 11557 char **papszEnvVars; 11558 const char *pszSpecialEnv = ""; 11559 const char *pszSpecialEnvFull = NULL; 10891 11560 KBOOL fWatcomBrainDamange = K_FALSE; 10892 11561 KBOOL fNoPchCaching = K_FALSE; … … 10934 11603 } 10935 11604 11605 /* Optional directory change. */ 11606 if ( i < argc 11607 && ( strcmp(argv[i], "--set-special") == 0 11608 || strcmp(argv[i], "-s") == 0 ) ) 11609 { 11610 i++; 11611 if (i >= argc) 11612 return kwErrPrintfRc(2, "--set-special takes an argument!\n"); 11613 pszSpecialEnvFull = argv[i++]; 11614 putenv(pszSpecialEnvFull); 11615 pszSpecialEnv = strdup(pszSpecialEnvFull); 11616 *strchr(pszSpecialEnv, '=') = '\0'; 11617 } 11618 10936 11619 /* Trigger breakpoint */ 10937 11620 if ( i < argc … … 10958 11641 10959 11642 /* 10960 * D o the job.11643 * Duplicate the environment. 10961 11644 */ 10962 11645 cEnvVars = 0; 10963 11646 while (environ[cEnvVars] != NULL) 10964 11647 cEnvVars++; 10965 11648 papszEnvVars = (char **)kHlpAllocZ(sizeof(papszEnvVars[0]) * (cEnvVars + 2)); 11649 11650 /* 11651 * Do the job. 11652 */ 10966 11653 for (j = 0; j < cRepeats; j++) 10967 11654 { 11655 memcpy(papszEnvVars, environ, sizeof(papszEnvVars[0]) * cEnvVars); 10968 11656 rcExit = kSubmitHandleJobUnpacked(argv[i], pszCwd, 10969 11657 argc - i, &argv[i], fWatcomBrainDamange, 10970 cEnvVars, environ, fNoPchCaching,11658 cEnvVars, papszEnvVars, pszSpecialEnv, fNoPchCaching, 10971 11659 0, NULL); 10972 11660 KW_LOG(("rcExit=%d\n", rcExit)); 10973 11661 kwSandboxCleanupLate(&g_Sandbox); 11662 } 11663 11664 if (getenv("KWORKER_STATS") != NULL) 11665 kwPrintStats(); 11666 11667 # ifdef WITH_LOG_FILE 11668 if (g_hLogFile != INVALID_HANDLE_VALUE && g_hLogFile != NULL) 11669 CloseHandle(g_hLogFile); 11670 # endif 11671 return rcExit; 11672 } 11673 11674 11675 /** 11676 * Reads @a pszFile into memory and chops it up into an argument vector. 11677 * 11678 * @returns Pointer to the argument vector on success, NULL on failure. 11679 * @param pszFile The file to load. 11680 * @param pcArgs Where to return the number of arguments. 11681 * @param ppszFileContent Where to return the allocation. 11682 */ 11683 static char **kwFullTestLoadArgvFile(const char *pszFile, int *pcArgs, char **ppszFileContent) 11684 { 11685 char **papszArgs = NULL; 11686 FILE *pFile = fopen(pszFile, "r"); 11687 if (pFile) 11688 { 11689 long cbFile; 11690 if ( fseek(pFile, 0, SEEK_END) == 0 11691 && (cbFile = ftell(pFile)) >= 0 11692 && fseek(pFile, 0, SEEK_SET) == 0) 11693 { 11694 char *pszFile = kHlpAllocZ(cbFile + 3); 11695 if (pszFile) 11696 { 11697 size_t cbRead = fread(pszFile, 1, cbFile + 1, pFile); 11698 if ( feof(pFile) 11699 && !ferror(pFile)) 11700 { 11701 size_t off = 0; 11702 int cArgs = 0; 11703 int cAllocated = 0; 11704 char ch; 11705 11706 pszFile[cbRead] = '\0'; 11707 pszFile[cbRead + 1] = '\0'; 11708 pszFile[cbRead + 2] = '\0'; 11709 11710 while ((ch = pszFile[off]) != '\0') 11711 { 11712 char *pszArg; 11713 switch (ch) 11714 { 11715 case ' ': 11716 case '\t': 11717 case '\n': 11718 case '\r': 11719 off++; 11720 continue; 11721 11722 case '\\': 11723 if (pszFile[off + 1] == '\n' || pszFile[off + 1] == '\r') 11724 { 11725 off += 2; 11726 continue; 11727 } 11728 /* fall thru */ 11729 default: 11730 pszArg = &pszFile[off]; 11731 do 11732 ch = pszFile[++off]; 11733 while (ch != '\0' && ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r'); 11734 pszFile[off++] = '\0'; 11735 break; 11736 11737 case '\'': 11738 pszArg = &pszFile[++off]; 11739 while ((ch = pszFile[off]) != '\0' && ch != '\'') 11740 off++; 11741 pszFile[off++] = '\0'; 11742 break; 11743 11744 case '\"': /** @todo escape sequences */ 11745 pszArg = &pszFile[++off]; 11746 while ((ch = pszFile[off]) != '\0' && ch != '"') 11747 off++; 11748 pszFile[off++] = '\0'; 11749 break; 11750 } 11751 if (cArgs + 1 >= cAllocated) 11752 { 11753 void *pvNew; 11754 cAllocated = cAllocated ? cAllocated * 2 : 16; 11755 pvNew = kHlpRealloc(papszArgs, cAllocated * sizeof(papszArgs[0])); 11756 if (pvNew) 11757 papszArgs = (char **)pvNew; 11758 else 11759 { 11760 kHlpFree(papszArgs); 11761 papszArgs = NULL; 11762 break; 11763 } 11764 } 11765 papszArgs[cArgs] = pszArg; 11766 papszArgs[++cArgs] = NULL; 11767 } 11768 *pcArgs = cArgs; 11769 } 11770 else 11771 kwErrPrintf("Error reading '%s'!\n", pszFile); 11772 } 11773 else 11774 kwErrPrintf("Error allocating %lu bytes!\n", cbFile + 2); 11775 } 11776 else 11777 kwErrPrintf("Error seeking '%s'!\n", pszFile); 11778 fclose(pFile); 11779 } 11780 else 11781 kwErrPrintf("Error opening '%s'!\n", pszFile); 11782 return papszArgs; 11783 } 11784 11785 /** 11786 * Appends a string to an string vector (arguments or enviornment). 11787 * 11788 * @returns 0 on success, non-zero on failure (exit code). 11789 * @param ppapszVector Pointer to the string pointer array. 11790 * @param pcEntries Pointer to the array size. 11791 * @param pszAppend The string to append. 11792 */ 11793 static int kwFullTestVectorAppend(const char ***ppapszVector, int *pcEntries, char const *pszAppend) 11794 { 11795 unsigned cEntries = *pcEntries; 11796 if (!(cEntries & 15)) 11797 { 11798 void *pvNew = kHlpRealloc((void *)*ppapszVector, sizeof(char *) * (cEntries + 16 + 1)); 11799 if (pvNew) 11800 *ppapszVector = (const char **)pvNew; 11801 else 11802 return kwErrPrintfRc(2, "Out of memory!\n"); 11803 } 11804 (*ppapszVector)[cEntries] = pszAppend; 11805 (*ppapszVector)[++cEntries] = NULL; 11806 *pcEntries = cEntries; 11807 return 0; 11808 } 11809 11810 11811 /** 11812 * Parses arguments for --full-test. 11813 * 11814 * @returns 0 on success, non-zero on failure (exit code). 11815 */ 11816 static int kwFullTestRunParseArgs(PKWONETEST *ppHead, int *piState, int argc, char **argv, 11817 const char *pszDefaultCwd, int cRecursions, const char *pszJobSrc) 11818 { 11819 PKWONETEST pCur = *ppHead; 11820 int i; 11821 for (i = 0; i < argc; i++) 11822 { 11823 int rc = 0; 11824 const char *pszArg = argv[i]; 11825 if (*pszArg == 'k' && kHlpStrComp(pszArg, "kSubmit") == 0) 11826 { 11827 if (*piState != 0) 11828 { 11829 pCur = (PKWONETEST)kHlpAllocZ(sizeof(*pCur)); 11830 if (!pCur) 11831 return kwErrPrintfRc(2, "Out of memory!\n"); 11832 pCur->fVirgin = K_TRUE; 11833 pCur->pszCwd = pszDefaultCwd; 11834 pCur->cRuns = 1; 11835 pCur->pNext = *ppHead; 11836 *ppHead = pCur; 11837 *piState = 0; 11838 } 11839 else if (!pCur->fVirgin) 11840 return kwErrPrintfRc(2, "Unexpected 'kSubmit' as argument #%u\n", i); 11841 pCur->pszJobSrc = pszJobSrc; 11842 pCur->iJobSrc = i; 11843 continue; /* (to stay virgin) */ 11844 } 11845 else if (*pszArg == '-' && *piState == 0) 11846 { 11847 const char *pszValue = NULL; 11848 char ch = *++pszArg; 11849 pszArg++; 11850 if (ch == '-') 11851 { 11852 ch = '\0'; 11853 if (*pszArg == '\0') /* -- */ 11854 *piState = 2; 11855 /* Translate or handle long options: */ 11856 else if (kHlpStrComp(pszArg, "putenv") == 0 || kHlpStrComp(pszArg, "set") == 0) 11857 ch = 'E'; 11858 else if (kHlpStrComp(pszArg, "special-env") == 0) 11859 ch = 's'; 11860 else if (kHlpStrComp(pszArg, "default-env") == 0) 11861 { 11862 unsigned i; 11863 pCur->cEnvVars = 0; 11864 for (i = 0; environ[i] && rc == 0; i++) 11865 rc = kwFullTestVectorAppend(&pCur->papszEnvVars, &pCur->cEnvVars, kHlpStrDup(environ[i])); /* leaks; unchecked */ 11866 } 11867 else if (kHlpStrComp(pszArg, "chdir") == 0) 11868 ch = 'C'; 11869 else if (kHlpStrComp(pszArg, "post-cmd") == 0) 11870 ch = 'P'; 11871 else if (kHlpStrComp(pszArg, "response-file") == 0) 11872 ch = '@'; 11873 else if (kHlpStrComp(pszArg, "runs") == 0) 11874 ch = 'R'; 11875 else if (kHlpStrComp(pszArg, "watcom-brain-damage") == 0) 11876 pCur->fWatcomBrainDamange = K_TRUE; 11877 else if (kHlpStrComp(pszArg, "no-pch-caching") == 0) 11878 pCur->fNoPchCaching = K_TRUE; 11879 else if (kHlpStrComp(pszArg, "executable") == 0) 11880 ch = 'e'; 11881 else if (kHlpStrComp(pszArg, "breakpoint") == 0) 11882 { 11883 __debugbreak(); 11884 continue; /* (to stay virgin) */ 11885 } 11886 else 11887 return kwErrPrintfRc(2, "Unknown option: --%s\n", pszArg); 11888 pszArg = ""; 11889 } 11890 11891 while (ch != '\0' && rc == 0) 11892 { 11893 /* Fetch value if needed: */ 11894 switch (ch) 11895 { 11896 case '@': 11897 case 'e': 11898 case 'E': 11899 case 's': 11900 case 'C': 11901 case 'R': 11902 if (*pszArg == ':' || *pszArg == '=') 11903 pszValue = &pszArg[1]; 11904 else if (*pszArg) 11905 pszValue = pszArg; 11906 else if (i + 1 < argc) 11907 pszValue = argv[++i]; 11908 else 11909 return kwErrPrintfRc(2, "Option -%c takes a value\n", ch); 11910 pszArg = ""; 11911 break; 11912 } 11913 11914 /* Handle the option: */ 11915 switch (ch) 11916 { 11917 case 'E': 11918 rc = kwFullTestVectorAppend(&pCur->papszEnvVars, &pCur->cEnvVars, pszValue); 11919 break; 11920 case 'C': 11921 pCur->pszCwd = pszValue; 11922 break; 11923 case 's': 11924 pCur->pszSpecialEnv = pszValue; 11925 break; 11926 case 'e': 11927 pCur->pszExecutable = pszValue; 11928 break; 11929 case 'P': 11930 *piState = 1; 11931 if (*pszArg) 11932 return kwErrPrintfRc(2, "Option -P cannot be followed by other options!\n"); 11933 break; 11934 case 'R': 11935 pCur->cRuns = atoi(pszValue); 11936 if ((int)pCur->cRuns < 0) 11937 return kwErrPrintfRc(2, "Option -R takes a positive (or zero) integer as value: %s\n", pszValue); 11938 break; 11939 case '@': 11940 if (cRecursions < 5) 11941 { 11942 char *pszLeaked = NULL; 11943 int cArgs = 0; 11944 char **papszArgsLeaked = kwFullTestLoadArgvFile(pszValue, &cArgs, &pszLeaked); 11945 if (papszArgsLeaked) 11946 { 11947 rc = kwFullTestRunParseArgs(ppHead, piState, cArgs, papszArgsLeaked, pszDefaultCwd, 11948 cRecursions + 1, pszValue); 11949 pCur = *ppHead; 11950 } 11951 else 11952 return 2; 11953 } 11954 else 11955 return kwErrPrintfRc(2, "Too deep response file nesting!\n"); 11956 break; 11957 } 11958 11959 /* next */ 11960 ch = *pszArg++; 11961 } 11962 } 11963 else if (*piState == 2) 11964 rc = kwFullTestVectorAppend(&pCur->papszArgs, &pCur->cArgs, pszArg); 11965 else if (*piState == 1) 11966 { 11967 if (pszArg[0] != '-' || pszArg[1] != '-' || pszArg[2] != '\0') 11968 rc = kwFullTestVectorAppend(&pCur->papszPostCmdArgs, &pCur->cPostCmdArgs, pszArg); 11969 else 11970 *piState = 2; 11971 } 11972 else 11973 return kwErrPrintfRc(2, "Unexpected argument: %s\n", pszArg); 11974 if (rc) 11975 return rc; 11976 pCur->fVirgin = K_FALSE; 11977 } 11978 return 0; 11979 } 11980 11981 11982 /** 11983 * Handles what comes after --full-test. 11984 * 11985 * @returns Exit code. 11986 * @param argc Number of arguments after --full-test. 11987 * @param argv Arguments after --full-test. 11988 */ 11989 static int kwFullTestRun(int argc, char **argv) 11990 { 11991 char szDefaultCwd[MAX_PATH]; 11992 const char *pszDefaultCwd = getcwd(szDefaultCwd, sizeof(szDefaultCwd)); 11993 KWONETEST FirstTest; 11994 PKWONETEST pHead = &FirstTest; 11995 PKWONETEST pCur; 11996 int iState = 0; 11997 int rcExit; 11998 11999 /* 12000 * Parse arguments. 12001 */ 12002 kHlpMemSet(&FirstTest, 0, sizeof(FirstTest)); 12003 FirstTest.pszJobSrc = "command-line"; 12004 FirstTest.iJobSrc = 1; 12005 FirstTest.fVirgin = K_TRUE; 12006 FirstTest.pszCwd = pszDefaultCwd; 12007 FirstTest.cRuns = 1; 12008 12009 rcExit = kwFullTestRunParseArgs(&pHead, &iState, argc, argv, pszDefaultCwd, 0, "command-line"); 12010 if (rcExit) 12011 return rcExit; 12012 12013 /* 12014 * Do the job. LIFO ordering (see kSubmit). 12015 */ 12016 for (pCur = pHead; pCur; pCur = pCur->pNext) 12017 { 12018 if (!pCur->pszExecutable && pCur->papszArgs) 12019 pCur->pszExecutable = pCur->papszArgs[0]; 12020 if ( pCur->pszExecutable 12021 && pCur->cArgs > 0 12022 && pCur->cEnvVars > 0) 12023 { 12024 size_t const cbEnvVarCopy = sizeof(pCur->papszEnvVars[0]) * (pCur->cEnvVars + 1); 12025 char ** const papszEnvVarsCopy = (char **)kHlpDup(pCur->papszEnvVars, cbEnvVarCopy); 12026 unsigned iRun; 12027 12028 for (iRun = 0; iRun < pCur->cRuns; iRun++) 12029 { 12030 rcExit = kSubmitHandleJobUnpacked(pCur->pszExecutable, pCur->pszCwd, 12031 pCur->cArgs, pCur->papszArgs, pCur->fWatcomBrainDamange, 12032 pCur->cEnvVars, pCur->papszEnvVars, pCur->pszSpecialEnv, 12033 pCur->fNoPchCaching, pCur->cPostCmdArgs, pCur->papszPostCmdArgs); 12034 12035 KW_LOG(("rcExit=%d\n", rcExit)); 12036 kwSandboxCleanupLate(&g_Sandbox); 12037 12038 memcpy((void *)pCur->papszEnvVars, papszEnvVarsCopy, cbEnvVarCopy); 12039 } 12040 kHlpFree(papszEnvVarsCopy); 12041 } 12042 else 12043 rcExit = kwErrPrintfRc(2, "Job is underspecified! %s%s%s (Job started with argument #%u, %s)\n", 12044 pCur->pszExecutable ? "" : " No executable!", 12045 pCur->cArgs < 1 ? " No arguments!" : "", 12046 pCur->cEnvVars < 1 ? " No environment!" : "", 12047 pCur->iJobSrc, pCur->pszJobSrc); 10974 12048 } 10975 12049 … … 11167 12241 else if (strcmp(argv[i], "--test") == 0) 11168 12242 return kwTestRun(argc - i - 1, &argv[i + 1]); 12243 else if (strcmp(argv[i], "--full-test") == 0) 12244 return kwFullTestRun(argc - i - 1, &argv[i + 1]); 11169 12245 else if (strcmp(argv[i], "--priority") == 0) 11170 12246 {
Note:
See TracChangeset
for help on using the changeset viewer.