/** * Queries symbol information by address. * * The returned symbol is what the debug info interpreter considers the symbol * most applicable to the specified address. This usually means a symbol with an * address equal or lower than the requested. * * @returns IPRT status code. * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found. * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols. * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and * it's not inside any of the segments defined by the module. * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid. * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the * end of the segment. * * @param hDbgMod The module handle. * @param iSeg The segment number. * @param off The offset into the segment. * @param poffDisp Where to store the distance between the * specified address and the returned symbol. * Optional. * @param pSymInfo Where to store the symbol information. */ RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo) { /* * Validate input. */ PRTDBGMODINT pDbgMod = hDbgMod; RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE); AssertPtrNull(poffDisp); AssertPtr(pSymInfo); RTDBGMOD_LOCK(pDbgMod); /* * Convert RVAs. */ if (iSeg == RTDBGSEGIDX_RVA) { iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off); if (iSeg == NIL_RTDBGSEGIDX) { RTDBGMOD_UNLOCK(pDbgMod); return VERR_DBG_INVALID_RVA; } } /* * Get down to business. */ int rc = pDbgMod->pDbgVt->pfnSymbolByAddr(pDbgMod, iSeg, off, poffDisp, pSymInfo); RTDBGMOD_UNLOCK(pDbgMod); return rc; }
/** * Adds a segment to the module. Optional feature. * * This method is intended used for manually constructing debug info for a * module. The main usage is from other debug info interpreters that want to * avoid writing a debug info database and instead uses the standard container * behind the scenes. * * @returns IPRT status code. * @retval VERR_NOT_SUPPORTED if this feature isn't support by the debug info * interpreter. This is a common return code. * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. * @retval VERR_DBG_ADDRESS_WRAP if uRva+cb wraps around. * @retval VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE if pszName is too short or long. * @retval VERR_INVALID_PARAMETER if fFlags contains undefined flags. * @retval VERR_DBG_SPECIAL_SEGMENT if *piSeg is a special segment. * @retval VERR_DBG_INVALID_SEGMENT_INDEX if *piSeg doesn't meet expectations. * * @param hDbgMod The module handle. * @param uRva The image relative address of the segment. * @param cb The size of the segment. * @param pszName The segment name. Does not normally need to be * unique, although this is somewhat up to the * debug interpreter to decide. * @param fFlags Segment flags. Reserved for future used, MBZ. * @param piSeg The segment index or NIL_RTDBGSEGIDX on input. * The assigned segment index on successful return. * Optional. */ RTDECL(int) RTDbgModSegmentAdd(RTDBGMOD hDbgMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, uint32_t fFlags, PRTDBGSEGIDX piSeg) { /* * Validate input. */ PRTDBGMODINT pDbgMod = hDbgMod; RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE); AssertMsgReturn(uRva + cb >= uRva, ("uRva=%RTptr cb=%RTptr\n", uRva, cb), VERR_DBG_ADDRESS_WRAP); Assert(*pszName); size_t cchName = strlen(pszName); AssertReturn(cchName > 0, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE); AssertReturn(cchName < RTDBG_SEGMENT_NAME_LENGTH, VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE); AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER); AssertPtrNull(piSeg); AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg <= RTDBGSEGIDX_LAST, ("%#x\n", *piSeg), VERR_DBG_SPECIAL_SEGMENT); /* * Do the deed. */ RTDBGMOD_LOCK(pDbgMod); int rc = pDbgMod->pDbgVt->pfnSegmentAdd(pDbgMod, uRva, cb, pszName, cchName, fFlags, piSeg); RTDBGMOD_UNLOCK(pDbgMod); return rc; }
/** * Connect to the DMI server. * * @returns COM status code. * @param pLocator The locator. * @param pszServer The server name. * @param ppServices Where to return the services interface. */ static HRESULT rtSystemDmiWinConnectToServer(IWbemLocator *pLocator, const char *pszServer, IWbemServices **ppServices) { AssertPtr(pLocator); AssertPtrNull(pszServer); AssertPtr(ppServices); BSTR pBStrServer = rtSystemWinBstrFromUtf8(pszServer); if (!pBStrServer) return E_OUTOFMEMORY; HRESULT hrc = pLocator->ConnectServer(pBStrServer, NULL, NULL, 0, NULL, 0, 0, ppServices); if (SUCCEEDED(hrc)) { hrc = CoSetProxyBlanket(*ppServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); if (FAILED(hrc)) (*ppServices)->Release(); } SysFreeString(pBStrServer); return hrc; }
/** * The native callback. * * @param pNotifierBlock Pointer to g_NotifierBlock. * @param ulNativeEvent The native event. * @param pvCpu The cpu id cast into a pointer value. */ static VOID __stdcall rtMpNotificationNtCallback(PVOID pvUser, PKE_PROCESSOR_CHANGE_NOTIFY_CONTEXT pChangeContext, PNTSTATUS pOperationStatus) { NOREF(pvUser); AssertPtr(pChangeContext); AssertPtrNull(pOperationStatus); RTCPUID idCpu = pChangeContext->NtNumber; switch (pChangeContext->State) { case KeProcessorAddStartNotify: case KeProcessorAddFailureNotify: break; case KeProcessorAddCompleteNotify: /* Update the active CPU set before doing callback round. */ RTCpuSetAdd(&g_rtMpNtCpuSet, idCpu); rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, idCpu); break; //case KeProcessorDelCompleteNotify: // rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, idCpu); // break; default: AssertMsgFailed(("Unexpected state=%d idCpu=%d\n", pChangeContext->State, (int)idCpu)); break; } *pOperationStatus = STATUS_SUCCESS; }
RTDECL(int) RTStrAAppendExNVTag(char **ppsz, size_t cPairs, va_list va, const char *pszTag) { AssertPtr(ppsz); if (!cPairs) return VINF_SUCCESS; /* * Determine the length of each string and calc the new total. */ struct RTStrAAppendExNVStruct { const char *psz; size_t cch; } *paPairs = (struct RTStrAAppendExNVStruct *)alloca(cPairs * sizeof(*paPairs)); AssertReturn(paPairs, VERR_NO_STR_MEMORY); size_t cchOrg = *ppsz ? strlen(*ppsz) : 0; size_t cchNewTotal = cchOrg; for (size_t i = 0; i < cPairs; i++) { const char *psz = va_arg(va, const char *); size_t cch = va_arg(va, size_t); AssertPtrNull(psz); Assert(cch == RTSTR_MAX || cch == RTStrNLen(psz, cch)); if (cch == RTSTR_MAX) cch = psz ? strlen(psz) : 0; cchNewTotal += cch; paPairs[i].cch = cch; paPairs[i].psz = psz; } cchNewTotal++; /* '\0' */ /* * Try reallocate the string. */ char *pszNew = (char *)RTMemReallocTag(*ppsz, cchNewTotal, pszTag); if (!pszNew) return VERR_NO_STR_MEMORY; /* * Do the appending. */ size_t off = cchOrg; for (size_t i = 0; i < cPairs; i++) { memcpy(&pszNew[off], paPairs[i].psz, paPairs[i].cch); off += paPairs[i].cch; } Assert(off + 1 == cchNewTotal); pszNew[off] = '\0'; /* done */ *ppsz = pszNew; return VINF_SUCCESS; }
RTDECL(int) RTPollNoResume(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid) { RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertPtrNull(pfEvents); AssertPtrNull(pid); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); int rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); ASMAtomicWriteBool(&pThis->fBusy, false); return rc; }
RTDECL(int) RTUtf16ToLatin1ExTag(PCRTUTF16 pwszString, size_t cwcString, char **ppsz, size_t cch, size_t *pcch, const char *pszTag) { /* * Validate input. */ AssertPtr(pwszString); AssertPtr(ppsz); AssertPtrNull(pcch); /* * Validate the UTF-16 string and calculate the length of the Latin1 encoding of it. */ size_t cchResult; int rc = rtUtf16CalcLatin1Length(pwszString, cwcString, &cchResult); if (RT_SUCCESS(rc)) { if (pcch) *pcch = cchResult; /* * Check buffer size / Allocate buffer and recode it. */ bool fShouldFree; char *pszResult; if (cch > 0 && *ppsz) { fShouldFree = false; if (cch <= cchResult) return VERR_BUFFER_OVERFLOW; pszResult = *ppsz; } else { *ppsz = NULL; fShouldFree = true; cch = RT_MAX(cch, cchResult + 1); pszResult = (char *)RTMemAllocTag(cch, pszTag); } if (pszResult) { rc = rtUtf16RecodeAsLatin1(pwszString, cwcString, pszResult, cch - 1); if (RT_SUCCESS(rc)) { *ppsz = pszResult; return rc; } if (fShouldFree) RTMemFree(pszResult); } else rc = VERR_NO_STR_MEMORY; } return rc; }
RTDECL(int) RTManifestQueryAttr(RTMANIFEST hManifest, const char *pszAttr, uint32_t fType, char *pszValue, size_t cbValue, uint32_t *pfType) { RTMANIFESTINT *pThis = hManifest; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE); AssertPtrNull(pszAttr); AssertPtr(pszValue); return rtManifestQueryAttrWorker(&pThis->SelfEntry, pszAttr, fType, pszValue, cbValue, pfType); }
RTDECL(int) RTPoll(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid) { RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertPtrNull(pfEvents); AssertPtrNull(pid); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); int rc; if (cMillies == RT_INDEFINITE_WAIT || cMillies == 0) { do rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); while (rc == VERR_INTERRUPTED); } else { uint64_t MsStart = RTTimeMilliTS(); rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); while (RT_UNLIKELY(rc == VERR_INTERRUPTED)) { if (RTTimeMilliTS() - MsStart >= cMillies) { rc = VERR_TIMEOUT; break; } rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); } } ASMAtomicWriteBool(&pThis->fBusy, false); return rc; }
RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered) { PRTFILEAIOREQINTERNAL pReqInt = hReq; RTFILEAIOREQ_VALID_RETURN(pReqInt); RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); AssertPtrNull(pcbTransfered); if ( (RT_SUCCESS(pReqInt->Rc)) && (pcbTransfered)) *pcbTransfered = pReqInt->cbTransfered; return pReqInt->Rc; }
RTDECL(int) RTPipeWriteBlocking(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten) { RTPIPEINTERNAL *pThis = hPipe; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE); AssertReturn(!pThis->fRead, VERR_ACCESS_DENIED); AssertPtr(pvBuf); AssertPtrNull(pcbWritten); int rc = rtPipeTryBlocking(pThis); if (RT_SUCCESS(rc)) { size_t cbTotalWritten = 0; while (cbToWrite > 0) { ssize_t cbWritten = write(pThis->fd, pvBuf, RT_MIN(cbToWrite, SSIZE_MAX)); if (cbWritten < 0) { rc = RTErrConvertFromErrno(errno); break; } /* advance */ pvBuf = (char const *)pvBuf + cbWritten; cbTotalWritten += cbWritten; cbToWrite -= cbWritten; } if (pcbWritten) { *pcbWritten = cbTotalWritten; if ( RT_FAILURE(rc) && cbTotalWritten && rc != VERR_INVALID_POINTER) rc = VINF_SUCCESS; } ASMAtomicDecU32(&pThis->u32State); } return rc; }
RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered) { PRTFILEAIOREQINTERNAL pReqInt = hReq; RTFILEAIOREQ_VALID_RETURN(pReqInt); RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); AssertPtrNull(pcbTransfered); int rcSol = aio_error(&pReqInt->AioCB); Assert(rcSol != EINPROGRESS); /* Handled by our own state handling. */ if (rcSol == 0) { if (pcbTransfered) *pcbTransfered = aio_return(&pReqInt->AioCB); return VINF_SUCCESS; } /* An error occurred. */ return RTErrConvertFromErrno(rcSol); }
RTDECL(int) RTManifestEntryQueryAttr(RTMANIFEST hManifest, const char *pszEntry, const char *pszAttr, uint32_t fType, char *pszValue, size_t cbValue, uint32_t *pfType) { RTMANIFESTINT *pThis = hManifest; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE); AssertPtr(pszEntry); AssertPtrNull(pszAttr); AssertPtr(pszValue); /* * Look up the entry. */ bool fNeedNormalization; size_t cchEntry; int rc = rtManifestValidateNameEntry(pszEntry, &fNeedNormalization, &cchEntry); AssertRCReturn(rc, rc); PRTMANIFESTENTRY pEntry; rc = rtManifestGetEntry(pThis, pszEntry, fNeedNormalization, cchEntry, &pEntry); if (RT_SUCCESS(rc)) rc = rtManifestQueryAttrWorker(pEntry, pszAttr, fType, pszValue, cbValue, pfType); return rc; }
RTDECL(int) RTPipeWriteBlocking(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten) { RTPIPEINTERNAL *pThis = hPipe; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE); AssertReturn(!pThis->fRead, VERR_ACCESS_DENIED); AssertPtr(pvBuf); AssertPtrNull(pcbWritten); int rc = RTCritSectEnter(&pThis->CritSect); if (RT_SUCCESS(rc)) { /* No concurrent readers, sorry. */ if (pThis->cUsers == 0) { pThis->cUsers++; /* * If I/O is pending, wait for it to complete. */ if (pThis->fIOPending) { rc = rtPipeWriteCheckCompletion(pThis); while (rc == VINF_TRY_AGAIN) { Assert(pThis->fIOPending); HANDLE hEvent = pThis->Overlapped.hEvent; RTCritSectLeave(&pThis->CritSect); WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE); RTCritSectEnter(&pThis->CritSect); } } if (RT_SUCCESS(rc)) { Assert(!pThis->fIOPending); pThis->fPromisedWritable = false; /* * Try write everything. * No bounce buffering, cUsers protects us. */ size_t cbTotalWritten = 0; while (cbToWrite > 0) { rc = ResetEvent(pThis->Overlapped.hEvent); Assert(rc == TRUE); pThis->fIOPending = true; RTCritSectLeave(&pThis->CritSect); DWORD cbWritten = 0; if (WriteFile(pThis->hPipe, pvBuf, cbToWrite <= ~(DWORD)0 ? (DWORD)cbToWrite : ~(DWORD)0, &cbWritten, &pThis->Overlapped)) rc = VINF_SUCCESS; else if (GetLastError() == ERROR_IO_PENDING) { WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE); if (GetOverlappedResult(pThis->hPipe, &pThis->Overlapped, &cbWritten, TRUE /*fWait*/)) rc = VINF_SUCCESS; else rc = RTErrConvertFromWin32(GetLastError()); } else if (GetLastError() == ERROR_NO_DATA) rc = VERR_BROKEN_PIPE; else rc = RTErrConvertFromWin32(GetLastError()); RTCritSectEnter(&pThis->CritSect); pThis->fIOPending = false; if (RT_FAILURE(rc)) break; /* advance */ pvBuf = (char const *)pvBuf + cbWritten; cbTotalWritten += cbWritten; cbToWrite -= cbWritten; } if (pcbWritten) { *pcbWritten = cbTotalWritten; if ( RT_FAILURE(rc) && cbTotalWritten && rc != VERR_INVALID_POINTER) rc = VINF_SUCCESS; } } if (rc == VERR_BROKEN_PIPE) pThis->fBrokenPipe = true; pThis->cUsers--; } else rc = VERR_WRONG_ORDER; RTCritSectLeave(&pThis->CritSect); } return rc; #if 1 return VERR_NOT_IMPLEMENTED; #else int rc = rtPipeTryBlocking(pThis); if (RT_SUCCESS(rc)) { size_t cbTotalWritten = 0; while (cbToWrite > 0) { ssize_t cbWritten = write(pThis->fd, pvBuf, RT_MIN(cbToWrite, SSIZE_MAX)); if (cbWritten < 0) { rc = RTErrConvertFromErrno(errno); break; } /* advance */ pvBuf = (char const *)pvBuf + cbWritten; cbTotalWritten += cbWritten; cbToWrite -= cbWritten; } if (pcbWritten) { *pcbWritten = cbTotalWritten; if ( RT_FAILURE(rc) && cbTotalWritten && rc != VERR_INVALID_POINTER) rc = VINF_SUCCESS; } ASMAtomicDecU32(&pThis->u32State); } return rc; #endif }
RTDECL(int) RTManifestReadStandardEx(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, char *pszErr, size_t cbErr) { /* * Validate input. */ AssertPtrNull(pszErr); if (pszErr && cbErr) *pszErr = '\0'; RTMANIFESTINT *pThis = hManifest; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE); /* * Process the stream line by line. */ uint32_t iLine = 0; for (;;) { /* * Read a line from the input stream. */ iLine++; char szLine[RTPATH_MAX + RTSHA512_DIGEST_LEN + 32]; int rc = rtManifestReadLine(hVfsIos, szLine, sizeof(szLine)); if (RT_FAILURE(rc)) { if (rc == VERR_EOF) return VINF_SUCCESS; RTStrPrintf(pszErr, cbErr, "Error reading line #%u: %Rrc", iLine, rc); return rc; } if (rc != VINF_SUCCESS) { RTStrPrintf(pszErr, cbErr, "Line number %u is too long", iLine); return VERR_OUT_OF_RANGE; } /* * Strip it and skip if empty. */ char *psz = RTStrStrip(szLine); if (!*psz) continue; /* * Read the attribute name. */ const char * const pszAttr = psz; do psz++; while (!RT_C_IS_BLANK(*psz) && *psz); if (*psz) *psz++ = '\0'; /* * The entry name is enclosed in parenthesis and followed by a '='. */ psz = RTStrStripL(psz); if (*psz != '(') { RTStrPrintf(pszErr, cbErr, "Expected '(' after %zu on line %u", psz - szLine, iLine); return VERR_PARSE_ERROR; } const char * const pszName = ++psz; while (*psz) { if (*psz == ')') { char *psz2 = RTStrStripL(psz + 1); if (*psz2 == '=') { *psz = '\0'; psz = psz2; break; } } psz++; } if (*psz != '=') { RTStrPrintf(pszErr, cbErr, "Expected ')=' at %zu on line %u", psz - szLine, iLine); return VERR_PARSE_ERROR; } /* * The value. */ psz = RTStrStrip(psz + 1); const char * const pszValue = psz; if (!*psz) { RTStrPrintf(pszErr, cbErr, "Expected value at %zu on line %u", psz - szLine, iLine); return VERR_PARSE_ERROR; } /* * Detect attribute type and sanity check the value. */ uint32_t fType = RTMANIFEST_ATTR_UNKNOWN; static const struct { const char *pszAttr; uint32_t fType; unsigned cBits; unsigned uBase; } s_aDecAttrs[] = { { "SIZE", RTMANIFEST_ATTR_SIZE, 64, 10} }; for (unsigned i = 0; i < RT_ELEMENTS(s_aDecAttrs); i++) if (!strcmp(s_aDecAttrs[i].pszAttr, pszAttr)) { fType = s_aDecAttrs[i].fType; rc = RTStrToUInt64Full(pszValue, s_aDecAttrs[i].uBase, NULL); if (rc != VINF_SUCCESS) { RTStrPrintf(pszErr, cbErr, "Malformed value ('%s') at %zu on line %u: %Rrc", pszValue, psz - szLine, iLine, rc); return VERR_PARSE_ERROR; } break; } if (fType == RTMANIFEST_ATTR_UNKNOWN) { static const struct { const char *pszAttr; uint32_t fType; unsigned cchHex; } s_aHexAttrs[] = { { "MD5", RTMANIFEST_ATTR_MD5, RTMD5_DIGEST_LEN }, { "SHA1", RTMANIFEST_ATTR_SHA1, RTSHA1_DIGEST_LEN }, { "SHA256", RTMANIFEST_ATTR_SHA256, RTSHA256_DIGEST_LEN }, { "SHA512", RTMANIFEST_ATTR_SHA512, RTSHA512_DIGEST_LEN } }; for (unsigned i = 0; i < RT_ELEMENTS(s_aHexAttrs); i++) if (!strcmp(s_aHexAttrs[i].pszAttr, pszAttr)) { fType = s_aHexAttrs[i].fType; for (unsigned off = 0; off < s_aHexAttrs[i].cchHex; off++) if (!RT_C_IS_XDIGIT(pszValue[off])) { RTStrPrintf(pszErr, cbErr, "Expected hex digit at %zu on line %u (value '%s', pos %u)", pszValue - szLine + off, iLine, pszValue, off); return VERR_PARSE_ERROR; } break; } } /* * Finally, add it. */ rc = RTManifestEntrySetAttr(hManifest, pszName, pszAttr, pszValue, fType); if (RT_FAILURE(rc)) { RTStrPrintf(pszErr, cbErr, "RTManifestEntrySetAttr(,'%s','%s', '%s', %#x) failed on line %u: %Rrc", pszName, pszAttr, pszValue, fType, iLine, rc); return rc; } } }
RTDECL(int) RTMemCacheCreate(PRTMEMCACHE phMemCache, size_t cbObject, size_t cbAlignment, uint32_t cMaxObjects, PFNMEMCACHECTOR pfnCtor, PFNMEMCACHEDTOR pfnDtor, void *pvUser, uint32_t fFlags) { AssertPtr(phMemCache); AssertPtrNull(pfnCtor); AssertPtrNull(pfnDtor); AssertReturn(!pfnDtor || pfnCtor, VERR_INVALID_PARAMETER); AssertReturn(cbObject > 0, VERR_INVALID_PARAMETER); AssertReturn(cbObject <= PAGE_SIZE / 8, VERR_INVALID_PARAMETER); AssertReturn(!fFlags, VERR_INVALID_PARAMETER); if (cbAlignment == 0) { if (cbObject <= 2) cbAlignment = cbObject; else if (cbObject <= 4) cbAlignment = 4; else if (cbObject <= 8) cbAlignment = 8; else if (cbObject <= 16) cbAlignment = 16; else if (cbObject <= 32) cbAlignment = 32; else cbAlignment = 64; } else { AssertReturn(!((cbAlignment - 1) & cbAlignment), VERR_NOT_POWER_OF_TWO); AssertReturn(cbAlignment <= 64, VERR_OUT_OF_RANGE); } /* * Allocate and initialize the instance memory. */ RTMEMCACHEINT *pThis = (RTMEMCACHEINT *)RTMemAlloc(sizeof(*pThis)); if (!pThis) return VERR_NO_MEMORY; int rc = RTCritSectInit(&pThis->CritSect); if (RT_FAILURE(rc)) { RTMemFree(pThis); return rc; } pThis->u32Magic = RTMEMCACHE_MAGIC; pThis->cbObject = (uint32_t)RT_ALIGN_Z(cbObject, cbAlignment); pThis->cbAlignment = (uint32_t)cbAlignment; pThis->cPerPage = (uint32_t)((PAGE_SIZE - RT_ALIGN_Z(sizeof(RTMEMCACHEPAGE), cbAlignment)) / pThis->cbObject); while ( RT_ALIGN_Z(sizeof(RTMEMCACHEPAGE), 8) + pThis->cPerPage * pThis->cbObject + RT_ALIGN(pThis->cPerPage, 64) / 8 * 2 > PAGE_SIZE) pThis->cPerPage--; pThis->cBits = RT_ALIGN(pThis->cPerPage, 64); pThis->cMax = cMaxObjects; pThis->fUseFreeList = cbObject >= sizeof(RTMEMCACHEFREEOBJ) && !pfnCtor && !pfnDtor; pThis->pPageHead = NULL; pThis->ppPageNext = &pThis->pPageHead; pThis->pfnCtor = pfnCtor; pThis->pfnDtor = pfnDtor; pThis->pvUser = pvUser; pThis->cTotal = 0; pThis->cFree = 0; pThis->pPageHint = NULL; pThis->pFreeTop = NULL; *phMemCache = pThis; return VINF_SUCCESS; }
/** * Runs a process, collecting the standard output and/or standard error. * * * @returns IPRT status code * @retval VERR_NO_TRANSLATION if the output of the program isn't valid UTF-8 * or contains a nul character. * @retval VERR_TOO_MUCH_DATA if the process produced too much data. * * @param pszExec Executable image to use to create the child process. * @param papszArgs Pointer to an array of arguments to the child. The * array terminated by an entry containing NULL. * @param hEnv Handle to the environment block for the child. * @param fFlags A combination of RTPROCEXEC_FLAGS_XXX. The @a * ppszStdOut and @a ppszStdErr parameters takes precedence * over redirection flags. * @param pStatus Where to return the status on success. * @param ppszStdOut Where to return the text written to standard output. If * NULL then standard output will not be collected and go * to the standard output handle of the process. * Free with RTStrFree, regardless of return status. * @param ppszStdErr Where to return the text written to standard error. If * NULL then standard output will not be collected and go * to the standard error handle of the process. * Free with RTStrFree, regardless of return status. */ int RTProcExecToString(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags, PRTPROCSTATUS pStatus, char **ppszStdOut, char **ppszStdErr) { int rc2; /* * Clear output arguments (no returning failure here, simply crash!). */ AssertPtr(pStatus); pStatus->enmReason = RTPROCEXITREASON_ABEND; pStatus->iStatus = RTEXITCODE_FAILURE; AssertPtrNull(ppszStdOut); if (ppszStdOut) *ppszStdOut = NULL; AssertPtrNull(ppszStdOut); if (ppszStdErr) *ppszStdErr = NULL; /* * Check input arguments. */ AssertReturn(!(fFlags & ~RTPROCEXEC_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER); /* * Do we need a standard input bitbucket? */ int rc = VINF_SUCCESS; PRTHANDLE phChildStdIn = NULL; RTHANDLE hChildStdIn; hChildStdIn.enmType = RTHANDLETYPE_FILE; hChildStdIn.u.hFile = NIL_RTFILE; if ((fFlags & RTPROCEXEC_FLAGS_STDIN_NULL) && RT_SUCCESS(rc)) { phChildStdIn = &hChildStdIn; rc = RTFileOpenBitBucket(&hChildStdIn.u.hFile, RTFILE_O_READ); } /* * Create the output pipes / bitbuckets. */ RTPIPE hPipeStdOutR = NIL_RTPIPE; PRTHANDLE phChildStdOut = NULL; RTHANDLE hChildStdOut; hChildStdOut.enmType = RTHANDLETYPE_PIPE; hChildStdOut.u.hPipe = NIL_RTPIPE; if (ppszStdOut && RT_SUCCESS(rc)) { phChildStdOut = &hChildStdOut; rc = RTPipeCreate(&hPipeStdOutR, &hChildStdOut.u.hPipe, 0 /*fFlags*/); } else if ((fFlags & RTPROCEXEC_FLAGS_STDOUT_NULL) && RT_SUCCESS(rc)) { phChildStdOut = &hChildStdOut; hChildStdOut.enmType = RTHANDLETYPE_FILE; hChildStdOut.u.hFile = NIL_RTFILE; rc = RTFileOpenBitBucket(&hChildStdOut.u.hFile, RTFILE_O_WRITE); } RTPIPE hPipeStdErrR = NIL_RTPIPE; PRTHANDLE phChildStdErr = NULL; RTHANDLE hChildStdErr; hChildStdErr.enmType = RTHANDLETYPE_PIPE; hChildStdErr.u.hPipe = NIL_RTPIPE; if (ppszStdErr && RT_SUCCESS(rc)) { phChildStdErr = &hChildStdErr; rc = RTPipeCreate(&hPipeStdErrR, &hChildStdErr.u.hPipe, 0 /*fFlags*/); } else if ((fFlags & RTPROCEXEC_FLAGS_STDERR_NULL) && RT_SUCCESS(rc)) { phChildStdErr = &hChildStdErr; hChildStdErr.enmType = RTHANDLETYPE_FILE; hChildStdErr.u.hFile = NIL_RTFILE; rc = RTFileOpenBitBucket(&hChildStdErr.u.hFile, RTFILE_O_WRITE); } if (RT_SUCCESS(rc)) { RTPOLLSET hPollSet; rc = RTPollSetCreate(&hPollSet); if (RT_SUCCESS(rc)) { if (hPipeStdOutR != NIL_RTPIPE && RT_SUCCESS(rc)) rc = RTPollSetAddPipe(hPollSet, hPipeStdOutR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 1); if (hPipeStdErrR != NIL_RTPIPE) rc = RTPollSetAddPipe(hPollSet, hPipeStdErrR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 2); } if (RT_SUCCESS(rc)) { /* * Create the process. */ RTPROCESS hProc; rc = RTProcCreateEx(g_szSvnPath, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL /*phStdIn*/, phChildStdOut, phChildStdErr, NULL /*pszAsUser*/, NULL /*pszPassword*/, &hProc); rc2 = RTHandleClose(&hChildStdErr); AssertRC(rc2); rc2 = RTHandleClose(&hChildStdOut); AssertRC(rc2); if (RT_SUCCESS(rc)) { /* * Process output and wait for the process to finish. */ size_t cbStdOut = 0; size_t offStdOut = 0; size_t cbStdErr = 0; size_t offStdErr = 0; for (;;) { if (hPipeStdOutR != NIL_RTPIPE) rc = rtProcProcessOutput(rc, &hPipeStdOutR, &cbStdOut, &offStdOut, ppszStdOut, hPollSet, 1); if (hPipeStdErrR != NIL_RTPIPE) rc = rtProcProcessOutput(rc, &hPipeStdErrR, &cbStdErr, &offStdErr, ppszStdErr, hPollSet, 2); if (hPipeStdOutR == NIL_RTPIPE && hPipeStdErrR == NIL_RTPIPE) break; if (hProc != NIL_RTPROCESS) { rc2 = RTProcWait(hProc, RTPROCWAIT_FLAGS_NOBLOCK, pStatus); if (rc2 != VERR_PROCESS_RUNNING) { if (RT_FAILURE(rc2)) rc = rc2; hProc = NIL_RTPROCESS; } } rc2 = RTPoll(hPollSet, 10000, NULL, NULL); Assert(RT_SUCCESS(rc2) || rc2 == VERR_TIMEOUT); } if (RT_SUCCESS(rc)) { if ( (ppszStdOut && *ppszStdOut && !RTStrIsValidEncoding(*ppszStdOut)) || (ppszStdErr && *ppszStdErr && !RTStrIsValidEncoding(*ppszStdErr)) ) rc = VERR_NO_TRANSLATION; } /* * No more output, just wait for it to finish. */ if (hProc != NIL_RTPROCESS) { rc2 = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, pStatus); if (RT_FAILURE(rc2)) rc = rc2; } } RTPollSetDestroy(hPollSet); } } rc2 = RTHandleClose(&hChildStdErr); AssertRC(rc2); rc2 = RTHandleClose(&hChildStdOut); AssertRC(rc2); rc2 = RTHandleClose(&hChildStdIn); AssertRC(rc2); rc2 = RTPipeClose(hPipeStdErrR); AssertRC(rc2); rc2 = RTPipeClose(hPipeStdOutR); AssertRC(rc2); return rc; }
RTDECL(int) RTMemCacheCreate(PRTMEMCACHE phMemCache, size_t cbObject, size_t cbAlignment, uint32_t cMaxObjects, PFNMEMCACHECTOR pfnCtor, PFNMEMCACHEDTOR pfnDtor, void *pvUser, uint32_t fFlags) { AssertPtr(phMemCache); AssertPtrNull(pfnCtor); AssertPtrNull(pfnDtor); AssertReturn(!pfnDtor || pfnCtor, VERR_INVALID_PARAMETER); AssertReturn(cbObject > 0, VERR_INVALID_PARAMETER); AssertReturn(cbObject <= PAGE_SIZE / 8, VERR_INVALID_PARAMETER); AssertReturn(!fFlags, VERR_INVALID_PARAMETER); if (cbAlignment == 0) { if (cbObject <= 2) cbAlignment = cbObject; else if (cbObject <= 4) cbAlignment = 4; else if (cbObject <= 8) cbAlignment = 8; else if (cbObject <= 16) cbAlignment = 16; else if (cbObject <= 32) cbAlignment = 32; else cbAlignment = 64; } else { AssertReturn(!((cbAlignment - 1) & cbAlignment), VERR_NOT_POWER_OF_TWO); AssertReturn(cbAlignment <= 64, VERR_OUT_OF_RANGE); } /* * Allocate and initialize the instance memory. */ RTMEMCACHEINT *pThis = (RTMEMCACHEINT *)RTMemAlloc(sizeof(*pThis)); if (!pThis) return VERR_NO_MEMORY; int rc = RTCritSectInit(&pThis->CritSect); if (RT_FAILURE(rc)) { RTMemFree(pThis); return rc; } pThis->u32Magic = RTMEMCACHE_MAGIC; pThis->cbObject = (uint32_t)RT_ALIGN_Z(cbObject, cbAlignment); pThis->cbAlignment = (uint32_t)cbAlignment; pThis->cPerPage = (uint32_t)((PAGE_SIZE - RT_ALIGN_Z(sizeof(RTMEMCACHEPAGE), cbAlignment)) / pThis->cbObject); while ( RT_ALIGN_Z(sizeof(RTMEMCACHEPAGE), 8) + pThis->cPerPage * pThis->cbObject + RT_ALIGN(pThis->cPerPage, 64) / 8 * 2 > PAGE_SIZE) pThis->cPerPage--; pThis->cBits = RT_ALIGN(pThis->cPerPage, 64); pThis->cMax = cMaxObjects; pThis->fUseFreeList = cbObject >= sizeof(RTMEMCACHEFREEOBJ) && !pfnCtor && !pfnDtor; pThis->pPageHead = NULL; pThis->pfnCtor = pfnCtor; pThis->pfnDtor = pfnDtor; pThis->pvUser = pvUser; pThis->cTotal = 0; pThis->cFree = 0; pThis->pPageHint = NULL; pThis->pFreeTop = NULL; /** @todo * Here is a puzzler (or maybe I'm just blind), the free list code breaks * badly on my macbook pro (i7) (32-bit). * * I tried changing the reads from unordered to ordered to no avail. Then I * tried optimizing the code with the ASMAtomicCmpXchgExPtr function to * avoid some reads - no change. Inserting pause instructions did nothing * (as expected). The only thing which seems to make a difference is * reading the pFreeTop pointer twice in the free code... This is weird or I'm * overlooking something.. * * No time to figure it out, so I'm disabling the broken code paths for * now. */ pThis->fUseFreeList = false; *phMemCache = pThis; return VINF_SUCCESS; }