/** * Make sure the Id and Revision keywords are expanded. * * @returns false - the state carries these kinds of changes. * @param pState The rewriter state. * @param pIn The input stream. * @param pOut The output stream. * @param pSettings The settings. */ bool rewrite_SvnKeywords(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings) { if ( !pSettings->fSetSvnKeywords || !ScmSvnIsInWorkingCopy(pState)) return false; char *pszKeywords; int rc = ScmSvnQueryProperty(pState, "svn:keywords", &pszKeywords); if ( RT_SUCCESS(rc) && ( !strstr(pszKeywords, "Id") /** @todo need some function for finding a word in a string. */ || !strstr(pszKeywords, "Revision")) ) { if (!strstr(pszKeywords, "Id") && !strstr(pszKeywords, "Revision")) rc = RTStrAAppend(&pszKeywords, " Id Revision"); else if (!strstr(pszKeywords, "Id")) rc = RTStrAAppend(&pszKeywords, " Id"); else rc = RTStrAAppend(&pszKeywords, " Revision"); if (RT_SUCCESS(rc)) { ScmVerbose(pState, 2, " * changing svn:keywords to '%s'\n", pszKeywords); rc = ScmSvnSetProperty(pState, "svn:keywords", pszKeywords); if (RT_FAILURE(rc)) RTMsgError("ScmSvnSetProperty: %Rrc\n", rc); /** @todo error propagation here.. */ } else RTMsgError("RTStrAppend: %Rrc\n", rc); /** @todo error propagation here.. */ RTStrFree(pszKeywords); } else if (rc == VERR_NOT_FOUND) { ScmVerbose(pState, 2, " * setting svn:keywords to 'Id Revision'\n"); rc = ScmSvnSetProperty(pState, "svn:keywords", "Id Revision"); if (RT_FAILURE(rc)) RTMsgError("ScmSvnSetProperty: %Rrc\n", rc); /** @todo error propagation here.. */ } else if (RT_SUCCESS(rc)) RTStrFree(pszKeywords); return false; }
/** * Basic API checks. * We'll return if any of these fails. */ static void tst1(void) { RTTestISub("Basics"); char *psz; int rc = VINF_SUCCESS; /* RTStrAlloc */ RTTESTI_CHECK(psz = RTStrAlloc(0)); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrAlloc(1)); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrAlloc(128)); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); /* RTStrAllocEx */ psz = (char*)"asdfasdf"; RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 1), VINF_SUCCESS); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 128), VINF_SUCCESS); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); /* RTStrRealloc */ psz = NULL; RTTESTI_CHECK_RC(RTStrRealloc(&psz, 10), VINF_SUCCESS); RTTESTI_CHECK(psz && !psz[0]); RTTESTI_CHECK(psz && !psz[9]); RTStrFree(psz); psz = NULL; RTTESTI_CHECK_RC(RTStrRealloc(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!psz); psz = NULL; RTTESTI_CHECK_RC(RTStrRealloc(&psz, 128), VINF_SUCCESS); RTTESTI_CHECK(psz && !psz[0]); RTTESTI_CHECK(psz && !psz[127]); if (psz) { memset(psz, 'a', 127); RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 160), VINF_SUCCESS); if (RT_SUCCESS(rc) && psz) { RTTESTI_CHECK(!psz[127]); RTTESTI_CHECK(!psz[159]); RTTESTI_CHECK(ASMMemIsAll8(psz, 127, 'a') == NULL); memset(psz, 'b', 159); RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 79), VINF_SUCCESS); if (RT_SUCCESS(rc)) { RTTESTI_CHECK(!psz[78]); RTTESTI_CHECK(ASMMemIsAll8(psz, 78, 'b') == NULL); RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!psz); } } } RTStrFree(psz); /* RTStrDup */ RTTESTI_CHECK(psz = RTStrDup("")); RTTESTI_CHECK(psz && *psz == '\0'); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDup("abcdefghijklmnop")); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnop")); RTStrFree(psz); /* RTStrDupEx */ psz = NULL; RTTESTI_CHECK_RC(RTStrDupEx(&psz, ""), VINF_SUCCESS); RTTESTI_CHECK(RT_FAILURE(rc) || *psz == '\0'); if (RT_SUCCESS(rc)) RTStrFree(psz); psz = (char*)"asdfasdfasdfasdf"; RTTESTI_CHECK_RC(rc = RTStrDupEx(&psz, "abcdefghijklmnop"), VINF_SUCCESS); RTTESTI_CHECK(RT_FAILURE(rc) || !RTStrCmp(psz, "abcdefghijklmnop")); if (RT_SUCCESS(rc)) RTStrFree(psz); /* RTStrDupN */ RTTESTI_CHECK(psz = RTStrDupN("abcdefg", 3)); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDupN("abc", 100000)); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDupN("abc", 0)); RTTESTI_CHECK(psz && *psz == '\0'); RTStrFree(psz); /* RTStrAAppend */ RTTESTI_CHECK(psz = RTStrDup("abc")); RTTESTI_CHECK_RC(RTStrAAppend(&psz, "def"), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdef")); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDup("abc")); RTTESTI_CHECK_RC(RTStrAAppend(&psz, ""), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTTESTI_CHECK_RC(RTStrAAppend(&psz, NULL), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTStrFree(psz); psz = NULL; RTTESTI_CHECK_RC(RTStrAAppend(&psz, "xyz"), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "xyz")); RTStrFree(psz); /* RTStrAAppendN */ RTTESTI_CHECK(psz = RTStrDup("abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "def", 1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcd")); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDup("abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "", 0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, NULL, 0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTStrFree(psz); psz = NULL; RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "abc", 2), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "ab")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "cdefghijklm", 1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "defghijklm", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklm")); RTStrFree(psz); /* RTStrAAppendExN / RTStrAAppendExNV */ psz = NULL; RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 5, "a", (size_t)1, "bc", (size_t)1, "cdefg", RTSTR_MAX, "hijkl", (size_t)2, "jklmnopqrstuvwxyz", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 2, NULL, (size_t)0, "", (size_t)0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 1, "-", (size_t)1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz-")); RTStrFree(psz); /* RTStrATruncate */ psz = NULL; RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!psz); RTTESTI_CHECK(psz = RTStrDup("")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDup("1234567890")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 5), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "12345")); RTStrFree(psz); psz = NULL; for (uint32_t i = 0; i < 128; i++) RTTESTI_CHECK_RC_RETV(RTStrAAppend(&psz, "abcdefghijklmnopqrstuvwxyz"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTStrATruncate(&psz, sizeof("abcdefghijklmnopqrstuvwxyz") - 1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 6), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdef")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "a")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "")); RTStrFree(psz); }
RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone) { /* * Validate input and figure out how many variable to clone and where to get them. */ bool fCaseSensitive = true; bool fPutEnvBlock = false; size_t cVars; const char * const *papszEnv; #ifdef RTENV_HAVE_WENVIRON PCRTUTF16 const * papwszEnv; #endif PRTENVINTERNAL pIntEnvToClone; AssertPtrReturn(pEnv, VERR_INVALID_POINTER); if (EnvToClone == RTENV_DEFAULT) { cVars = 0; pIntEnvToClone = NULL; #ifdef RTENV_HAVE_WENVIRON papszEnv = NULL; papwszEnv = (PCRTUTF16 * const)_wenviron; if (!papwszEnv) { _wgetenv(L"Path"); /* Force the CRT to initalize it. */ papwszEnv = (PCRTUTF16 * const)_wenviron; } if (papwszEnv) while (papwszEnv[cVars]) cVars++; #else papszEnv = rtEnvDefault(); if (papszEnv) while (papszEnv[cVars]) cVars++; #endif #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) /* DOS systems was case insensitive. A prime example is the 'Path' variable on windows which turns into the 'PATH' variable. */ fCaseSensitive = false; #endif } else { pIntEnvToClone = EnvToClone; AssertPtrReturn(pIntEnvToClone, VERR_INVALID_HANDLE); AssertReturn(pIntEnvToClone->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); RTENV_LOCK(pIntEnvToClone); fPutEnvBlock = pIntEnvToClone->fPutEnvBlock; papszEnv = pIntEnvToClone->papszEnv; cVars = pIntEnvToClone->cVars; } /* * Create the duplicate. */ PRTENVINTERNAL pIntEnv; int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, fCaseSensitive, fPutEnvBlock); if (RT_SUCCESS(rc)) { pIntEnv->cVars = cVars; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; if (EnvToClone == RTENV_DEFAULT) { /* ASSUMES the default environment is in the current codepage. */ size_t iDst = 0; for (size_t iSrc = 0; iSrc < cVars; iSrc++) { #ifdef RTENV_HAVE_WENVIRON int rc2 = RTUtf16ToUtf8(papwszEnv[iSrc], &pIntEnv->papszEnv[iDst]); #else int rc2 = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iDst], papszEnv[iSrc]); #endif if (RT_SUCCESS(rc2)) { /* Make sure it contains an '='. */ iDst++; if (strchr(pIntEnv->papszEnv[iDst - 1], '=')) continue; rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst - 1], "="); if (RT_SUCCESS(rc2)) continue; } else if (rc2 == VERR_NO_TRANSLATION) { rc = VWRN_ENV_NOT_FULLY_TRANSLATED; continue; } /* failed fatally. */ pIntEnv->cVars = iDst; RTEnvDestroy(pIntEnv); return rc2; } pIntEnv->cVars = iDst; } else { for (size_t iVar = 0; iVar < cVars; iVar++) { char *pszVar = RTStrDup(papszEnv[iVar]); if (RT_UNLIKELY(!pszVar)) { RTENV_UNLOCK(pIntEnvToClone); pIntEnv->cVars = iVar; RTEnvDestroy(pIntEnv); return VERR_NO_STR_MEMORY; } pIntEnv->papszEnv[iVar] = pszVar; } } /* done */ *pEnv = pIntEnv; } if (pIntEnvToClone) RTENV_UNLOCK(pIntEnvToClone); return rc; }
/** * Retrieves the currently logged in users and stores their names along with the * user count. * * @returns VBox status code. * @param ppszUserList Where to store the user list (separated by commas). * Must be freed with RTStrFree(). * @param pcUsersInList Where to store the number of users in the list. */ int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList) { PLUID paSessions = NULL; ULONG cSessions = 0; /* This function can report stale or orphaned interactive logon sessions of already logged off users (especially in Windows 2000). */ NTSTATUS rcNt = LsaEnumerateLogonSessions(&cSessions, &paSessions); if (rcNt != STATUS_SUCCESS) { ULONG ulError = LsaNtStatusToWinError(rcNt); switch (ulError) { case ERROR_NOT_ENOUGH_MEMORY: VBoxServiceError("Not enough memory to enumerate logon sessions!\n"); break; case ERROR_SHUTDOWN_IN_PROGRESS: /* If we're about to shutdown when we were in the middle of enumerating the logon * sessions, skip the error to not confuse the user with an unnecessary log message. */ VBoxServiceVerbose(3, "Shutdown in progress ...\n"); ulError = ERROR_SUCCESS; break; default: VBoxServiceError("LsaEnumerate failed with error %u\n", ulError); break; } return RTErrConvertFromWin32(ulError); } VBoxServiceVerbose(3, "Found %ld sessions\n", cSessions); PVBOXSERVICEVMINFOPROC paProcs; DWORD cProcs; int rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs); if (RT_FAILURE(rc)) { if (rc == VERR_NO_MEMORY) VBoxServiceError("Not enough memory to enumerate processes\n"); else VBoxServiceError("Failed to enumerate processes, rc=%Rrc\n", rc); } else { PVBOXSERVICEVMINFOUSER pUserInfo; pUserInfo = (PVBOXSERVICEVMINFOUSER)RTMemAllocZ(cSessions * sizeof(VBOXSERVICEVMINFOUSER) + 1); if (!pUserInfo) VBoxServiceError("Not enough memory to store enumerated users!\n"); else { ULONG cUniqueUsers = 0; for (ULONG i = 0; i < cSessions; i++) { VBoxServiceVerbose(3, "Handling session %u\n", i); VBOXSERVICEVMINFOUSER UserInfo; if (VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i])) { VBoxServiceVerbose(4, "Handling user=%ls, domain=%ls, package=%ls\n", UserInfo.wszUser, UserInfo.wszLogonDomain, UserInfo.wszAuthenticationPackage); /* Retrieve assigned processes of current session. */ ULONG ulSession; uint32_t cSessionProcs = VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs, &ulSession); /* Don't return here when current session does not have assigned processes * anymore -- in that case we have to search through the unique users list below * and see if got a stale user/session entry. */ bool fFoundUser = false; for (ULONG i = 0; i < cUniqueUsers; i++) { if ( !wcscmp(UserInfo.wszUser, pUserInfo[i].wszUser) && !wcscmp(UserInfo.wszLogonDomain, pUserInfo[i].wszLogonDomain) && !wcscmp(UserInfo.wszAuthenticationPackage, pUserInfo[i].wszAuthenticationPackage) && cSessionProcs) { /* * Only respect the highest session for the current user. */ if (ulSession > pUserInfo[i].ulSession) { VBoxServiceVerbose(4, "Updating user=%ls to %u processes (last session: %u)\n", UserInfo.wszUser, cSessionProcs, ulSession); pUserInfo[i].ulNumProcs = cSessionProcs; pUserInfo[i].ulSession = ulSession; if (!cSessionProcs) VBoxServiceVerbose(3, "Stale session for user=%ls detected! Old processes: %u, new: %u\n", pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, cSessionProcs); } /* There can be multiple session objects using the same session ID for the * current user -- so when we got the same session again just add the found * processes to it. */ else if (pUserInfo[i].ulSession == ulSession) { VBoxServiceVerbose(4, "Adding %u processes to user=%ls (session %u)\n", cSessionProcs, UserInfo.wszUser, ulSession); pUserInfo[i].ulNumProcs += cSessionProcs; pUserInfo[i].ulSession = ulSession; } fFoundUser = true; break; } } if (!fFoundUser) { VBoxServiceVerbose(4, "Adding new user=%ls (session %u) with %u processes\n", UserInfo.wszUser, ulSession, cSessionProcs); memcpy(&pUserInfo[cUniqueUsers], &UserInfo, sizeof(VBOXSERVICEVMINFOUSER)); pUserInfo[cUniqueUsers].ulNumProcs = cSessionProcs; pUserInfo[cUniqueUsers].ulSession = ulSession; cUniqueUsers++; Assert(cUniqueUsers <= cSessions); } } } VBoxServiceVerbose(3, "Found %u unique logged-in user(s)\n", cUniqueUsers); *pcUsersInList = 0; for (ULONG i = 0; i < cUniqueUsers; i++) { if (pUserInfo[i].ulNumProcs) { VBoxServiceVerbose(3, "User %ls has %ld processes (session %u)\n", pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, pUserInfo[i].ulSession); if (*pcUsersInList > 0) { rc = RTStrAAppend(ppszUserList, ","); AssertRCBreakStmt(rc, RTStrFree(*ppszUserList)); } *pcUsersInList += 1; char *pszTemp; int rc2 = RTUtf16ToUtf8(pUserInfo[i].wszUser, &pszTemp); if (RT_SUCCESS(rc2)) { rc = RTStrAAppend(ppszUserList, pszTemp); RTMemFree(pszTemp); } else rc = RTStrAAppend(ppszUserList, "<string-conversion-error>"); AssertRCBreakStmt(rc, RTStrFree(*ppszUserList)); } } RTMemFree(pUserInfo); } VBoxServiceVMInfoWinProcessesFree(paProcs); } LsaFreeReturnBuffer(paSessions); return rc; }
RTDECL(int) RTEnvCloneUtf16Block(PRTENV phEnv, PCRTUTF16 pwszzBlock, uint32_t fFlags) { AssertPtrReturn(pwszzBlock, VERR_INVALID_POINTER); AssertReturn(!fFlags, VERR_INVALID_FLAGS); /* * Count the number of variables in the block. */ uint32_t cVars = 0; PCRTUTF16 pwsz = pwszzBlock; while (*pwsz != '\0') { cVars++; pwsz += RTUtf16Len(pwsz) + 1; AssertReturn(cVars < _256K, VERR_OUT_OF_RANGE); } /* * Create the duplicate. */ PRTENVINTERNAL pIntEnv; int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, false /*fCaseSensitive*/, false /*fPutEnvBlock*/); if (RT_SUCCESS(rc)) { pIntEnv->cVars = cVars; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; size_t iDst = 0; for (pwsz = pwszzBlock; *pwsz != '\0'; pwsz += RTUtf16Len(pwsz) + 1) { int rc2 = RTUtf16ToUtf8(pwsz, &pIntEnv->papszEnv[iDst]); if (RT_SUCCESS(rc2)) { /* Make sure it contains an '='. */ const char *pszEqual = strchr(pIntEnv->papszEnv[iDst], '='); if (!pszEqual) { rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst], "="); if (RT_SUCCESS(rc2)) pszEqual = strchr(pIntEnv->papszEnv[iDst], '='); } if (pszEqual) { /* Check for duplicates, keep the last version. */ const char *pchVar = pIntEnv->papszEnv[iDst]; size_t cchVarNmAndEq = pszEqual - pchVar; for (size_t iDst2 = 0; iDst2 < iDst; iDst2++) if (pIntEnv->pfnCompare(pIntEnv->papszEnv[iDst2], pchVar, cchVarNmAndEq) == 0) { RTStrFree(pIntEnv->papszEnv[iDst2]); pIntEnv->papszEnv[iDst2] = pIntEnv->papszEnv[iDst]; pIntEnv->papszEnv[iDst] = NULL; iDst--; break; } iDst++; continue; } iDst++; } /* failed fatally. */ pIntEnv->cVars = iDst; RTEnvDestroy(pIntEnv); return rc2; } Assert(iDst <= pIntEnv->cVars); pIntEnv->cVars = iDst; /* done */ *phEnv = pIntEnv; } return rc; }