int GuestCtrlCallback::Init(eVBoxGuestCtrlCallbackType enmType) { LogFlowFuncEnter(); AssertReturn(enmType > VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN, VERR_INVALID_PARAMETER); Assert((pvData == NULL) && !cbData); switch (enmType) { case VBOXGUESTCTRLCALLBACKTYPE_EXEC_START: { pvData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS)); AssertPtrReturn(pvData, VERR_NO_MEMORY); RT_BZERO(pvData, sizeof(CALLBACKDATAEXECSTATUS)); cbData = sizeof(CALLBACKDATAEXECSTATUS); break; } case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT: { pvData = (PCALLBACKDATAEXECOUT)RTMemAlloc(sizeof(CALLBACKDATAEXECOUT)); AssertPtrReturn(pvData, VERR_NO_MEMORY); RT_BZERO(pvData, sizeof(CALLBACKDATAEXECOUT)); cbData = sizeof(CALLBACKDATAEXECOUT); break; } case VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS: { PCALLBACKDATAEXECINSTATUS pData = (PCALLBACKDATAEXECINSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECINSTATUS)); AssertPtrReturn(pData, VERR_NO_MEMORY); RT_BZERO(pData, sizeof(CALLBACKDATAEXECINSTATUS)); cbData = sizeof(CALLBACKDATAEXECINSTATUS); break; } default: AssertMsgFailed(("Unknown callback type specified (%d)\n", enmType)); break; } int rc = GuestCtrlEvent::Init(); if (RT_SUCCESS(rc)) mType = enmType; LogFlowFuncLeaveRC(rc); return rc; }
/** * Allocates memory from the specified heap. * * @returns Address of the allocated memory. * @param cb The number of bytes to allocate. * @param pszTag The tag. * @param fZero Whether to zero the memory or not. * @param fProtExec PROT_EXEC or 0. */ static void *rtMemPagePosixAlloc(size_t cb, const char *pszTag, bool fZero, int fProtExec) { /* * Validate & adjust the input. */ Assert(cb > 0); NOREF(pszTag); cb = RT_ALIGN_Z(cb, PAGE_SIZE); /* * Do the allocation. */ void *pv = mmap(NULL, cb, PROT_READ | PROT_WRITE | fProtExec, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (pv != MAP_FAILED) { AssertPtr(pv); if (fZero) RT_BZERO(pv, cb); } else pv = NULL; return pv; }
int DumpHtml(char* src, size_t cb) { size_t lenght = 0; int rc = RTStrNLenEx(src, cb, &lenght); if (RT_SUCCESS(rc)) { char* buf = (char*)RTMemAlloc(cb + 1); if (buf != NULL) { RT_BZERO(buf, cb + 1); rc = RTStrCopy(buf, cb, (const char*)src); if (RT_SUCCESS(rc)) { for (int i = 0; i < cb; ++i) { if (buf[i] == '\n' || buf[i] == '\r') buf[i] = ' '; } } else { Log(("Error in copying string.\n")); } Log(("Removed \\r\\n: %s\n", buf)); RTMemFree(buf); } else { rc = VERR_NO_MEMORY; Log(("Not enough memory to allocate buffer.\n")); } } return rc; }
static int rtTarAppendZeros(PRTTARFILEINTERNAL pFileInt, uint64_t cbSize) { /* Allocate a temporary buffer for copying the tar content in blocks. */ size_t cbTmp = 0; void *pvTmp = rtTarMemTmpAlloc(&cbTmp); if (!pvTmp) return VERR_NO_MEMORY; RT_BZERO(pvTmp, cbTmp); int rc = VINF_SUCCESS; uint64_t cbAllWritten = 0; size_t cbWritten = 0; for (;;) { if (cbAllWritten >= cbSize) break; size_t cbToWrite = RT_MIN(cbSize - cbAllWritten, cbTmp); rc = RTTarFileWriteAt(pFileInt, pFileInt->offCurrent, pvTmp, cbToWrite, &cbWritten); if (RT_FAILURE(rc)) break; cbAllWritten += cbWritten; } RTMemTmpFree(pvTmp); return rc; }
RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char *pszLogMsg) { AssertPtrReturn(pszLogMsg, VERR_INVALID_POINTER); AssertReturn(!(fFlags & ~RTSYSTEM_SHUTDOWN_VALID_MASK), VERR_INVALID_PARAMETER); /* * Assemble the argument vector. */ int iArg = 0; const char *apszArgs[6]; RT_BZERO(apszArgs, sizeof(apszArgs)); apszArgs[iArg++] = "/sbin/shutdown"; switch (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK) { case RTSYSTEM_SHUTDOWN_HALT: apszArgs[iArg++] = "-h"; apszArgs[iArg++] = "-H"; break; case RTSYSTEM_SHUTDOWN_REBOOT: apszArgs[iArg++] = "-r"; break; case RTSYSTEM_SHUTDOWN_POWER_OFF: case RTSYSTEM_SHUTDOWN_POWER_OFF_HALT: apszArgs[iArg++] = "-h"; apszArgs[iArg++] = "-P"; break; } char szWhen[80]; if (cMsDelay < 500) strcpy(szWhen, "now"); else RTStrPrintf(szWhen, sizeof(szWhen), "%u", (unsigned)((cMsDelay + 499) / 1000)); apszArgs[iArg++] = szWhen; apszArgs[iArg++] = pszLogMsg; /* * Start the shutdown process and wait for it to complete. */ RTPROCESS hProc; int rc = RTProcCreate(apszArgs[0], apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &hProc); if (RT_FAILURE(rc)) return rc; RTPROCSTATUS ProcStatus; rc = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus); if (RT_SUCCESS(rc)) { if ( ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) rc = VERR_SYS_SHUTDOWN_FAILED; } return rc; }
static void testCopy1(RTTEST hTest) { RTTestISub("RTStrCopy"); char *pszBuf4H = (char *)RTTestGuardedAllocHead(hTest, 4); char *pszBuf4T = (char *)RTTestGuardedAllocTail(hTest, 4); RTTESTI_CHECK_RC(RTStrCopy(pszBuf4H, 4, "abc"), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCopy(pszBuf4T, 4, "abc"), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); RT_BZERO(pszBuf4H, 4); RT_BZERO(pszBuf4T, 4); RTTESTI_CHECK_RC(RTStrCopy(pszBuf4H, 4, "abcd"), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCopy(pszBuf4T, 4, "abcd"), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); }
HRESULT VBoxCredProvCredential::kerberosLogonSerialize(const KERB_INTERACTIVE_LOGON *pLogonIn, PBYTE *ppPackage, DWORD *pcbPackage) { AssertPtrReturn(pLogonIn, E_INVALIDARG); AssertPtrReturn(ppPackage, E_INVALIDARG); AssertPtrReturn(pcbPackage, E_INVALIDARG); /* * First, allocate enough space for the logon structure itself and separate * string buffers right after it to store the actual user, password and domain * credentials. */ DWORD cbLogon = sizeof(KERB_INTERACTIVE_UNLOCK_LOGON) + pLogonIn->LogonDomainName.Length + + pLogonIn->UserName.Length + + pLogonIn->Password.Length; #ifdef DEBUG VBoxCredProvVerbose(3, "VBoxCredProvCredential::AllocateLogonPackage: Allocating %ld bytes (%d bytes credentials)\n", cbLogon, cbLogon - sizeof(KERB_INTERACTIVE_UNLOCK_LOGON)); #endif KERB_INTERACTIVE_UNLOCK_LOGON *pLogon = (KERB_INTERACTIVE_UNLOCK_LOGON*)CoTaskMemAlloc(cbLogon); if (!pLogon) return E_OUTOFMEMORY; /* Let our byte buffer point to the end of our allocated structure so that it can * be used to store the credential data sequentially in a binary blob * (without terminating \0). */ PBYTE pbBuffer = (PBYTE)pLogon + sizeof(KERB_INTERACTIVE_UNLOCK_LOGON); /* The buffer of the packed destination string does not contain the actual * string content but a relative offset starting at the given * KERB_INTERACTIVE_UNLOCK_LOGON structure. */ #define KERB_CRED_INIT_PACKED(StringDst, StringSrc, LogonOffset) \ StringDst.Length = StringSrc.Length; \ StringDst.MaximumLength = StringSrc.Length; \ StringDst.Buffer = (PWSTR)pbBuffer; \ memcpy(StringDst.Buffer, StringSrc.Buffer, StringDst.Length); \ StringDst.Buffer = (PWSTR)(pbBuffer - (PBYTE)LogonOffset); \ pbBuffer += StringDst.Length; RT_BZERO(&pLogon->LogonId, sizeof(LUID)); KERB_INTERACTIVE_LOGON *pLogonOut = &pLogon->Logon; pLogonOut->MessageType = pLogonIn->MessageType; KERB_CRED_INIT_PACKED(pLogonOut->LogonDomainName, pLogonIn->LogonDomainName, pLogon); KERB_CRED_INIT_PACKED(pLogonOut->UserName , pLogonIn->UserName, pLogon); KERB_CRED_INIT_PACKED(pLogonOut->Password , pLogonIn->Password, pLogon); *ppPackage = (PBYTE)pLogon; *pcbPackage = cbLogon; #undef KERB_CRED_INIT_PACKED return S_OK; }
VBoxCredProvCredential::VBoxCredProvCredential(void) : m_enmUsageScenario(CPUS_INVALID), m_cRefs(1), m_pEvents(NULL), m_fHaveCreds(false) { VBoxCredProvVerbose(0, "VBoxCredProvCredential: Created\n"); VBoxCredentialProviderAcquire(); RT_BZERO(m_apwszCredentials, sizeof(PRTUTF16) * VBOXCREDPROV_NUM_FIELDS); }
/* * Converts clipboard data from CF_HTML format to mimie clipboard format * Returns allocated buffer that contains html converted to text/html mime type * return result code * parameters - output buffer and size of output buffer * It allocates the buffer needed for storing converted fragment * Allocated buffer should be destroyed by RTMemFree after usage */ int ConvertCFHtmlToMime(const char *pcszSource, const uint32_t cch, char **ppszOutput, size_t *pcCh) { char* result = NULL; Assert(pcszSource); Assert(cch); Assert(ppszOutput); Assert(pcCh); size_t cStartOffset, cEndOffset; int rc = GetHeaderValue(pcszSource, "StartFragment:", &cStartOffset); if (!RT_SUCCESS(rc)) { LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc.\n", rc)); return VERR_INVALID_PARAMETER; } rc = GetHeaderValue(pcszSource, "EndFragment:", &cEndOffset); if (!RT_SUCCESS(rc)) { LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc.\n", rc)); return VERR_INVALID_PARAMETER; } if (cStartOffset > 0 && cEndOffset > 0 && cEndOffset > cStartOffset) { size_t cSubstrlen = cEndOffset - cStartOffset; result = (char*)RTMemAlloc(cSubstrlen + 1); if (result) { RT_BZERO(result, cSubstrlen + 1); rc = RTStrCopyEx(result, cSubstrlen + 1, pcszSource + cStartOffset, cSubstrlen); if (RT_SUCCESS(rc)) { *ppszOutput = result; *pcCh = cSubstrlen + 1; } else { LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc)); return rc; } } else { LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment.\n")); return VERR_NO_MEMORY; } } return VINF_SUCCESS; }
RTDECL(int) RTCrDigestReset(RTCRDIGEST hDigest) { PRTCRDIGESTINT pThis = hDigest; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, VERR_INVALID_HANDLE); pThis->cbConsumed = 0; pThis->uState = RTCRDIGEST_STATE_READY; int rc = VINF_SUCCESS; if (pThis->pDesc->pfnInit) { rc = pThis->pDesc->pfnInit(pThis->pvState, NULL, true /*fReInit*/); if (RT_FAILURE(rc)) pThis->uState = RTCRDIGEST_STATE_BUSTED; RT_BZERO(&pThis->abState[pThis->offHash], pThis->pDesc->cbHash); } else { Assert(!pThis->pDesc->pfnNew); RT_BZERO(pThis->pvState, pThis->offHash + pThis->pDesc->cbHash); } return rc; }
DECLCALLBACK(void) VBoxClipboardDestroy(void *pInstance) { AssertPtrReturnVoid(pInstance); PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)pInstance; AssertPtr(pCtx); /* Make sure that we are disconnected. */ Assert(pCtx->u32ClientID == 0); vboxClipboardDestroy(pCtx); RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT)); return; }
RTDECL(int) RTAsn1MemGrowArray(PRTASN1ALLOCATION pAllocation, void **ppvArray, size_t cbEntry, uint32_t cCurrent, uint32_t cNew) { AssertReturn(pAllocation->pAllocator != NULL, VERR_WRONG_ORDER); AssertReturn(cbEntry > 0, VERR_INVALID_PARAMETER); AssertReturn(cNew > cCurrent, VERR_INVALID_PARAMETER); AssertReturn(cNew < _1M, VERR_OUT_OF_RANGE); pAllocation->cReallocs++; void *pvOld = *ppvArray; /* Initial allocation? */ if (cCurrent == 0) { AssertReturn(pvOld == NULL, VERR_INVALID_PARAMETER); AssertReturn(cNew != 0, VERR_INVALID_PARAMETER); return pAllocation->pAllocator->pfnAlloc(pAllocation->pAllocator, pAllocation, ppvArray, cNew * cbEntry); } /* Do we need to grow the allocation or did we already allocate sufficient memory in a previous call? */ size_t cbNew = cNew * cbEntry; if (pAllocation->cbAllocated < cbNew) { /* Need to grow. Adjust the new size according to how many times we've been called. */ if (pAllocation->cReallocs > 2) { if (pAllocation->cReallocs > 8) cNew += 8; else if (pAllocation->cReallocs < 4) cNew += 2; else cNew += 4; cbNew += cNew * cbEntry; } int rc = pAllocation->pAllocator->pfnRealloc(pAllocation->pAllocator, pAllocation, pvOld, ppvArray, cbNew); if (RT_FAILURE(rc)) return rc; Assert(pAllocation->cbAllocated >= cbNew); /* Clear the memory. */ size_t cbOld = cCurrent * cbEntry; RT_BZERO((uint8_t *)*ppvArray + cbOld, pAllocation->cbAllocated - cbOld); } return VINF_SUCCESS; }
void vboxClipboardDump(const void *pv, size_t cb, uint32_t u32Format) { if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { Log(("DUMP: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT:\n")); if (pv && cb) { Log(("%ls\n", pv)); } else { Log(("%p %d\n", pv, cb)); } } else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { dprintf(("DUMP: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n")); } else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML) { Log(("DUMP: VBOX_SHARED_CLIPBOARD_FMT_HTML:\n")); if (pv && cb) { Log(("%s\n", pv)); //size_t cb = RTStrNLen(pv, ); char* buf = (char*)RTMemAlloc(cb + 1); RT_BZERO(buf, cb); RTStrCopy(buf, cb, (const char*)pv); for (int i = 0; i < cb; ++i) { if (buf[i] == '\n' || buf[i] == '\r') buf[i] = ' '; } Log(("%s\n", buf)); RTMemFree(buf); } else { Log(("%p %d\n", pv, cb)); } } else { dprintf(("DUMP: invalid format %02X\n", u32Format)); } }
/** * Avoids some gotos in rtHeapPageAllocFromBlock. * * @returns VINF_SUCCESS. * @param pBlock The block. * @param iPage The page to start allocating at. * @param cPages The number of pages. * @param fZero Whether to clear them. * @param ppv Where to return the allocation address. */ DECLINLINE(int) rtHeapPageAllocFromBlockSuccess(PRTHEAPPAGEBLOCK pBlock, uint32_t iPage, size_t cPages, bool fZero, void **ppv) { PRTHEAPPAGE pHeap = pBlock->pHeap; ASMBitSet(&pBlock->bmFirst[0], iPage); pBlock->cFreePages -= cPages; pHeap->cFreePages -= cPages; if (!pHeap->pHint2 || pHeap->pHint2->cFreePages < pBlock->cFreePages) pHeap->pHint2 = pBlock; pHeap->cAllocCalls++; void *pv = (uint8_t *)pBlock->Core.Key + (iPage << PAGE_SHIFT); *ppv = pv; if (fZero) RT_BZERO(pv, cPages << PAGE_SHIFT); return VINF_SUCCESS; }
DECLCALLBACK(int) VBoxClipboardInit(const PVBOXSERVICEENV pEnv, void **ppInstance) { LogFlowFuncEnter(); PVBOXCLIPBOARDCONTEXT pCtx = &g_Ctx; /* Only one instance for now. */ AssertPtr(pCtx); if (pCtx->pEnv) { /* Clipboard was already initialized. 2 or more instances are not supported. */ return VERR_NOT_SUPPORTED; } if (VbglR3AutoLogonIsRemoteSession()) { /* Do not use clipboard for remote sessions. */ LogRel(("Clipboard: Clipboard has been disabled for a remote session\n")); return VERR_NOT_SUPPORTED; } RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT)); pCtx->pEnv = pEnv; /* Check that new Clipboard API is available */ VBoxClipboardWinCheckAndInitNewAPI(&pCtx->Win.newAPI); int rc = VbglR3ClipboardConnect(&pCtx->u32ClientID); if (RT_SUCCESS(rc)) { rc = vboxClipboardCreateWindow(pCtx); if (RT_SUCCESS(rc)) { *ppInstance = pCtx; } else { VbglR3ClipboardDisconnect(pCtx->u32ClientID); } } LogFlowFuncLeaveRC(rc); return rc; }
static SHFLROOT initWithWritableMapping(RTTEST hTest, VBOXHGCMSVCFNTABLE *psvcTable, VBOXHGCMSVCHELPERS *psvcHelpers, const char *pcszFolderName, const char *pcszMapping) { VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_ADD_MAPPING, SHFL_CPARMS_MAP_FOLDER)]; struct TESTSHFLSTRING FolderName; struct TESTSHFLSTRING Mapping; VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; int rc; initTable(psvcTable, psvcHelpers); AssertReleaseRC(VBoxHGCMSvcLoad(psvcTable)); AssertRelease( psvcTable->pvService = RTTestGuardedAllocTail(hTest, psvcTable->cbClient)); RT_BZERO(psvcTable->pvService, psvcTable->cbClient); fillTestShflString(&FolderName, pcszFolderName); fillTestShflString(&Mapping, pcszMapping); aParms[0].setPointer(&FolderName, RT_UOFFSETOF(SHFLSTRING, String) + FolderName.string.u16Size); aParms[1].setPointer(&Mapping, RT_UOFFSETOF(SHFLSTRING, String) + Mapping.string.u16Size); aParms[2].setUInt32(1); rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_ADD_MAPPING, SHFL_CPARMS_ADD_MAPPING, aParms); AssertReleaseRC(rc); aParms[0].setPointer(&Mapping, RT_UOFFSETOF(SHFLSTRING, String) + Mapping.string.u16Size); aParms[1].setUInt32(0); /* root */ aParms[2].setUInt32('/'); /* delimiter */ aParms[3].setUInt32(1); /* case sensitive */ psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0, psvcTable->pvService, SHFL_FN_MAP_FOLDER, SHFL_CPARMS_MAP_FOLDER, aParms); AssertReleaseRC(callHandle.rc); return aParms[1].u.uint32; }
/** * Applies flags to an allocation. * * @param pv The allocation. * @param cb The size of the allocation (page aligned). * @param fFlags RTMEMPAGEALLOC_F_XXX. */ DECLINLINE(void) rtMemPagePosixApplyFlags(void *pv, size_t cb, uint32_t fFlags) { #ifndef RT_OS_OS2 if (fFlags & RTMEMPAGEALLOC_F_ADVISE_LOCKED) { int rc = mlock(pv, cb); AssertMsg(rc == 0, ("mlock %p LB %#zx -> %d errno=%d\n", pv, cb, rc, errno)); NOREF(rc); } # ifdef MADV_DONTDUMP if (fFlags & RTMEMPAGEALLOC_F_ADVISE_NO_DUMP) { int rc = madvise(pv, cb, MADV_DONTDUMP); AssertMsg(rc == 0, ("madvice %p LB %#zx MADV_DONTDUMP -> %d errno=%d\n", pv, cb, rc, errno)); NOREF(rc); } # endif #endif if (fFlags & RTMEMPAGEALLOC_F_ZERO) RT_BZERO(pv, cb); }
/** * Retrieves a descriptor of a specified field. * * @return HRESULT * @param dwIndex ID of field to retrieve descriptor for. * @param ppFieldDescriptor Pointer which receives the allocated field * descriptor. */ HRESULT VBoxCredProvProvider::GetFieldDescriptorAt(DWORD dwIndex, CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppFieldDescriptor) { HRESULT hr = S_OK; if ( dwIndex < VBOXCREDPROV_NUM_FIELDS && ppFieldDescriptor) { PCREDENTIAL_PROVIDER_FIELD_DESCRIPTOR pcpFieldDesc = (PCREDENTIAL_PROVIDER_FIELD_DESCRIPTOR)CoTaskMemAlloc(sizeof(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR)); if (pcpFieldDesc) { const VBOXCREDPROV_FIELD &field = s_VBoxCredProvFields[dwIndex]; RT_BZERO(pcpFieldDesc, sizeof(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR)); pcpFieldDesc->dwFieldID = field.desc.dwFieldID; pcpFieldDesc->cpft = field.desc.cpft; if (field.desc.pszLabel) hr = SHStrDupW(field.desc.pszLabel, &pcpFieldDesc->pszLabel); } else hr = E_OUTOFMEMORY; if (SUCCEEDED(hr)) *ppFieldDescriptor = pcpFieldDesc; else CoTaskMemFree(pcpFieldDesc); } else hr = E_INVALIDARG; VBoxCredProvVerbose(0, "VBoxCredProv::GetFieldDescriptorAt: dwIndex=%ld, ppDesc=0x%p, hr=0x%08x\n", dwIndex, ppFieldDescriptor, hr); return hr; }
/** * Retrieves a descriptor of a specified field. * * @return HRESULT * @param dwIndex ID of field to retrieve descriptor for. * @param ppFieldDescriptor Pointer which receives the allocated field * descriptor. */ HRESULT VBoxCredProvProvider::GetFieldDescriptorAt(DWORD dwIndex, CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppFieldDescriptor) { HRESULT hr = S_OK; if ( dwIndex < VBOXCREDPROV_NUM_FIELDS && ppFieldDescriptor) { PCREDENTIAL_PROVIDER_FIELD_DESCRIPTOR pcpFieldDesc = (PCREDENTIAL_PROVIDER_FIELD_DESCRIPTOR)CoTaskMemAlloc(sizeof(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR)); if (pcpFieldDesc) { const VBOXCREDPROV_FIELD &field = s_VBoxCredProvDefaultFields[dwIndex]; RT_BZERO(pcpFieldDesc, sizeof(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR)); pcpFieldDesc->dwFieldID = field.desc.dwFieldID; pcpFieldDesc->cpft = field.desc.cpft; PCRTUTF16 pcwszField = NULL; if (dwIndex != VBOXCREDPROV_FIELDID_PASSWORD) /* Don't ever get any password. Never ever, ever. */ { if (m_pCred) /* If we have retrieved credentials, get the actual (current) value. */ pcwszField = m_pCred->getField(dwIndex); else /* Otherwise get the default value. */ pcwszField = field.desc.pszLabel; } hr = SHStrDupW(pcwszField ? pcwszField : L"", &pcpFieldDesc->pszLabel); VBoxCredProvVerbose(0, "VBoxCredProv::GetFieldDescriptorAt: dwIndex=%ld, pszLabel=%ls, hr=0x%08x\n", dwIndex, #ifdef DEBUG /* Don't show any (sensitive data) in release mode. */ pcwszField ? pcwszField : L"", #else L"XXX", #endif hr); pcpFieldDesc->guidFieldType = field.desc.guidFieldType; } else hr = E_OUTOFMEMORY; if (SUCCEEDED(hr)) { *ppFieldDescriptor = pcpFieldDesc; } else if (pcpFieldDesc) { if (pcpFieldDesc->pszLabel) { CoTaskMemFree(pcpFieldDesc->pszLabel); pcpFieldDesc->pszLabel = NULL; } CoTaskMemFree(pcpFieldDesc); } } else hr = E_INVALIDARG; VBoxCredProvVerbose(0, "VBoxCredProv::GetFieldDescriptorAt: dwIndex=%ld, ppDesc=0x%p, hr=0x%08x\n", dwIndex, ppFieldDescriptor, hr); return hr; }
RTDECL(char *) RTUriCreate(const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery, const char *pszFragment) { if (!pszScheme) /* Scheme is minimum requirement */ return NULL; char *pszResult = 0; char *pszAuthority1 = 0; char *pszPath1 = 0; char *pszQuery1 = 0; char *pszFragment1 = 0; do { /* Create the percent encoded strings and calculate the necessary uri * length. */ size_t cbSize = strlen(pszScheme) + 1 + 1; /* plus zero byte */ if (pszAuthority) { pszAuthority1 = rtUriPercentEncodeN(pszAuthority, RTSTR_MAX); if (!pszAuthority1) break; cbSize += strlen(pszAuthority1) + 2; } if (pszPath) { pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX); if (!pszPath1) break; cbSize += strlen(pszPath1); } if (pszQuery) { pszQuery1 = rtUriPercentEncodeN(pszQuery, RTSTR_MAX); if (!pszQuery1) break; cbSize += strlen(pszQuery1) + 1; } if (pszFragment) { pszFragment1 = rtUriPercentEncodeN(pszFragment, RTSTR_MAX); if (!pszFragment1) break; cbSize += strlen(pszFragment1) + 1; } char *pszTmp = pszResult = (char *)RTStrAlloc(cbSize); if (!pszResult) break; RT_BZERO(pszTmp, cbSize); /* Compose the target uri string. */ RTStrCatP(&pszTmp, &cbSize, pszScheme); RTStrCatP(&pszTmp, &cbSize, ":"); if (pszAuthority1) { RTStrCatP(&pszTmp, &cbSize, "//"); RTStrCatP(&pszTmp, &cbSize, pszAuthority1); } if (pszPath1) { RTStrCatP(&pszTmp, &cbSize, pszPath1); } if (pszQuery1) { RTStrCatP(&pszTmp, &cbSize, "?"); RTStrCatP(&pszTmp, &cbSize, pszQuery1); } if (pszFragment1) { RTStrCatP(&pszTmp, &cbSize, "#"); RTStrCatP(&pszTmp, &cbSize, pszFragment1); } } while (0); /* Cleanup */ if (pszAuthority1) RTStrFree(pszAuthority1); if (pszPath1) RTStrFree(pszPath1); if (pszQuery1) RTStrFree(pszQuery1); if (pszFragment1) RTStrFree(pszFragment1); return pszResult; }
/** * Deal with the 'slow' I/O control requests. * * @returns 0 on success, appropriate errno on failure. * @param pSession The session. * @param ulCmd The command. * @param pvData The request data. * @param pTd The calling thread. */ static int vgdrvFreeBSDIOCtlSlow(PVBOXGUESTSESSION pSession, u_long ulCmd, caddr_t pvData, struct thread *pTd) { PVBGLREQHDR pHdr; uint32_t cbReq = IOCPARM_LEN(ulCmd); void *pvUser = NULL; /* * Buffered request? */ if ((IOC_DIRMASK & ulCmd) == IOC_INOUT) { pHdr = (PVBGLREQHDR)pvData; if (RT_UNLIKELY(cbReq < sizeof(*pHdr))) { LogRel(("vgdrvFreeBSDIOCtlSlow: cbReq=%#x < %#x; ulCmd=%#lx\n", cbReq, (int)sizeof(*pHdr), ulCmd)); return EINVAL; } if (RT_UNLIKELY(pHdr->uVersion != VBGLREQHDR_VERSION)) { LogRel(("vgdrvFreeBSDIOCtlSlow: bad uVersion=%#x; ulCmd=%#lx\n", pHdr->uVersion, ulCmd)); return EINVAL; } if (RT_UNLIKELY( RT_MAX(pHdr->cbIn, pHdr->cbOut) != cbReq || pHdr->cbIn < sizeof(*pHdr) || (pHdr->cbOut < sizeof(*pHdr) && pHdr->cbOut != 0))) { LogRel(("vgdrvFreeBSDIOCtlSlow: max(%#x,%#x) != %#x; ulCmd=%#lx\n", pHdr->cbIn, pHdr->cbOut, cbReq, ulCmd)); return EINVAL; } } /* * Big unbuffered request? */ else if ((IOC_DIRMASK & ulCmd) == IOC_VOID && !cbReq) { /* * Read the header, validate it and figure out how much that needs to be buffered. */ VBGLREQHDR Hdr; pvUser = *(void **)pvData; int rc = copyin(pvUser, &Hdr, sizeof(Hdr)); if (RT_UNLIKELY(rc)) { LogRel(("vgdrvFreeBSDIOCtlSlow: copyin(%p,Hdr,) -> %#x; ulCmd=%#lx\n", pvUser, rc, ulCmd)); return rc; } if (RT_UNLIKELY(Hdr.uVersion != VBGLREQHDR_VERSION)) { LogRel(("vgdrvFreeBSDIOCtlSlow: bad uVersion=%#x; ulCmd=%#lx\n", Hdr.uVersion, ulCmd)); return EINVAL; } cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut); if (RT_UNLIKELY( Hdr.cbIn < sizeof(Hdr) || (Hdr.cbOut < sizeof(Hdr) && Hdr.cbOut != 0) || cbReq > _1M*16)) { LogRel(("vgdrvFreeBSDIOCtlSlow: max(%#x,%#x); ulCmd=%#lx\n", Hdr.cbIn, Hdr.cbOut, ulCmd)); return EINVAL; } /* * Allocate buffer and copy in the data. */ pHdr = (PVBGLREQHDR)RTMemTmpAlloc(cbReq); if (RT_UNLIKELY(!pHdr)) { LogRel(("vgdrvFreeBSDIOCtlSlow: failed to allocate buffer of %d bytes; ulCmd=%#lx\n", cbReq, ulCmd)); return ENOMEM; } rc = copyin(pvUser, pHdr, Hdr.cbIn); if (RT_UNLIKELY(rc)) { LogRel(("vgdrvFreeBSDIOCtlSlow: copyin(%p,%p,%#x) -> %#x; ulCmd=%#lx\n", pvUser, pHdr, Hdr.cbIn, rc, ulCmd)); RTMemTmpFree(pHdr); return rc; } if (Hdr.cbIn < cbReq) RT_BZERO((uint8_t *)pHdr + Hdr.cbIn, cbReq - Hdr.cbIn); } else { Log(("vgdrvFreeBSDIOCtlSlow: huh? cbReq=%#x ulCmd=%#lx\n", cbReq, ulCmd)); return EINVAL; } /* * Process the IOCtl. */ int rc = VGDrvCommonIoCtl(ulCmd, &g_DevExt, pSession, pHdr, cbReq); if (RT_LIKELY(!rc)) { /* * If unbuffered, copy back the result before returning. */ if (pvUser) { uint32_t cbOut = pHdr->cbOut; if (cbOut > cbReq) { LogRel(("vgdrvFreeBSDIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbOut, cbReq, ulCmd)); cbOut = cbReq; } rc = copyout(pHdr, pvUser, cbOut); if (RT_UNLIKELY(rc)) LogRel(("vgdrvFreeBSDIOCtlSlow: copyout(%p,%p,%#x) -> %d; uCmd=%#lx!\n", pHdr, pvUser, cbOut, rc, ulCmd)); Log(("vgdrvFreeBSDIOCtlSlow: returns %d / %d ulCmd=%lx\n", 0, pHdr->rc, ulCmd)); /* cleanup */ RTMemTmpFree(pHdr); } } else { /* * The request failed, just clean up. */ if (pvUser) RTMemTmpFree(pHdr); Log(("vgdrvFreeBSDIOCtlSlow: ulCmd=%lx pData=%p failed, rc=%d\n", ulCmd, pvData, rc)); rc = EINVAL; } return rc; }
/** * Worker function for dbgfR3CoreWrite() which does the writing. * * @returns VBox status code * @param pVM Pointer to the VM. * @param hFile The file to write to. Caller closes this. */ static int dbgfR3CoreWriteWorker(PVM pVM, RTFILE hFile) { /* * Collect core information. */ uint32_t const cu32MemRanges = dbgfR3GetRamRangeCount(pVM); uint16_t const cMemRanges = cu32MemRanges < UINT16_MAX - 1 ? cu32MemRanges : UINT16_MAX - 1; /* One PT_NOTE Program header */ uint16_t const cProgHdrs = cMemRanges + 1; DBGFCOREDESCRIPTOR CoreDescriptor; RT_ZERO(CoreDescriptor); CoreDescriptor.u32Magic = DBGFCORE_MAGIC; CoreDescriptor.u32FmtVersion = DBGFCORE_FMT_VERSION; CoreDescriptor.cbSelf = sizeof(CoreDescriptor); CoreDescriptor.u32VBoxVersion = VBOX_FULL_VERSION; CoreDescriptor.u32VBoxRevision = VMMGetSvnRev(); CoreDescriptor.cCpus = pVM->cCpus; Log((DBGFLOG_NAME ": CoreDescriptor Version=%u Revision=%u\n", CoreDescriptor.u32VBoxVersion, CoreDescriptor.u32VBoxRevision)); /* * Compute the file layout (see pg_dbgf_vmcore). */ uint64_t const offElfHdr = RTFileTell(hFile); uint64_t const offNoteSection = offElfHdr + sizeof(Elf64_Ehdr); uint64_t const offLoadSections = offNoteSection + sizeof(Elf64_Phdr); uint64_t const cbLoadSections = cMemRanges * sizeof(Elf64_Phdr); uint64_t const offCoreDescriptor = offLoadSections + cbLoadSections; uint64_t const cbCoreDescriptor = Elf64NoteSectionSize(g_pcszCoreVBoxCore, sizeof(CoreDescriptor)); uint64_t const offCpuDumps = offCoreDescriptor + cbCoreDescriptor; uint64_t const cbCpuDumps = pVM->cCpus * Elf64NoteSectionSize(g_pcszCoreVBoxCpu, sizeof(DBGFCORECPU)); uint64_t const offMemory = offCpuDumps + cbCpuDumps; uint64_t const offNoteSectionData = offCoreDescriptor; uint64_t const cbNoteSectionData = cbCoreDescriptor + cbCpuDumps; /* * Write ELF header. */ int rc = Elf64WriteElfHdr(hFile, cProgHdrs, 0 /* cSecHdrs */); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WriteElfHdr failed. rc=%Rrc\n", rc)); return rc; } /* * Write PT_NOTE program header. */ Assert(RTFileTell(hFile) == offNoteSection); rc = Elf64WriteProgHdr(hFile, PT_NOTE, PF_R, offNoteSectionData, /* file offset to contents */ cbNoteSectionData, /* size in core file */ cbNoteSectionData, /* size in memory */ 0); /* physical address */ if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WritreProgHdr failed for PT_NOTE. rc=%Rrc\n", rc)); return rc; } /* * Write PT_LOAD program header for each memory range. */ Assert(RTFileTell(hFile) == offLoadSections); uint64_t offMemRange = offMemory; for (uint16_t iRange = 0; iRange < cMemRanges; iRange++) { RTGCPHYS GCPhysStart; RTGCPHYS GCPhysEnd; bool fIsMmio; rc = PGMR3PhysGetRange(pVM, iRange, &GCPhysStart, &GCPhysEnd, NULL /* pszDesc */, &fIsMmio); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": PGMR3PhysGetRange failed for iRange(%u) rc=%Rrc\n", iRange, rc)); return rc; } uint64_t cbMemRange = GCPhysEnd - GCPhysStart + 1; uint64_t cbFileRange = fIsMmio ? 0 : cbMemRange; Log((DBGFLOG_NAME ": PGMR3PhysGetRange iRange=%u GCPhysStart=%#x GCPhysEnd=%#x cbMemRange=%u\n", iRange, GCPhysStart, GCPhysEnd, cbMemRange)); rc = Elf64WriteProgHdr(hFile, PT_LOAD, PF_R, offMemRange, /* file offset to contents */ cbFileRange, /* size in core file */ cbMemRange, /* size in memory */ GCPhysStart); /* physical address */ if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WriteProgHdr failed for memory range(%u) cbFileRange=%u cbMemRange=%u rc=%Rrc\n", iRange, cbFileRange, cbMemRange, rc)); return rc; } offMemRange += cbFileRange; } /* * Write the Core descriptor note header and data. */ Assert(RTFileTell(hFile) == offCoreDescriptor); rc = Elf64WriteNoteHdr(hFile, NT_VBOXCORE, g_pcszCoreVBoxCore, &CoreDescriptor, sizeof(CoreDescriptor)); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WriteNoteHdr failed for Note '%s' rc=%Rrc\n", g_pcszCoreVBoxCore, rc)); return rc; } /* * Write the CPU context note headers and data. */ Assert(RTFileTell(hFile) == offCpuDumps); PDBGFCORECPU pDbgfCoreCpu = (PDBGFCORECPU)RTMemAlloc(sizeof(*pDbgfCoreCpu)); if (RT_UNLIKELY(!pDbgfCoreCpu)) { LogRel((DBGFLOG_NAME ": failed to alloc %u bytes for DBGFCORECPU\n", sizeof(*pDbgfCoreCpu))); return VERR_NO_MEMORY; } for (uint32_t iCpu = 0; iCpu < pVM->cCpus; iCpu++) { PVMCPU pVCpu = &pVM->aCpus[iCpu]; PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); if (RT_UNLIKELY(!pCtx)) { LogRel((DBGFLOG_NAME ": CPUMQueryGuestCtxPtr failed for vCPU[%u]\n", iCpu)); RTMemFree(pDbgfCoreCpu); return VERR_INVALID_POINTER; } RT_BZERO(pDbgfCoreCpu, sizeof(*pDbgfCoreCpu)); dbgfR3GetCoreCpu(pCtx, pDbgfCoreCpu); rc = Elf64WriteNoteHdr(hFile, NT_VBOXCPU, g_pcszCoreVBoxCpu, pDbgfCoreCpu, sizeof(*pDbgfCoreCpu)); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WriteNoteHdr failed for vCPU[%u] rc=%Rrc\n", iCpu, rc)); RTMemFree(pDbgfCoreCpu); return rc; } } RTMemFree(pDbgfCoreCpu); pDbgfCoreCpu = NULL; /* * Write memory ranges. */ Assert(RTFileTell(hFile) == offMemory); for (uint16_t iRange = 0; iRange < cMemRanges; iRange++) { RTGCPHYS GCPhysStart; RTGCPHYS GCPhysEnd; bool fIsMmio; rc = PGMR3PhysGetRange(pVM, iRange, &GCPhysStart, &GCPhysEnd, NULL /* pszDesc */, &fIsMmio); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": PGMR3PhysGetRange(2) failed for iRange(%u) rc=%Rrc\n", iRange, rc)); return rc; } if (fIsMmio) continue; /* * Write page-by-page of this memory range. * * The read function may fail on MMIO ranges, we write these as zero * pages for now (would be nice to have the VGA bits there though). */ uint64_t cbMemRange = GCPhysEnd - GCPhysStart + 1; uint64_t cPages = cbMemRange >> PAGE_SHIFT; for (uint64_t iPage = 0; iPage < cPages; iPage++) { uint8_t abPage[PAGE_SIZE]; rc = PGMPhysSimpleReadGCPhys(pVM, abPage, GCPhysStart + (iPage << PAGE_SHIFT), sizeof(abPage)); if (RT_FAILURE(rc)) { if (rc != VERR_PGM_PHYS_PAGE_RESERVED) LogRel((DBGFLOG_NAME ": PGMPhysRead failed for iRange=%u iPage=%u. rc=%Rrc. Ignoring...\n", iRange, iPage, rc)); RT_ZERO(abPage); } rc = RTFileWrite(hFile, abPage, sizeof(abPage), NULL /* all */); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": RTFileWrite failed. iRange=%u iPage=%u rc=%Rrc\n", iRange, iPage, rc)); return rc; } } } return rc; }
VBoxDnDDataObject::VBoxDnDDataObject(FORMATETC *pFormatEtc, STGMEDIUM *pStgMed, ULONG cFormats) : mStatus(Uninitialized), mRefCount(1), mcFormats(0), mpvData(NULL), mcbData(0) { HRESULT hr; /* Make sure that there's enough room for our fixed formats. */ ULONG cAllFormats = cFormats + 1; try { mpFormatEtc = new FORMATETC[cAllFormats]; RT_BZERO(mpFormatEtc, sizeof(FORMATETC) * cAllFormats); mpStgMedium = new STGMEDIUM[cAllFormats]; RT_BZERO(mpStgMedium, sizeof(STGMEDIUM) * cAllFormats); if ( pFormatEtc && pStgMed) { for (ULONG i = 0; i < cFormats; i++) { LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n", i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect)); mpFormatEtc[i] = pFormatEtc[i]; mpStgMedium[i] = pStgMed[i]; } } hr = S_OK; } catch (std::bad_alloc &) { hr = E_OUTOFMEMORY; } if (SUCCEEDED(hr)) { int rc2 = RTSemEventCreate(&mSemEvent); AssertRC(rc2); /* Most commonly used format. */ RegisterFormat(&mpFormatEtc[cFormats], CF_HDROP); mpStgMedium[cFormats++].tymed = TYMED_HGLOBAL; #if 0 /* IStream. */ RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)); RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_FILECONTENTS), TYMED_ISTREAM, 0 /* lIndex */); /* Required for e.g. Windows Media Player. */ RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_FILENAME)); RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_FILENAMEW)); RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_SHELLIDLIST)); RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET)); #endif mcFormats = cFormats; mStatus = Initialized; } LogFlowFunc(("cFormats=%RU32, hr=%Rhrc\n", cFormats, hr)); }
/** * Device I/O Control entry point. * * @param pFilp Associated file pointer. * @param uCmd The function specified to ioctl(). * @param ulArg The argument specified to ioctl(). * @param pSession The session instance. */ static int VBoxDrvLinuxIOCtlSlow(struct file *pFilp, unsigned int uCmd, unsigned long ulArg, PSUPDRVSESSION pSession) { int rc; SUPREQHDR Hdr; PSUPREQHDR pHdr; uint32_t cbBuf; Log6(("VBoxDrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p pid=%d/%d\n", pFilp, uCmd, (void *)ulArg, RTProcSelf(), current->pid)); /* * Read the header. */ if (RT_UNLIKELY(copy_from_user(&Hdr, (void *)ulArg, sizeof(Hdr)))) { Log(("VBoxDrvLinuxIOCtl: copy_from_user(,%#lx,) failed; uCmd=%#x\n", ulArg, uCmd)); return -EFAULT; } if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) { Log(("VBoxDrvLinuxIOCtl: bad header magic %#x; uCmd=%#x\n", Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK, uCmd)); return -EINVAL; } /* * Buffer the request. */ cbBuf = RT_MAX(Hdr.cbIn, Hdr.cbOut); if (RT_UNLIKELY(cbBuf > _1M*16)) { Log(("VBoxDrvLinuxIOCtl: too big cbBuf=%#x; uCmd=%#x\n", cbBuf, uCmd)); return -E2BIG; } if (RT_UNLIKELY(_IOC_SIZE(uCmd) ? cbBuf != _IOC_SIZE(uCmd) : Hdr.cbIn < sizeof(Hdr))) { Log(("VBoxDrvLinuxIOCtl: bad ioctl cbBuf=%#x _IOC_SIZE=%#x; uCmd=%#x\n", cbBuf, _IOC_SIZE(uCmd), uCmd)); return -EINVAL; } pHdr = RTMemAlloc(cbBuf); if (RT_UNLIKELY(!pHdr)) { OSDBGPRINT(("VBoxDrvLinuxIOCtl: failed to allocate buffer of %d bytes for uCmd=%#x\n", cbBuf, uCmd)); return -ENOMEM; } if (RT_UNLIKELY(copy_from_user(pHdr, (void *)ulArg, Hdr.cbIn))) { Log(("VBoxDrvLinuxIOCtl: copy_from_user(,%#lx, %#x) failed; uCmd=%#x\n", ulArg, Hdr.cbIn, uCmd)); RTMemFree(pHdr); return -EFAULT; } if (Hdr.cbIn < cbBuf) RT_BZERO((uint8_t *)pHdr + Hdr.cbIn, cbBuf - Hdr.cbIn); /* * Process the IOCtl. */ stac(); rc = supdrvIOCtl(uCmd, &g_DevExt, pSession, pHdr, cbBuf); clac(); /* * Copy ioctl data and output buffer back to user space. */ if (RT_LIKELY(!rc)) { uint32_t cbOut = pHdr->cbOut; if (RT_UNLIKELY(cbOut > cbBuf)) { OSDBGPRINT(("VBoxDrvLinuxIOCtl: too much output! %#x > %#x; uCmd=%#x!\n", cbOut, cbBuf, uCmd)); cbOut = cbBuf; } if (RT_UNLIKELY(copy_to_user((void *)ulArg, pHdr, cbOut))) { /* this is really bad! */ OSDBGPRINT(("VBoxDrvLinuxIOCtl: copy_to_user(%#lx,,%#x); uCmd=%#x!\n", ulArg, cbOut, uCmd)); rc = -EFAULT; } } else { Log(("VBoxDrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p failed, rc=%d\n", pFilp, uCmd, (void *)ulArg, rc)); rc = -EINVAL; } RTMemFree(pHdr); Log6(("VBoxDrvLinuxIOCtl: returns %d (pid=%d/%d)\n", rc, RTProcSelf(), current->pid)); return rc; }
/** * Get Parallel port address and update the shared data * structure. * @returns VBox status code. * @param pThis The host parallel port instance data. */ static int drvWinHostGetparportAddr(PDRVHOSTPARALLEL pThis) { HDEVINFO hDevInfo; SP_DEVINFO_DATA DeviceInfoData; uint32_t u32Idx; uint32_t u32ParportAddr; int rc = VINF_SUCCESS; hDevInfo = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES); if (hDevInfo == INVALID_HANDLE_VALUE) return VERR_INVALID_HANDLE; /* Enumerate through all devices in Set. */ DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (u32Idx = 0; SetupDiEnumDeviceInfo(hDevInfo, u32Idx, &DeviceInfoData); u32Idx++) { DWORD dwDataType; uint8_t *pBuf = NULL; DWORD dwBufSize = 0; while (!SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_FRIENDLYNAME, (PDWORD)&dwDataType, (uint8_t *)pBuf, dwBufSize, (PDWORD)&dwBufSize)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { LogFlow(("ERROR_INSUFF_BUFF = %d. dwBufSz = %d\n", GetLastError(), dwBufSize)); if (pBuf) RTMemFree(pBuf); pBuf = (uint8_t *)RTMemAlloc(dwBufSize * 2); } else { /* No need to bother about this error (in most cases its errno=13, * INVALID_DATA . Just break from here and proceed to next device * enumerated item */ LogFlow(("GetDevProp Error = %d & dwBufSz = %d\n", GetLastError(), dwBufSize)); break; } } if (RTStrStr((char*)pBuf, "LPT")) { u32ParportAddr = drvHostWinFindIORangeResource(DeviceInfoData.DevInst); if (u32ParportAddr) { /* Find parallel port name and update the shared data struncture */ char *pCh = RTStrStr((char*)pBuf, "("); char *pTmpCh = RTStrStr((char *)pBuf, ")"); /* check for the confirmation for the availability of parallel port */ if (!(pCh && pTmpCh)) { LogFlowFunc(("Parallel port Not Found. \n")); return VERR_NOT_FOUND; } if (((pTmpCh - (char *)pBuf) - (pCh - (char *)pBuf)) < 0) { LogFlowFunc(("Parallel port string not properly formatted.\n")); return VERR_NOT_FOUND; } /* check for the confirmation for the availability of parallel port */ if (RTStrCopyEx((char *)(pThis->szParportName), sizeof(pThis->szParportName), pCh+1, ((pTmpCh - (char *)pBuf) - (pCh - (char *)pBuf)) - 1)) { LogFlowFunc(("Parallel Port Not Found.\n")); return VERR_NOT_FOUND; } *((char *)pThis->szParportName + (pTmpCh - (char *)pBuf) - (pCh - (char *)pBuf) + 1 ) = '\0'; /* checking again to make sure that we have got a valid name and in valid format too. */ if (RTStrNCmp((char *)pThis->szParportName, "LPT", 3)) { LogFlowFunc(("Parallel Port name \"LPT\" Not Found.\n")); return VERR_NOT_FOUND; } if (!RTStrStr((char *)pThis->szParportName, "LPT") || !(pThis->szParportName[3] >= '0' && pThis->szParportName[3] <= '9')) { RT_BZERO(pThis->szParportName, sizeof(pThis->szParportName)); LogFlowFunc(("Printer Port Name Not Found.\n")); return VERR_NOT_FOUND; } pThis->fParportAvail = true; pThis->u32LptAddr = u32ParportAddr; pThis->u32LptAddrControl = pThis->u32LptAddr + CTRL_REG_OFFSET; pThis->u32LptAddrStatus = pThis->u32LptAddr + STATUS_REG_OFFSET; } else LogFlowFunc(("u32Parport Addr No Available \n")); if (pThis->fParportAvail) break; } if (pBuf) RTMemFree(pBuf); if (pThis->fParportAvail) { /* Parallel port address has been found. No need to iterate further. */ break; } } if (GetLastError() != NO_ERROR && GetLastError() != ERROR_NO_MORE_ITEMS) rc = VERR_GENERAL_FAILURE; SetupDiDestroyDeviceInfoList(hDevInfo); return rc; }
int MsixInit(PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, PPDMMSIREG pMsiReg) { if (pMsiReg->cMsixVectors == 0) return VINF_SUCCESS; /* We cannot init MSI-X on raw devices yet. */ Assert(!pciDevIsPassthrough(pDev)); uint16_t cVectors = pMsiReg->cMsixVectors; uint8_t iCapOffset = pMsiReg->iMsixCapOffset; uint8_t iNextOffset = pMsiReg->iMsixNextOffset; uint8_t iBar = pMsiReg->iMsixBar; if (cVectors > VBOX_MSIX_MAX_ENTRIES) { AssertMsgFailed(("Too many MSI-X vectors: %d\n", cVectors)); return VERR_TOO_MUCH_DATA; } if (iBar > 5) { AssertMsgFailed(("Using wrong BAR for MSI-X: %d\n", iBar)); return VERR_INVALID_PARAMETER; } Assert(iCapOffset != 0 && iCapOffset < 0xff && iNextOffset < 0xff); int rc = VINF_SUCCESS; /* If device is passthrough, BAR is registered using common mechanism. */ if (!pciDevIsPassthrough(pDev)) { rc = PDMDevHlpPCIIORegionRegister (pDev->pDevIns, iBar, 0x1000, PCI_ADDRESS_SPACE_MEM, msixMap); if (RT_FAILURE (rc)) return rc; } pDev->Int.s.u8MsixCapOffset = iCapOffset; pDev->Int.s.u8MsixCapSize = VBOX_MSIX_CAP_SIZE; PVM pVM = PDMDevHlpGetVM(pDev->pDevIns); pDev->Int.s.pMsixPageR3 = NULL; rc = MMHyperAlloc(pVM, 0x1000, 1, MM_TAG_PDM_DEVICE_USER, (void **)&pDev->Int.s.pMsixPageR3); if (RT_FAILURE(rc) || (pDev->Int.s.pMsixPageR3 == NULL)) return VERR_NO_VM_MEMORY; RT_BZERO(pDev->Int.s.pMsixPageR3, 0x1000); pDev->Int.s.pMsixPageR0 = MMHyperR3ToR0(pVM, pDev->Int.s.pMsixPageR3); pDev->Int.s.pMsixPageRC = MMHyperR3ToRC(pVM, pDev->Int.s.pMsixPageR3); /* R3 PCI helper */ pDev->Int.s.pPciBusPtrR3 = pPciHlp; PCIDevSetByte(pDev, iCapOffset + 0, VBOX_PCI_CAP_ID_MSIX); PCIDevSetByte(pDev, iCapOffset + 1, iNextOffset); /* next */ PCIDevSetWord(pDev, iCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL, cVectors - 1); uint32_t offTable = 0, offPBA = 0x800; PCIDevSetDWord(pDev, iCapOffset + VBOX_MSIX_TABLE_BIROFFSET, offTable | iBar); PCIDevSetDWord(pDev, iCapOffset + VBOX_MSIX_PBA_BIROFFSET, offPBA | iBar); pciDevSetMsixCapable(pDev); return VINF_SUCCESS; }
void tstFileAioTestReadWriteBasic(RTFILE File, bool fWrite, void *pvTestBuf, size_t cbTestBuf, size_t cbTestFile, uint32_t cMaxReqsInFlight) { /* Allocate request array. */ RTFILEAIOREQ *paReqs; paReqs = (PRTFILEAIOREQ)RTTestGuardedAllocHead(g_hTest, cMaxReqsInFlight * sizeof(RTFILEAIOREQ)); RTTESTI_CHECK_RETV(paReqs); RT_BZERO(paReqs, sizeof(cMaxReqsInFlight * sizeof(RTFILEAIOREQ))); /* Allocate array holding pointer to data buffers. */ void **papvBuf = (void **)RTTestGuardedAllocHead(g_hTest, cMaxReqsInFlight * sizeof(void *)); RTTESTI_CHECK_RETV(papvBuf); /* Allocate the buffers*/ for (unsigned i = 0; i < cMaxReqsInFlight; i++) { RTTESTI_CHECK_RC_OK_RETV(RTTestGuardedAlloc(g_hTest, cbTestBuf, PAGE_SIZE, true /*fHead*/, &papvBuf[i])); if (fWrite) memcpy(papvBuf[i], pvTestBuf, cbTestBuf); if (fWrite) memcpy(papvBuf[i], pvTestBuf, cbTestBuf); else RT_BZERO(papvBuf[i], cbTestBuf); } /* Allocate array holding completed requests. */ RTFILEAIOREQ *paReqsCompleted; paReqsCompleted = (PRTFILEAIOREQ)RTTestGuardedAllocHead(g_hTest, cMaxReqsInFlight * sizeof(RTFILEAIOREQ)); RTTESTI_CHECK_RETV(paReqsCompleted); RT_BZERO(paReqsCompleted, cMaxReqsInFlight * sizeof(RTFILEAIOREQ)); /* Create a context and associate the file handle with it. */ RTFILEAIOCTX hAioContext; RTTESTI_CHECK_RC_RETV(RTFileAioCtxCreate(&hAioContext, cMaxReqsInFlight, 0 /* fFlags */), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTFileAioCtxAssociateWithFile(hAioContext, File), VINF_SUCCESS); /* Initialize requests. */ for (unsigned i = 0; i < cMaxReqsInFlight; i++) RTFileAioReqCreate(&paReqs[i]); RTFOFF off = 0; int cRuns = 0; uint64_t NanoTS = RTTimeNanoTS(); size_t cbLeft = cbTestFile; while (cbLeft) { int rc; int cReqs = 0; for (unsigned i = 0; i < cMaxReqsInFlight; i++) { size_t cbTransfer = cbLeft < cbTestBuf ? cbLeft : cbTestBuf; if (!cbTransfer) break; if (fWrite) rc = RTFileAioReqPrepareWrite(paReqs[i], File, off, papvBuf[i], cbTransfer, papvBuf[i]); else rc = RTFileAioReqPrepareRead(paReqs[i], File, off, papvBuf[i], cbTransfer, papvBuf[i]); RTTESTI_CHECK_RC(rc, VINF_SUCCESS); cbLeft -= cbTransfer; off += cbTransfer; cReqs++; } rc = RTFileAioCtxSubmit(hAioContext, paReqs, cReqs); RTTESTI_CHECK_MSG(rc == VINF_SUCCESS, ("Failed to submit tasks after %d runs. rc=%Rrc\n", cRuns, rc)); if (rc != VINF_SUCCESS) break; /* Wait */ uint32_t cCompleted = 0; RTTESTI_CHECK_RC(rc = RTFileAioCtxWait(hAioContext, cReqs, RT_INDEFINITE_WAIT, paReqsCompleted, cMaxReqsInFlight, &cCompleted), VINF_SUCCESS); if (rc != VINF_SUCCESS) break; if (!fWrite) { for (uint32_t i = 0; i < cCompleted; i++) { /* Compare that we read the right stuff. */ void *pvBuf = RTFileAioReqGetUser(paReqsCompleted[i]); RTTESTI_CHECK(pvBuf); size_t cbTransfered; RTTESTI_CHECK_RC(rc = RTFileAioReqGetRC(paReqsCompleted[i], &cbTransfered), VINF_SUCCESS); if (rc != VINF_SUCCESS) break; RTTESTI_CHECK_MSG(cbTransfered == cbTestBuf, ("cbTransfered=%zd\n", cbTransfered)); RTTESTI_CHECK_RC_OK(rc = (memcmp(pvBuf, pvTestBuf, cbTestBuf) == 0 ? VINF_SUCCESS : VERR_BAD_EXE_FORMAT)); if (rc != VINF_SUCCESS) break; memset(pvBuf, 0, cbTestBuf); } } cRuns++; if (RT_FAILURE(rc)) break; } NanoTS = RTTimeNanoTS() - NanoTS; uint64_t SpeedKBs = (uint64_t)(cbTestFile / (NanoTS / 1000000000.0) / 1024); RTTestValue(g_hTest, "Throughput", SpeedKBs, RTTESTUNIT_KILOBYTES_PER_SEC); /* cleanup */ for (unsigned i = 0; i < cMaxReqsInFlight; i++) RTTestGuardedFree(g_hTest, papvBuf[i]); RTTestGuardedFree(g_hTest, papvBuf); for (unsigned i = 0; i < cMaxReqsInFlight; i++) RTTESTI_CHECK_RC(RTFileAioReqDestroy(paReqs[i]), VINF_SUCCESS); RTTESTI_CHECK_RC(RTFileAioCtxDestroy(hAioContext), VINF_SUCCESS); RTTestGuardedFree(g_hTest, paReqs); }
RTDECL(int) RTAsn1ContentReallocZ(PRTASN1CORE pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator) { /* Validate input. */ AssertPtr(pAsn1Core); AssertReturn(cb < _1G, VERR_INVALID_PARAMETER); if (cb > 0) { /* * Case 1 - Initial allocation. */ uint32_t cbNeeded = RT_OFFSETOF(RTASN1MEMCONTENT, au64Content) + (uint32_t)cb; if (!(pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT)) return RTAsn1ContentAllocZ(pAsn1Core, cb, pAllocator); /* Locate the header. */ PRTASN1MEMCONTENT pHdr = RT_FROM_MEMBER(pAsn1Core->uData.pv, RTASN1MEMCONTENT, au64Content); /* * Case 2 - Reallocation using the same allocator. */ if ( pHdr->Allocation.pAllocator == pAllocator || !pAllocator) { pHdr->Allocation.cReallocs++; /* Modify the allocation if necessary. */ if (pHdr->Allocation.cbAllocated < cbNeeded) { RTASN1ALLOCATION Allocation = pHdr->Allocation; int rc = Allocation.pAllocator->pfnRealloc(Allocation.pAllocator, &Allocation, pHdr, (void **)&pHdr, cbNeeded); if (RT_FAILURE(rc)) return rc; Assert(Allocation.cbAllocated >= cbNeeded); pAsn1Core->uData.pv = &pHdr->au64Content[0]; pHdr->Allocation = Allocation; } /* Clear any additional memory we're letting the user use and update the content size. */ if (pAsn1Core->cb < cb) RT_BZERO((uint8_t *)&pAsn1Core->uData.pu8[pAsn1Core->cb], cb - pAsn1Core->cb); pAsn1Core->cb = (uint32_t)cb; } /* * Case 3 - Reallocation using a different allocator. */ else { /* Initialize the temporary allocation tracker. */ RTASN1ALLOCATION Allocation; Allocation.cbAllocated = 0; Allocation.cReallocs = pHdr->Allocation.cReallocs + 1; Allocation.uReserved0 = 0; Allocation.pAllocator = pAllocator; /* Make the allocation. */ PRTASN1MEMCONTENT pHdrNew; int rc = pAllocator->pfnAlloc(pAllocator, &Allocation, (void **)&pHdrNew, cbNeeded); if (RT_FAILURE(rc)) return rc; Assert(Allocation.cbAllocated >= cbNeeded); /* Duplicate the old content and zero any new memory we might've added. */ if (pAsn1Core->cb >= cb) memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], cb); else { memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], pAsn1Core->cb); RT_BZERO((uint8_t *)&pHdrNew->au64Content[0] + pAsn1Core->cb, cb - pAsn1Core->cb); } /* Update the core. */ pHdrNew->Allocation = Allocation; pAsn1Core->uData.pv = &pHdrNew->au64Content[0]; pAsn1Core->fFlags |= RTASN1CORE_F_ALLOCATED_CONTENT; /* free cleared it. */ pAsn1Core->cb = (uint32_t)cb; /* Free the old content. */ Allocation = pHdr->Allocation; Allocation.pAllocator->pfnFree(Allocation.pAllocator, &Allocation, pHdr); Assert(Allocation.cbAllocated == 0); } } /* * Case 4 - It's a request to free the memory. */ else RTAsn1ContentFree(pAsn1Core); return VINF_SUCCESS; }
UIDnDDataObject::UIDnDDataObject(UIDnDHandler *pDnDHandler, const QStringList &lstFormats) : m_pDnDHandler(pDnDHandler) , m_enmStatus(DnDDataObjectStatus_Uninitialized) , m_cRefs(1) , m_cFormats(0) , m_pFormatEtc(NULL) , m_pStgMedium(NULL) , m_SemEvent(NIL_RTSEMEVENT) , m_fDataRetrieved(false) , m_pvData(NULL) , m_cbData(0) { HRESULT hr; ULONG cMaxFormats = 16; /* Maximum number of registered formats. */ ULONG cRegisteredFormats = 0; try { m_pFormatEtc = new FORMATETC[cMaxFormats]; RT_BZERO(m_pFormatEtc, sizeof(FORMATETC) * cMaxFormats); m_pStgMedium = new STGMEDIUM[cMaxFormats]; RT_BZERO(m_pStgMedium, sizeof(STGMEDIUM) * cMaxFormats); for (int i = 0; ( i < lstFormats.size() && i < cMaxFormats); i++) { const QString &strFormat = lstFormats.at(i); if (m_lstFormats.contains(strFormat)) continue; /* URI data ("text/uri-list"). */ if (strFormat.contains("text/uri-list", Qt::CaseInsensitive)) { RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_TEXT); m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_UNICODETEXT); m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_HDROP); m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; m_lstFormats << strFormat; } /* Plain text ("text/plain"). */ if (strFormat.contains("text/plain", Qt::CaseInsensitive)) { RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_TEXT); m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_UNICODETEXT); m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; m_lstFormats << strFormat; } } LogRel3(("DnD: Total registered native formats: %RU32 (for %d formats from guest)\n", cRegisteredFormats, lstFormats.size())); hr = S_OK; } catch (std::bad_alloc &) { hr = E_OUTOFMEMORY; } if (SUCCEEDED(hr)) { int rc2 = RTSemEventCreate(&m_SemEvent); AssertRC(rc2); /* * Other (not so common) formats. */ #if 0 /* IStream. */ RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)); RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_FILECONTENTS), TYMED_ISTREAM, 0 /* lIndex */); /* Required for e.g. Windows Media Player. */ RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_FILENAME)); RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_FILENAMEW)); RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_SHELLIDLIST)); RegisterFormat(&mpFormatEtc[cFormats++], RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET)); #endif m_cFormats = cRegisteredFormats; m_enmStatus = DnDDataObjectStatus_Dropping; } LogFlowFunc(("hr=%Rhrc\n", hr)); }
/** * @interface_method_impl{DBGFOSIDMESG,pfnQueryKernelLog} */ static DECLCALLBACK(int) dbgDiggerLinuxIDmsg_QueryKernelLog(PDBGFOSIDMESG pThis, PUVM pUVM, uint32_t fFlags, uint32_t cMessages, char *pszBuf, size_t cbBuf, size_t *pcbActual) { PDBGDIGGERLINUX pData = RT_FROM_MEMBER(pThis, DBGDIGGERLINUX, IDmesg); if (cMessages < 1) return VERR_INVALID_PARAMETER; /* * Resolve the symbols we need and read their values. */ RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL); RTDBGMOD hMod; int rc = RTDbgAsModuleByName(hAs, "vmlinux", 0, &hMod); if (RT_FAILURE(rc)) return VERR_NOT_FOUND; RTDbgAsRelease(hAs); RTGCPTR GCPtrLogBuf; uint32_t cbLogBuf; uint32_t idxFirst; uint32_t idxNext; struct { void *pvVar; size_t cbHost, cbGuest; const char *pszSymbol; } aSymbols[] = { { &GCPtrLogBuf, sizeof(GCPtrLogBuf), pData->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t), "log_buf" }, { &cbLogBuf, sizeof(cbLogBuf), sizeof(cbLogBuf), "log_buf_len" }, { &idxFirst, sizeof(idxFirst), sizeof(idxFirst), "log_first_idx" }, { &idxNext, sizeof(idxNext), sizeof(idxNext), "log_next_idx" }, }; for (uint32_t i = 0; i < RT_ELEMENTS(aSymbols); i++) { RTDBGSYMBOL SymInfo; rc = RTDbgModSymbolByName(hMod, aSymbols[i].pszSymbol, &SymInfo); if (RT_SUCCESS(rc)) { RT_BZERO(aSymbols[i].pvVar, aSymbols[i].cbHost); Assert(aSymbols[i].cbHost >= aSymbols[i].cbGuest); DBGFADDRESS Addr; rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, (RTGCPTR)SymInfo.Value + pData->AddrKernelBase.FlatPtr), aSymbols[i].pvVar, aSymbols[i].cbGuest); if (RT_SUCCESS(rc)) continue; Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Reading '%s' at %RGv: %Rrc\n", aSymbols[i].pszSymbol, Addr.FlatPtr, rc)); } else Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Error looking up '%s': %Rrc\n", aSymbols[i].pszSymbol, rc)); RTDbgModRelease(hMod); return VERR_NOT_FOUND; } /* * Check if the values make sense. */ if (pData->f64Bit ? !LNX64_VALID_ADDRESS(GCPtrLogBuf) : !LNX32_VALID_ADDRESS(GCPtrLogBuf)) { Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_buf' value %RGv is not valid.\n", GCPtrLogBuf)); return VERR_NOT_FOUND; } if ( cbLogBuf < 4096 || !RT_IS_POWER_OF_TWO(cbLogBuf) || cbLogBuf > 16*_1M) { Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_buf_len' value %#x is not valid.\n", cbLogBuf)); return VERR_NOT_FOUND; } uint32_t const cbLogAlign = 4; if ( idxFirst > cbLogBuf - sizeof(LNXPRINTKHDR) || (idxFirst & (cbLogAlign - 1)) != 0) { Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_first_idx' value %#x is not valid.\n", idxFirst)); return VERR_NOT_FOUND; } if ( idxNext > cbLogBuf - sizeof(LNXPRINTKHDR) || (idxNext & (cbLogAlign - 1)) != 0) { Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_next_idx' value %#x is not valid.\n", idxNext)); return VERR_NOT_FOUND; } /* * Read the whole log buffer. */ uint8_t *pbLogBuf = (uint8_t *)RTMemAlloc(cbLogBuf); if (!pbLogBuf) { Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Failed to allocate %#x bytes for log buffer\n", cbLogBuf)); return VERR_NO_MEMORY; } DBGFADDRESS Addr; rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, GCPtrLogBuf), pbLogBuf, cbLogBuf); if (RT_FAILURE(rc)) { Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Error reading %#x bytes of log buffer at %RGv: %Rrc\n", cbLogBuf, Addr.FlatPtr, rc)); RTMemFree(pbLogBuf); return VERR_NOT_FOUND; } /* * Count the messages in the buffer while doing some basic validation. */ uint32_t const cbUsed = idxFirst == idxNext ? cbLogBuf /* could be empty... */ : idxFirst < idxNext ? idxNext - idxFirst : cbLogBuf - idxFirst + idxNext; uint32_t cbLeft = cbUsed; uint32_t offCur = idxFirst; uint32_t cLogMsgs = 0; while (cbLeft > 0) { PCLNXPRINTKHDR pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; if (!pHdr->cbTotal) { /* Wrap around packet, most likely... */ if (cbLogBuf - offCur >= cbLeft) break; offCur = 0; pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; } if (RT_UNLIKELY( pHdr->cbTotal > cbLogBuf - sizeof(*pHdr) - offCur || pHdr->cbTotal > cbLeft || (pHdr->cbTotal & (cbLogAlign - 1)) != 0 || pHdr->cbTotal < (uint32_t)pHdr->cbText + (uint32_t)pHdr->cbDict + sizeof(*pHdr) )) { Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Invalid printk_log record at %#x: cbTotal=%#x cbText=%#x cbDict=%#x cbLogBuf=%#x cbLeft=%#x\n", offCur, pHdr->cbTotal, pHdr->cbText, pHdr->cbDict, cbLogBuf, cbLeft)); rc = VERR_INVALID_STATE; break; } if (pHdr->cbText > 0) cLogMsgs++; /* next */ offCur += pHdr->cbTotal; cbLeft -= pHdr->cbTotal; } if (RT_FAILURE(rc)) { RTMemFree(pbLogBuf); return rc; } /* * Copy the messages into the output buffer. */ offCur = idxFirst; cbLeft = cbUsed; /* Skip messages that the caller doesn't want. */ if (cMessages < cLogMsgs) { uint32_t cToSkip = cLogMsgs - cMessages; while (cToSkip > 0) { PCLNXPRINTKHDR pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; if (!pHdr->cbTotal) { offCur = 0; pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; } if (pHdr->cbText > 0) cToSkip--; /* next */ offCur += pHdr->cbTotal; cbLeft -= pHdr->cbTotal; } } /* Now copy the messages. */ size_t offDst = 0; while (cbLeft > 0) { PCLNXPRINTKHDR pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; if (!pHdr->cbTotal) { if (cbLogBuf - offCur >= cbLeft) break; offCur = 0; pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; } if (pHdr->cbText > 0) { char *pchText = (char *)(pHdr + 1); size_t cchText = RTStrNLen(pchText, pHdr->cbText); if (offDst + cchText < cbBuf) { memcpy(&pszBuf[offDst], pHdr + 1, cchText); pszBuf[offDst + cchText] = '\n'; } else if (offDst < cbBuf) memcpy(&pszBuf[offDst], pHdr + 1, cbBuf - offDst); offDst += cchText + 1; } /* next */ offCur += pHdr->cbTotal; cbLeft -= pHdr->cbTotal; } /* Done with the buffer. */ RTMemFree(pbLogBuf); /* Make sure we've reserved a char for the terminator. */ if (!offDst) offDst = 1; /* Set return size value. */ if (pcbActual) *pcbActual = offDst; /* * All VBox strings are UTF-8 and bad things may in theory happen if we * pass bad UTF-8 to code which assumes it's all valid. So, we enforce * UTF-8 upon the guest kernel messages here even if they (probably) have * no defined code set in reality. */ if (offDst <= cbBuf) { pszBuf[offDst - 1] = '\0'; RTStrPurgeEncoding(pszBuf); return VINF_SUCCESS; } if (cbBuf) { pszBuf[cbBuf - 1] = '\0'; RTStrPurgeEncoding(pszBuf); } return VERR_BUFFER_OVERFLOW; }