void fix_env(char **&en) { static char *dummy = 0; en = &dummy; wchar_t *wstrings = GetEnvironmentStringsW(); if(!wstrings) return; try { wchar_t *wstrings_end = 0; int count = 0; for(wstrings_end = wstrings;*wstrings_end;wstrings_end+=wcslen(wstrings_end)+1) count++; if(env_.convert(wstrings,wstrings_end)) { envp_.resize(count+1,0); char *p=env_.c_str(); int pos = 0; for(int i=0;i<count;i++) { if(*p!='=') envp_[pos++] = p; p+=strlen(p)+1; } en = &envp_[0]; } } catch(...) { FreeEnvironmentStringsW(wstrings); throw; } FreeEnvironmentStringsW(wstrings); }
bool Platform::GetCurrentEnvironment(EnvironmentBlock &env) { WCHAR *envStrings = GetEnvironmentStringsW(); WCHAR *oldEnvStrings = envStrings; if (envStrings == nullptr) return false; while (*envStrings) { std::string envStr; envStr = WideToNarrowString(envStrings); size_t equal = envStr.find('='); DS2ASSERT(equal != std::string::npos); // Some environment values can start with '=' for MS-DOS compatibility. // Ignore these values. if (equal != 0) env[envStr.substr(0, equal)] = envStr.substr(equal + 1); envStrings += wcslen(envStrings) + 1; } FreeEnvironmentStringsW(oldEnvStrings); return true; }
DKLIB_API DKMap<DKString, DKString> DKProcessEnvironments(void) { DKMap<DKString, DKString> env; LPWSTR str = (LPWSTR)GetEnvironmentStringsW(); if (str) { while (*str) { /* key=value */ DKString tmp(str); long i = tmp.Find(L'='); if (i > 0) { DKString key = tmp.Left(i); DKString val = tmp.Right(i+1); env.Update(key, val); } size_t len = wcslen(str); str += len + 1; } FreeEnvironmentStringsW((LPWCH)str); } return env; }
void CALLBACK Export( HWND, HINSTANCE, LPTSTR lpCmdLine, int ) { if( !lpCmdLine ) ExitProcess( 0 ); Handle onp( CreateFile( lpCmdLine, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 ) ); if( !onp || onp == INVALID_HANDLE_VALUE ) ExitProcess( 0 ); wchar_t* env = GetEnvironmentStringsW(); int i; for( i = 0; *(int*)(env + i); i++ ); i *= sizeof(*env); i += 2 * sizeof(*env); DWORD written; WriteFile( onp, env, i, &written, 0 ); FreeEnvironmentStringsW( env ); return; }
//------------------------------------------------------------------------------ static void capture_env(env_block_t* block) { void* env; const wchar_t* c; void* data; int size; env = GetEnvironmentStringsW(); size = 0; c = (const wchar_t*)env; while (1) { if (*((const int*)(c)) == 0) { size += 4; break; } size += 2; ++c; } data = malloc(size); memcpy(data, env, size); block->data = data; block->size = size; FreeEnvironmentStringsW(env); }
bool OOBase::Environment::get_current(env_table_t& tabEnv) { wchar_t* env = GetEnvironmentStringsW(); if (!env) return GetLastError() == ERROR_SUCCESS; int err = process_block(env,tabEnv); FreeEnvironmentStringsW(env); return (err == ERROR_SUCCESS); }
LPVOID __cdecl __crtGetEnvironmentStringsW( VOID ) { void *penv; wchar_t *pwch; wchar_t *wbuffer; int total_size; if ( NULL == (penv = GetEnvironmentStringsW()) ) return NULL; /* find out how big a buffer is needed */ pwch = penv; while ( *pwch != L'\0' ) { if ( *++pwch == L'\0' ) pwch++; } total_size = (int)((char *)pwch - (char *)penv) + (int)sizeof( wchar_t ); /* allocate the buffer */ if ( NULL == (wbuffer = _malloc_crt( total_size )) ) { FreeEnvironmentStringsW( penv ); return NULL; } /* copy environment strings to buffer */ memcpy( wbuffer, penv, total_size ); FreeEnvironmentStringsW( penv ); return (LPVOID)wbuffer; }
static void dec_cRefThisDLL() { #ifdef FEAT_GETTEXT if (InterlockedDecrement((LPLONG)&g_cRefThisDll) == 0) { dyn_gettext_free(); if (oldenv != NULL) { FreeEnvironmentStringsW(oldenv); oldenv = NULL; } } #else InterlockedDecrement((LPLONG)&g_cRefThisDll); #endif }
Result<Environment> Environment::CreateForCurrentProcess(Trace& trace) { trace < L"Environment::CreateForCurrentProcess"; auto environment = GetEnvironmentStringsW(); Environment newEnvironment; try { newEnvironment.CreateVariableMap(environment, trace); } catch(...) { } FreeEnvironmentStringsW(environment); return newEnvironment; }
char* win_build_environment(char* new_env) { if (new_env == NULL) { return NULL; } else { WCHAR *tmp, *merged, *tmp_new; tmp_new = (WCHAR *) new_env; erts_rwmtx_rlock(&environ_rwmtx); tmp = GetEnvironmentStringsW(); merged = merge_environment(tmp, tmp_new); FreeEnvironmentStringsW(tmp); erts_rwmtx_runlock(&environ_rwmtx); return (char *) merged; } }
/* Returns a Windows style environment block, discarding final trailing NUL */ JNIEXPORT jstring JNICALL Java_java_lang_ProcessEnvironment_environmentBlock(JNIEnv *env, jclass klass) { int i; jstring envblock; jchar *blockW = (jchar *) GetEnvironmentStringsW(); if (blockW == NULL) return environmentBlock9x(env); /* Don't search for "\u0000\u0000", since an empty environment block may legitimately consist of a single "\u0000". */ for (i = 0; blockW[i];) while (blockW[i++]) ; envblock = (*env)->NewString(env, blockW, i); FreeEnvironmentStringsW(blockW); return envblock; }
QProcessEnvironment QProcessEnvironment::systemEnvironment() { QProcessEnvironment env; // Calls to setenv() affect the low-level environment as well. // This is not the case the other way round. if (wchar_t *envStrings = GetEnvironmentStringsW()) { for (const wchar_t *entry = envStrings; *entry; ) { const int entryLen = int(wcslen(entry)); // + 1 to permit magic cmd variable names starting with = if (const wchar_t *equal = wcschr(entry + 1, L'=')) { int nameLen = equal - entry; QString name = QString::fromWCharArray(entry, nameLen); QString value = QString::fromWCharArray(equal + 1, entryLen - nameLen - 1); env.d->hash.insert(QProcessEnvironmentPrivate::Key(name), value); } entry += entryLen + 1; } FreeEnvironmentStringsW(envStrings); } return env; }
QProcessEnvironment QProcessEnvironment::systemEnvironment() { QProcessEnvironment env; #if !defined(Q_OS_WINCE) // Calls to setenv() affect the low-level environment as well. // This is not the case the other way round. if (wchar_t *envStrings = GetEnvironmentStringsW()) { for (const wchar_t *entry = envStrings; *entry; ) { int entryLen = wcslen(entry); if (const wchar_t *equal = wcschr(entry, L'=')) { int nameLen = equal - entry; QString name = QString::fromWCharArray(entry, nameLen); QString value = QString::fromWCharArray(equal + 1, entryLen - nameLen - 1); env.d->hash.insert(QProcessEnvironmentPrivate::Key(name), value); } entry += entryLen + 1; } FreeEnvironmentStringsW(envStrings); } #endif return env; }
LPVOID __cdecl __crtGetEnvironmentStringsA( VOID ) { static int f_use = 0; wchar_t *wEnv; wchar_t *wTmp; char *aEnv; char *aTmp; int nSizeW; int nSizeA; /* * Look for 'preferred' flavor. Otherwise use available flavor. * Must actually call the function to ensure it's not a stub. */ if ( 0 == f_use ) { if ( NULL != (wEnv = GetEnvironmentStringsW()) ) f_use = USE_W; else if ( NULL != (aEnv = GetEnvironmentStringsA()) ) f_use = USE_A; else return NULL; } /* Use "W" version */ if (USE_W == f_use) { /* obtain wide environment block */ if ( NULL == wEnv ) if ( NULL == (wEnv = GetEnvironmentStringsW()) ) return NULL; /* look for double null that indicates end of block */ wTmp = wEnv; while ( *wTmp != L'\0' ) { if ( *++wTmp == L'\0' ) wTmp++; } /* calculate total size of block, including all nulls */ nSizeW = wTmp - wEnv + 1; /* find out how much space needed for multi-byte environment */ nSizeA = WideCharToMultiByte( CP_ACP, 0, wEnv, nSizeW, NULL, 0, NULL, NULL ); /* allocate space for multi-byte string */ if ( (nSizeA == 0) || ((aEnv = (char *)_malloc_crt(nSizeA)) == NULL) ) { FreeEnvironmentStringsW( wEnv ); return NULL; } /* do the conversion */ if ( !WideCharToMultiByte( CP_ACP, 0, wEnv, nSizeW, aEnv, nSizeA, NULL, NULL ) ) { _free_crt( aEnv ); aEnv = NULL; } FreeEnvironmentStringsW( wEnv ); return aEnv; } /* Use "A" version */ if ( USE_A == f_use ) { if ( NULL == aEnv ) if ( NULL == (aEnv = GetEnvironmentStringsA()) ) return NULL; /* determine how big a buffer is needed */ aTmp = aEnv; while ( *aTmp != '\0' ) { if ( *++aTmp == '\0' ) aTmp++; } nSizeA = aTmp - aEnv + 1; if ( NULL == (aTmp = _malloc_crt( nSizeA )) ) { FreeEnvironmentStringsA( aEnv ); return NULL; } memcpy( aTmp, aEnv, nSizeA ); FreeEnvironmentStringsA( aEnv ); return aTmp; } return NULL; }
LPVOID __cdecl __crtGetEnvironmentStringsW( VOID ) { static int f_use = 0; void *penv = NULL; char *pch; wchar_t *pwch; wchar_t *wbuffer; int total_size = 0; int str_size; /* * Look for unstubbed 'preferred' flavor. Otherwise use available flavor. * Must actually call the function to ensure it's not a stub. */ if ( 0 == f_use ) { if ( NULL != (penv = GetEnvironmentStringsW()) ) f_use = USE_W; else if ( NULL != (penv = GetEnvironmentStringsA()) ) f_use = USE_A; else return NULL; } /* Use "W" version */ if ( USE_W == f_use ) { if ( NULL == penv ) if ( NULL == (penv = GetEnvironmentStringsW()) ) return NULL; /* find out how big a buffer is needed */ pwch = penv; while ( *pwch != L'\0' ) { if ( *++pwch == L'\0' ) pwch++; } total_size = (char *)pwch - (char *)penv + sizeof( wchar_t ); /* allocate the buffer */ if ( NULL == (wbuffer = _malloc_crt( total_size )) ) { FreeEnvironmentStringsW( penv ); return NULL; } /* copy environment strings to buffer */ memcpy( wbuffer, penv, total_size ); FreeEnvironmentStringsW( penv ); return (LPVOID)wbuffer; } /* Use "A" version */ if ( USE_A == f_use ) { /* * Convert strings and return the requested information. */ if ( NULL == penv ) if ( NULL == (penv = GetEnvironmentStringsA()) ) return NULL; pch = penv; /* find out how big a buffer we need */ while ( *pch != '\0' ) { if ( 0 == (str_size = MultiByteToWideChar( __lc_codepage, MB_PRECOMPOSED, pch, -1, NULL, 0 )) ) return 0; total_size += str_size; pch += strlen(pch) + 1; } /* room for final NULL */ total_size++; /* allocate enough space for chars */ if ( NULL == (wbuffer = (wchar_t *) _malloc_crt( total_size * sizeof( wchar_t ) )) ) { FreeEnvironmentStringsA( penv ); return NULL; } /* do the conversion */ pch = penv; pwch = wbuffer; while (*pch != '\0') { if ( 0 == MultiByteToWideChar( __lc_codepage, MB_PRECOMPOSED, pch, -1, pwch, total_size - (pwch - wbuffer) ) ) { _free_crt( wbuffer ); FreeEnvironmentStringsA( penv ); return NULL; } pch += strlen(pch) + 1; pwch += wcslen(pwch) + 1; } *pwch = L'\0'; FreeEnvironmentStringsA( penv ); return (LPVOID)wbuffer; } else /* f_use is neither USE_A nor USE_W */ return NULL; }
ProgramRunner::ProgramRunner(const BSONObj& args, const BSONObj& env) { uassert(ErrorCodes::FailedToParse, "cannot pass an empty argument to ProgramRunner", !args.isEmpty()); string program(args.firstElement().valuestrsafe()); uassert(ErrorCodes::FailedToParse, "invalid program name passed to ProgramRunner", !program.empty()); boost::filesystem::path programPath = findProgram(program); boost::filesystem::path programName = programPath.stem(); string prefix("mongod-"); bool isMongodProgram = string("mongod") == programName || programName.string().compare(0, prefix.size(), prefix) == 0; prefix = "mongos-"; bool isMongosProgram = string("mongos") == programName || programName.string().compare(0, prefix.size(), prefix) == 0; if (isMongodProgram) { _name = "d"; } else if (isMongosProgram) { _name = "s"; } else if (programName == "mongobridge") { _name = "b"; } else { _name = "sh"; } _argv.push_back(programPath.string()); _port = -1; // Parse individual arguments into _argv BSONObjIterator j(args); j.next(); // skip program name (handled above) while (j.more()) { BSONElement e = j.next(); string str; if (e.isNumber()) { stringstream ss; ss << e.number(); str = ss.str(); } else { verify(e.type() == mongo::String); str = e.valuestr(); } if (str == "--port") { _port = -2; } else if (_port == -2) { _port = strtol(str.c_str(), 0, 10); } else if (isMongodProgram && str == "--configsvr") { _name = "c"; } _argv.push_back(str); } // Load explicitly set environment key value pairs into _envp. for (const BSONElement& e : env) { // Environment variable values must be strings verify(e.type() == mongo::String); _envp.emplace(std::string(e.fieldName()), std::string(e.valuestr())); } // Import this process' environment into _envp, for all keys that have not already been set. // We need to do this so that the child process has all the PATH and locale variables, unless // we explicitly override them. #ifdef _WIN32 wchar_t* processEnv = GetEnvironmentStringsW(); ON_BLOCK_EXIT( [](wchar_t* toFree) { if (toFree) FreeEnvironmentStringsW(toFree); }, processEnv); // Windows' GetEnvironmentStringsW returns a NULL terminated array of NULL separated // <key>=<value> pairs. while (processEnv && *processEnv) { std::wstring envKeyValue(processEnv); size_t splitPoint = envKeyValue.find('='); invariant(splitPoint != std::wstring::npos); std::string envKey = toUtf8String(envKeyValue.substr(0, splitPoint)); std::string envValue = toUtf8String(envKeyValue.substr(splitPoint + 1)); _envp.emplace(std::move(envKey), std::move(envValue)); processEnv += envKeyValue.size() + 1; } #else // environ is a POSIX defined array of char*s. Each char* in the array is a <key>=<value>\0 // pair. char** environEntry = environ; while (*environEntry) { std::string envKeyValue(*environEntry); size_t splitPoint = envKeyValue.find('='); invariant(splitPoint != std::string::npos); std::string envKey = envKeyValue.substr(0, splitPoint); std::string envValue = envKeyValue.substr(splitPoint + 1); _envp.emplace(std::move(envKey), std::move(envValue)); ++environEntry; } #endif bool needsPort = isMongodProgram || isMongosProgram || (programName == "mongobridge"); if (!needsPort) { _port = -1; } uassert(ErrorCodes::FailedToParse, str::stream() << "a port number is expected when running " << program << " from the shell", !needsPort || _port >= 0); uassert(ErrorCodes::BadValue, str::stream() << "can't start " << program << ", port " << _port << " already in use", _port < 0 || !registry.isPortRegistered(_port)); }
/** * Launch a child process without elevated privilege. */ static BOOL LaunchAsNormalUser(const PRUnichar *exePath, PRUnichar *cl) { #ifdef WINCE return PR_FALSE; #else if (!pCreateProcessWithTokenW) { // IsUserAnAdmin is not present on Win9x and not exported by name on Win2k *(FARPROC *)&pIsUserAnAdmin = GetProcAddress(GetModuleHandleA("shell32.dll"), "IsUserAnAdmin"); // CreateProcessWithTokenW is not present on WinXP or earlier *(FARPROC *)&pCreateProcessWithTokenW = GetProcAddress(GetModuleHandleA("advapi32.dll"), "CreateProcessWithTokenW"); if (!pCreateProcessWithTokenW) return FALSE; } // do nothing here if we are not elevated or IsUserAnAdmin is not present. if (!pIsUserAnAdmin || pIsUserAnAdmin && !pIsUserAnAdmin()) return FALSE; // borrow the shell token to drop the privilege HWND hwndShell = FindWindowA("Progman", NULL); DWORD dwProcessId; GetWindowThreadProcessId(hwndShell, &dwProcessId); HANDLE hProcessShell = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId); if (!hProcessShell) return FALSE; HANDLE hTokenShell; BOOL ok = OpenProcessToken(hProcessShell, MAXIMUM_ALLOWED, &hTokenShell); CloseHandle(hProcessShell); if (!ok) return FALSE; HANDLE hNewToken; ok = DuplicateTokenEx(hTokenShell, MAXIMUM_ALLOWED, NULL, SecurityDelegation, TokenPrimary, &hNewToken); CloseHandle(hTokenShell); if (!ok) return FALSE; STARTUPINFOW si = {sizeof(si), 0}; PROCESS_INFORMATION pi = {0}; // When launching with reduced privileges, environment inheritance // (passing NULL as lpEnvironment) doesn't work correctly. Pass our // current environment block explicitly WCHAR* myenv = GetEnvironmentStringsW(); ok = pCreateProcessWithTokenW(hNewToken, 0, // profile is already loaded exePath, cl, CREATE_UNICODE_ENVIRONMENT, myenv, // inherit my environment NULL, // use my current directory &si, &pi); if (myenv) FreeEnvironmentStringsW(myenv); CloseHandle(hNewToken); if (!ok) return FALSE; CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return TRUE; #endif }
DWORD main(int argc, char **argv) { HANDLE hCompletionPort; BOOL fNeedHelp = FALSE; WCHAR wzzDrop[1024] = L"build\0nmake\0"; GetSystemTimeAsFileTime((FILETIME *)&s_llStartTime); StringCchPrintfA(s_szPipe, ARRAYSIZE(s_szPipe), "%s.%d", TBLOG_PIPE_NAME, GetCurrentProcessId()); int arg = 1; for (; arg < argc && (argv[arg][0] == '-' || argv[arg][0] == '/'); arg++) { CHAR *argn = argv[arg] + 1; CHAR *argp = argn; while (*argp && *argp != ':' && *argp != '=') { argp++; } if (*argp == ':' || *argp == '=') { *argp++ = '\0'; } switch (argn[0]) { case 'd': // Drop Processes case 'D': if (*argp) { PWCHAR pwz = wzzDrop; while (*argp) { if (*argp == ';') { *pwz++ = '\0'; } else { *pwz++ = *argp++; } } *pwz++ = '\0'; *pwz = '\0'; } case 'o': // Output file. case 'O': StringCchCopyA(s_szLogFile, ARRAYSIZE(s_szLogFile), argp); break; case 'v': // Verbose case 'V': s_fVerbose = TRUE; break; case '?': // Help. fNeedHelp = TRUE; break; default: fNeedHelp = TRUE; printf("TRACEBLD: Bad argument: %s:%s\n", argn, argp); break; } } if (arg >= argc) { fNeedHelp = TRUE; } if (fNeedHelp) { printf("Usage:\n" " tracebld [options] command {command arguments}\n" "Options:\n" " /o:file Log all events to the output files.\n" " /? Display this help message.\n" "Summary:\n" " Runs the build commands and figures out which files have dependencies..\n" "\n"); exit(9001); } // Create the completion port. hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0); if (hCompletionPort == NULL) { MyErrExit("CreateIoCompletionPort"); } // Create completion port worker threads. // CreateWorkers(hCompletionPort); CreatePipeConnection(hCompletionPort, 0); printf("TRACEBLD: Ready for clients. Press Ctrl-C to stop.\n"); /////////////////////////////////////////////////////////// Validate DLLs. // CHAR szTmpPath[MAX_PATH]; CHAR szExePath[MAX_PATH]; CHAR szDllPath[MAX_PATH]; PCHAR pszFilePart = NULL; if (!GetModuleFileNameA(NULL, szTmpPath, ARRAYSIZE(szTmpPath))) { printf("TRACEBLD: Couldn't retreive exe name.\n"); return 9002; } if (!GetFullPathNameA(szTmpPath, ARRAYSIZE(szExePath), szExePath, &pszFilePart) || pszFilePart == NULL) { printf("TRACEBLD: Error: %s is not a valid path name..\n", szTmpPath); return 9002; } StringCchCopyA(pszFilePart, szExePath + ARRAYSIZE(szExePath) - pszFilePart, "trcbld" DETOURS_STRINGIFY(DETOURS_BITS) ".dll"); StringCchCopyA(szDllPath, ARRAYSIZE(szDllPath), szExePath); ////////////////////////////////////////////////////////////////////////// STARTUPINFOA si; PROCESS_INFORMATION pi; CHAR szCommand[2048]; CHAR szExe[MAX_PATH]; CHAR szFullExe[MAX_PATH] = "\0"; PCHAR pszFileExe = NULL; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); si.cb = sizeof(si); szCommand[0] = L'\0'; StringCchCopyA(szExe, sizeof(szExe), argv[arg]); for (; arg < argc; arg++) { if (strchr(argv[arg], ' ') != NULL || strchr(argv[arg], '\t') != NULL) { StringCchCatA(szCommand, sizeof(szCommand), "\""); StringCchCatA(szCommand, sizeof(szCommand), argv[arg]); StringCchCatA(szCommand, sizeof(szCommand), "\""); } else { StringCchCatA(szCommand, sizeof(szCommand), argv[arg]); } if (arg + 1 < argc) { StringCchCatA(szCommand, sizeof(szCommand), " "); } } printf("TRACEBLD: Starting: `%s'\n", szCommand); printf("TRACEBLD: with `%s'\n", szDllPath); fflush(stdout); DWORD dwFlags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED; SetLastError(0); SearchPathA(NULL, szExe, ".exe", ARRAYSIZE(szFullExe), szFullExe, &pszFileExe); if (!DetourCreateProcessWithDllExA(szFullExe[0] ? szFullExe : NULL, szCommand, NULL, NULL, TRUE, dwFlags, NULL, NULL, &si, &pi, szDllPath, NULL)) { printf("TRACEBLD: DetourCreateProcessWithDllEx failed: %d\n", GetLastError()); ExitProcess(9007); } ZeroMemory(&s_Payload, sizeof(s_Payload)); s_Payload.nParentProcessId = GetCurrentProcessId(); s_Payload.nTraceProcessId = GetCurrentProcessId(); s_Payload.nGeneology = 1; s_Payload.rGeneology[0] = 0; StringCchCopyW(s_Payload.wzStdin, ARRAYSIZE(s_Payload.wzStdin), L"\\\\.\\CONIN$"); StringCchCopyW(s_Payload.wzStdout, ARRAYSIZE(s_Payload.wzStdout), L"\\\\.\\CONOUT$"); StringCchCopyW(s_Payload.wzStderr, ARRAYSIZE(s_Payload.wzStderr), L"\\\\.\\CONOUT$"); StringCchCopyW(s_Payload.wzParents, ARRAYSIZE(s_Payload.wzParents), L""); CopyEnvironment(s_Payload.wzzDrop, wzzDrop); LPWCH pwStrings = GetEnvironmentStringsW(); CopyEnvironment(s_Payload.wzzEnvironment, pwStrings); FreeEnvironmentStringsW(pwStrings); if (!DetourCopyPayloadToProcess(pi.hProcess, s_guidTrace, &s_Payload, sizeof(s_Payload))) { printf("TRACEBLD: DetourCopyPayloadToProcess failed: %d\n", GetLastError()); ExitProcess(9008); } ResumeThread(pi.hThread); WaitForSingleObject(pi.hProcess, INFINITE); DWORD dwResult = 0; if (!GetExitCodeProcess(pi.hProcess, &dwResult)) { printf("TRACEBLD: GetExitCodeProcess failed: %d\n", GetLastError()); return 9008; } printf("TRACEBLD: %d processes.\n", s_nTotalClients); return dwResult; }
int main() { int argc; wchar_t ** argv = CommandLineToArgvW(GetCommandLine(), &argc); // Make sure that we've been passed the right number of arguments if (argc < 8) { _tprintf(_T("Usage: %s (four inheritable event handles) (CommandLineToSpawn)\n"), argv[0]); return(0); } // Construct the full command line int nCmdLineLength= MAX_CMD_LINE_LENGTH; wchar_t * szCmdLine= (wchar_t *)malloc(nCmdLineLength * sizeof(wchar_t)); szCmdLine[0]= 0; int nPos = 0; for(int i = 8; i < argc; ++i) { int nCpyLen; int len= wcslen(argv[i]); int requiredSize= nPos+len+2; if (requiredSize > 32*1024) { #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Command line too long!\n")); #endif return 0; } ensureSize(&szCmdLine, &nCmdLineLength, requiredSize); if (NULL == szCmdLine) { #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Not enough memory to build cmd line!\n")); #endif return 0; } if(0 > (nCpyLen = copyTo(szCmdLine + nPos, argv[i], len, nCmdLineLength - nPos))) { #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Not enough space to build command line\n")); #endif return 0; } nPos += nCpyLen; szCmdLine[nPos] = _T(' '); ++nPos; } szCmdLine[nPos] = _T('\0'); STARTUPINFOW si = {sizeof(si)}; PROCESS_INFORMATION pi = {0}; DWORD dwExitCode = 0; #ifdef DEBUG_MONITOR int currentPID = GetCurrentProcessId(); wchar_t buffer[MAX_CMD_LINE_LENGTH]; #endif BOOL exitProc = FALSE; HANDLE waitEvent = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[4]); HANDLE h[5]; h[0] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[3]); // simulated SIGINT (CTRL-C or Cygwin 'kill -SIGINT') // h[1] we reserve for the process handle h[2] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[5]); // simulated SIGTERM h[3] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[6]); // simulated SIGKILL h[4] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[7]); // CTRL-C, in all cases SetConsoleCtrlHandler(HandlerRoutine, TRUE); int parentPid = wcstol(argv[1], NULL, 10); int nCounter = wcstol(argv[2], NULL, 10); wchar_t inPipeName[PIPE_NAME_LENGTH]; wchar_t outPipeName[PIPE_NAME_LENGTH]; wchar_t errPipeName[PIPE_NAME_LENGTH]; swprintf(inPipeName, L"\\\\.\\pipe\\stdin%08i%010i", parentPid, nCounter); swprintf(outPipeName, L"\\\\.\\pipe\\stdout%08i%010i", parentPid, nCounter); swprintf(errPipeName, L"\\\\.\\pipe\\stderr%08i%010i", parentPid, nCounter); #ifdef DEBUG_MONITOR swprintf(buffer, _T("Pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName); OutputDebugStringW(buffer); #endif HANDLE stdHandles[3]; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; if((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateFileW(inPipeName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, &sa))) || (INVALID_HANDLE_VALUE == (stdHandles[1] = CreateFileW(outPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))) || (INVALID_HANDLE_VALUE == (stdHandles[2] = CreateFileW(errPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa)))) { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Failed to open pipe %i, %i, %i: %i\n"), stdHandles[0], stdHandles[1], stdHandles[2], GetLastError()); OutputDebugStringW(buffer); #endif CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); return -1;; } SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, TRUE); if(!SetStdHandle(STD_INPUT_HANDLE, stdHandles[0]) || !SetStdHandle(STD_OUTPUT_HANDLE, stdHandles[1]) || !SetStdHandle(STD_ERROR_HANDLE, stdHandles[2])) { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Failed to reassign standard streams: %i\n"), GetLastError()); OutputDebugStringW(buffer); #endif CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); return -1;; } #ifdef DEBUG_MONITOR wchar_t * lpvEnv = GetEnvironmentStringsW(); // If the returned pointer is NULL, exit. if (lpvEnv == NULL) OutputDebugStringW(_T("Cannot Read Environment\n")); else { // Variable strings are separated by NULL byte, and the block is // terminated by a NULL byte. OutputDebugStringW(_T("Starter: Environment\n")); for (wchar_t * lpszVariable = (wchar_t *) lpvEnv; *lpszVariable; lpszVariable+=wcslen(lpszVariable) + 1) { swprintf(buffer, _T("%s\n"), lpszVariable); OutputDebugStringW(buffer); } FreeEnvironmentStringsW(lpvEnv); } #endif #ifdef DEBUG_MONITOR swprintf(buffer, _T("Starting: %s\n"), szCmdLine); OutputDebugStringW(buffer); #endif // Create job object HANDLE hJob = CreateJobObject(NULL, NULL); // Spawn the other processes as part of this Process Group BOOL f = CreateProcessW(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); // We don't need them any more CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); if (f) { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Process %i started\n"), pi.dwProcessId); OutputDebugStringW(buffer); #endif SetEvent(waitEvent); // Means thar process has been spawned CloseHandle(pi.hThread); h[1] = pi.hProcess; if(NULL != hJob) { if(!AssignProcessToJobObject(hJob, pi.hProcess)) { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Cannot assign process %i to a job\n"), pi.dwProcessId); OutputDebugStringW(buffer); DisplayErrorMessage(); #endif } } while(!exitProc) { // Wait for the spawned-process to die or for the event // indicating that the processes should be forcibly killed. DWORD event = WaitForMultipleObjects(5, h, FALSE, INFINITE); switch (event) { case WAIT_OBJECT_0 + 0: // SIGINT case WAIT_OBJECT_0 + 4: // CTRL-C #ifdef DEBUG_MONITOR swprintf(buffer, _T("starter (PID %i) received CTRL-C event\n"), currentPID); OutputDebugStringW(buffer); #endif if ((event == (WAIT_OBJECT_0 + 0)) && isCygwin(h[1])) { // Need to issue a kill command wchar_t kill[1024]; swprintf(kill, L"kill -SIGINT %d", pi.dwProcessId); if (!runCygwinCommand(kill)) { // fall back to console event GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } } else { GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } SetEvent(waitEvent); break; case WAIT_OBJECT_0 + 1: // App terminated normally // Make it's exit code our exit code #ifdef DEBUG_MONITOR swprintf(buffer, _T("starter: launched process has been terminated(PID %i)\n"), pi.dwProcessId); OutputDebugStringW(buffer); #endif GetExitCodeProcess(pi.hProcess, &dwExitCode); exitProc = TRUE; break; // Terminate and Kill behavior differ only for cygwin processes, where // we use the cygwin 'kill' command. We send a SIGKILL in one case, // SIGTERM in the other. For non-cygwin processes, both requests // are treated exactly the same case WAIT_OBJECT_0 + 2: // TERM case WAIT_OBJECT_0 + 3: // KILL { const wchar_t* signal = (event == WAIT_OBJECT_0 + 2) ? L"TERM" : L"KILL"; #ifdef DEBUG_MONITOR swprintf(buffer, _T("starter received %s event (PID %i)\n"), signal, currentPID); OutputDebugStringW(buffer); #endif if (isCygwin(h[1])) { // Need to issue a kill command wchar_t kill[1024]; swprintf(kill, L"kill -%s %d", signal, pi.dwProcessId); if (!runCygwinCommand(kill)) { // fall back to console event GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } } else { GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } SetEvent(waitEvent); if(NULL != hJob) { if(!TerminateJobObject(hJob, (DWORD)-1)) { #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Cannot terminate job\n")); DisplayErrorMessage(); #endif } } // Note that we keep trucking until the child process terminates (case WAIT_OBJECT_0 + 1) break; } default: // Unexpected code #ifdef DEBUG_MONITOR DisplayErrorMessage(); #endif exitProc = TRUE; break; } } } else { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Cannot start: %s\n"), szCmdLine); OutputDebugStringW(buffer); DisplayErrorMessage(); #endif } if (NULL != szCmdLine) { free(szCmdLine); } CloseHandle(waitEvent); CloseHandle(h[0]); CloseHandle(h[1]); CloseHandle(h[2]); CloseHandle(h[3]); CloseHandle(h[4]); return(dwExitCode); }
void fini_getenv_state(GETENV_STATE *state) { FreeEnvironmentStringsW(state->environment_strings); state->environment_strings = state->next_string = NULL; erts_rwmtx_runlock(&environ_rwmtx); }
APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, const char * const * *argv, const char * const * *env) { apr_status_t rv = apr_initialize(); if (rv != APR_SUCCESS) { return rv; } #if defined(_WIN32_WCE) apr_app_init_complete = 1; #elif APR_HAS_UNICODE_FS IF_WIN_OS_IS_UNICODE { apr_wchar_t **wstrs; apr_wchar_t *sysstr; int wstrc; int dupenv; if (apr_app_init_complete) { return rv; } apr_app_init_complete = 1; sysstr = GetCommandLineW(); if (sysstr) { wstrs = CommandLineToArgvW(sysstr, &wstrc); if (wstrs) { *argc = apr_wastrtoastr(argv, wstrs, wstrc); GlobalFree(wstrs); } } sysstr = GetEnvironmentStringsW(); dupenv = warrsztoastr(&_environ, sysstr, -1); if (env) { *env = apr_malloc_dbg((dupenv + 1) * sizeof (char *), __FILE__, __LINE__ ); memcpy((void*)*env, _environ, (dupenv + 1) * sizeof (char *)); } else { } FreeEnvironmentStringsW(sysstr); /* MSVCRT will attempt to maintain the wide environment calls * on _putenv(), which is bogus if we've passed a non-ascii * string to _putenv(), since they use MultiByteToWideChar * and breaking the implicit utf-8 assumption we've built. * * Reset _wenviron for good measure. */ if (_wenviron) { apr_wchar_t **wenv = _wenviron; _wenviron = NULL; free(wenv); } } #endif return rv; }
BOOLEAN DosBIOSInitialize(VOID) { PDOS_MCB Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT); LPWSTR SourcePtr, Environment; LPSTR AsciiString; DWORD AsciiSize; LPSTR DestPtr = (LPSTR)SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0); #if 0 UCHAR i; CHAR CurrentDirectory[MAX_PATH]; CHAR DosDirectory[DOS_DIR_LENGTH]; LPSTR Path; FILE *Stream; WCHAR Buffer[256]; #endif /* Initialize the MCB */ Mcb->BlockType = 'Z'; Mcb->Size = USER_MEMORY_SIZE; Mcb->OwnerPsp = 0; /* Initialize the link MCB to the UMB area */ Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT + USER_MEMORY_SIZE + 1); Mcb->BlockType = 'M'; Mcb->Size = UMB_START_SEGMENT - FIRST_MCB_SEGMENT - USER_MEMORY_SIZE - 2; Mcb->OwnerPsp = SYSTEM_PSP; /* Initialize the UMB area */ Mcb = SEGMENT_TO_MCB(UMB_START_SEGMENT); Mcb->BlockType = 'Z'; Mcb->Size = UMB_END_SEGMENT - UMB_START_SEGMENT; Mcb->OwnerPsp = 0; /* Get the environment strings */ SourcePtr = Environment = GetEnvironmentStringsW(); if (Environment == NULL) return FALSE; /* Fill the DOS system environment block */ while (*SourcePtr) { /* Get the size of the ASCII string */ AsciiSize = WideCharToMultiByte(CP_ACP, 0, SourcePtr, -1, NULL, 0, NULL, NULL); /* Allocate memory for the ASCII string */ AsciiString = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, AsciiSize); if (AsciiString == NULL) { FreeEnvironmentStringsW(Environment); return FALSE; } /* Convert to ASCII */ WideCharToMultiByte(CP_ACP, 0, SourcePtr, -1, AsciiString, AsciiSize, NULL, NULL); /* Copy the string into DOS memory */ strcpy(DestPtr, AsciiString); /* Move to the next string */ SourcePtr += wcslen(SourcePtr) + 1; DestPtr += strlen(AsciiString); *(DestPtr++) = 0; /* Free the memory */ HeapFree(GetProcessHeap(), 0, AsciiString); } *DestPtr = 0; /* Free the memory allocated for environment strings */ FreeEnvironmentStringsW(Environment); #if 0 /* Clear the current directory buffer */ ZeroMemory(CurrentDirectories, sizeof(CurrentDirectories)); /* Get the current directory */ if (!GetCurrentDirectoryA(MAX_PATH, CurrentDirectory)) { // TODO: Use some kind of default path? return FALSE; } /* Convert that to a DOS path */ if (!GetShortPathNameA(CurrentDirectory, DosDirectory, DOS_DIR_LENGTH)) { // TODO: Use some kind of default path? return FALSE; } /* Set the drive */ CurrentDrive = DosDirectory[0] - 'A'; /* Get the directory part of the path */ Path = strchr(DosDirectory, '\\'); if (Path != NULL) { /* Skip the backslash */ Path++; } /* Set the directory */ if (Path != NULL) { strncpy(CurrentDirectories[CurrentDrive], Path, DOS_DIR_LENGTH); } /* Read CONFIG.SYS */ Stream = _wfopen(DOS_CONFIG_PATH, L"r"); if (Stream != NULL) { while (fgetws(Buffer, sizeof(Buffer)/sizeof(Buffer[0]), Stream)) { // TODO: Parse the line } fclose(Stream); } #endif /* Register the DOS 32-bit Interrupts */ // RegisterDosInt32(0x20, DosInt20h); /* Initialize the DOS kernel */ return DosKRNLInitialize(); }