RTDECL(int) RTPowerNotificationRegister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser) { PRTPOWERNOTIFYREG pCur; PRTPOWERNOTIFYREG pNew; /* * Validation. */ AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); AssertReturn(g_hRTPowerNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER); RT_ASSERT_PREEMPTIBLE(); RTSpinlockAcquire(g_hRTPowerNotifySpinLock); for (pCur = g_pRTPowerCallbackHead; pCur; pCur = pCur->pNext) if ( pCur->pvUser == pvUser && pCur->pfnCallback == pfnCallback) break; RTSpinlockRelease(g_hRTPowerNotifySpinLock); AssertMsgReturn(!pCur, ("pCur=%p pfnCallback=%p pvUser=%p\n", pCur, pfnCallback, pvUser), VERR_ALREADY_EXISTS); /* * Allocate a new record and attempt to insert it. */ pNew = (PRTPOWERNOTIFYREG)RTMemAlloc(sizeof(*pNew)); if (!pNew) return VERR_NO_MEMORY; pNew->pNext = NULL; pNew->pfnCallback = pfnCallback; pNew->pvUser = pvUser; memset(&pNew->bmDone[0], 0xff, sizeof(pNew->bmDone)); RTSpinlockAcquire(g_hRTPowerNotifySpinLock); pCur = g_pRTPowerCallbackHead; if (!pCur) g_pRTPowerCallbackHead = pNew; else { for (pCur = g_pRTPowerCallbackHead; ; pCur = pCur->pNext) if ( pCur->pvUser == pvUser && pCur->pfnCallback == pfnCallback) break; else if (!pCur->pNext) { pCur->pNext = pNew; pCur = NULL; break; } } ASMAtomicIncU32(&g_iRTPowerGeneration); RTSpinlockRelease(g_hRTPowerNotifySpinLock); /* duplicate? */ if (pCur) { RTMemFree(pCur); AssertMsgFailedReturn(("pCur=%p pfnCallback=%p pvUser=%p\n", pCur, pfnCallback, pvUser), VERR_ALREADY_EXISTS); } return VINF_SUCCESS; }
/* For contiguous chunks just return the address in the buffer. * For crossing boundary - allocate a buffer from heap. */ static bool i_vbvaFetchCmd(VIDEOACCEL *pVideoAccel, VBVACMDHDR **ppHdr, uint32_t *pcbCmd) { VBVAMEMORY *pVbvaMemory = pVideoAccel->pVbvaMemory; uint32_t indexRecordFirst = pVbvaMemory->indexRecordFirst; uint32_t indexRecordFree = pVbvaMemory->indexRecordFree; #ifdef DEBUG_sunlover LogFlowFunc(("first = %d, free = %d\n", indexRecordFirst, indexRecordFree)); #endif /* DEBUG_sunlover */ if (!i_vbvaVerifyRingBuffer(pVbvaMemory)) { return false; } if (indexRecordFirst == indexRecordFree) { /* No records to process. Return without assigning output variables. */ return true; } uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVbvaMemory->aRecords[indexRecordFirst].cbRecord); #ifdef DEBUG_sunlover LogFlowFunc(("cbRecord = 0x%08X\n", cbRecordCurrent)); #endif /* DEBUG_sunlover */ uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL; if (pVideoAccel->cbVbvaPartial) { /* There is a partial read in process. Continue with it. */ Assert(pVideoAccel->pu8VbvaPartial); LogFlowFunc(("continue partial record cbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n", pVideoAccel->cbVbvaPartial, cbRecordCurrent, indexRecordFirst, indexRecordFree)); if (cbRecord > pVideoAccel->cbVbvaPartial) { /* New data has been added to the record. */ if (!i_vbvaPartialRead(&pVideoAccel->pu8VbvaPartial, &pVideoAccel->cbVbvaPartial, cbRecord, pVbvaMemory)) { return false; } } if (!(cbRecordCurrent & VBVA_F_RECORD_PARTIAL)) { /* The record is completed by guest. Return it to the caller. */ *ppHdr = (VBVACMDHDR *)pVideoAccel->pu8VbvaPartial; *pcbCmd = pVideoAccel->cbVbvaPartial; pVideoAccel->pu8VbvaPartial = NULL; pVideoAccel->cbVbvaPartial = 0; /* Advance the record index. */ pVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS; #ifdef DEBUG_sunlover LogFlowFunc(("partial done ok, data = %d, free = %d\n", pVbvaMemory->off32Data, pVbvaMemory->off32Free)); #endif /* DEBUG_sunlover */ } return true; } /* A new record need to be processed. */ if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL) { /* Current record is being written by guest. '=' is important here. */ if (cbRecord >= VBVA_RING_BUFFER_SIZE - VBVA_RING_BUFFER_THRESHOLD) { /* Partial read must be started. */ if (!i_vbvaPartialRead(&pVideoAccel->pu8VbvaPartial, &pVideoAccel->cbVbvaPartial, cbRecord, pVbvaMemory)) { return false; } LogFlowFunc(("started partial record cbVbvaPartial = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n", pVideoAccel->cbVbvaPartial, cbRecordCurrent, indexRecordFirst, indexRecordFree)); } return true; } /* Current record is complete. If it is not empty, process it. */ if (cbRecord) { /* The size of largest contiguous chunk in the ring biffer. */ uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - pVbvaMemory->off32Data; /* The ring buffer pointer. */ uint8_t *au8RingBuffer = &pVbvaMemory->au8RingBuffer[0]; /* The pointer to data in the ring buffer. */ uint8_t *src = &au8RingBuffer[pVbvaMemory->off32Data]; /* Fetch or point the data. */ if (u32BytesTillBoundary >= cbRecord) { /* The command does not cross buffer boundary. Return address in the buffer. */ *ppHdr = (VBVACMDHDR *)src; /* Advance data offset. */ pVbvaMemory->off32Data = (pVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE; } else { /* The command crosses buffer boundary. Rare case, so not optimized. */ uint8_t *dst = (uint8_t *)RTMemAlloc(cbRecord); if (!dst) { LogRelFlowFunc(("could not allocate %d bytes from heap!!!\n", cbRecord)); pVbvaMemory->off32Data = (pVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE; return false; } i_vbvaFetchBytes(pVbvaMemory, dst, cbRecord); *ppHdr = (VBVACMDHDR *)dst; #ifdef DEBUG_sunlover LogFlowFunc(("Allocated from heap %p\n", dst)); #endif /* DEBUG_sunlover */ } } *pcbCmd = cbRecord; /* Advance the record index. */ pVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS; #ifdef DEBUG_sunlover LogFlowFunc(("done ok, data = %d, free = %d\n", pVbvaMemory->off32Data, pVbvaMemory->off32Free)); #endif /* DEBUG_sunlover */ return true; }
RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...) { AssertReturn(!(fFlags & ~RTSEMRW_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER); /* * Allocate handle. */ int rc; struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL)); if (pThis) { /* * Create the rwlock. */ pthread_rwlockattr_t Attr; rc = pthread_rwlockattr_init(&Attr); if (!rc) { rc = pthread_rwlock_init(&pThis->RWLock, &Attr); if (!rc) { pThis->u32Magic = RTSEMRW_MAGIC; pThis->cReaders = 0; pThis->cWrites = 0; pThis->cWriterReads = 0; pThis->Writer = (pthread_t)-1; #ifdef RTSEMRW_STRICT bool const fLVEnabled = !(fFlags & RTSEMRW_FLAGS_NO_LOCK_VAL); if (!pszNameFmt) { static uint32_t volatile s_iSemRWAnon = 0; uint32_t i = ASMAtomicIncU32(&s_iSemRWAnon) - 1; RTLockValidatorRecExclInit(&pThis->ValidatorWrite, hClass, uSubClass, pThis, fLVEnabled, "RTSemRW-%u", i); RTLockValidatorRecSharedInit(&pThis->ValidatorRead, hClass, uSubClass, pThis, false /*fSignaller*/, fLVEnabled, "RTSemRW-%u", i); } else { va_list va; va_start(va, pszNameFmt); RTLockValidatorRecExclInitV(&pThis->ValidatorWrite, hClass, uSubClass, pThis, fLVEnabled, pszNameFmt, va); va_end(va); va_start(va, pszNameFmt); RTLockValidatorRecSharedInitV(&pThis->ValidatorRead, hClass, uSubClass, pThis, false /*fSignaller*/, fLVEnabled, pszNameFmt, va); va_end(va); } RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core); #endif *phRWSem = pThis; return VINF_SUCCESS; } } rc = RTErrConvertFromErrno(rc); RTMemFree(pThis); } else rc = VERR_NO_MEMORY; return rc; }
/** * Reads a guest property. * * @returns VBox status code, fully bitched. * * @param u32ClientId The HGCM client ID for the guest property session. * @param pszPropName The property name. * @param ppszValue Where to return the value. This is always set * to NULL. Free it using RTStrFree(). * @param ppszFlags Where to return the value flags. Free it * using RTStrFree(). Optional. * @param puTimestamp Where to return the timestamp. This is only set * on success. Optional. */ int VBoxServiceReadProp(uint32_t u32ClientId, const char *pszPropName, char **ppszValue, char **ppszFlags, uint64_t *puTimestamp) { AssertPtrReturn(pszPropName, VERR_INVALID_POINTER); AssertPtrReturn(ppszValue, VERR_INVALID_POINTER); uint32_t cbBuf = _1K; void *pvBuf = NULL; int rc; *ppszValue = NULL; for (unsigned cTries = 0; cTries < 10; cTries++) { /* * (Re-)Allocate the buffer and try read the property. */ RTMemFree(pvBuf); pvBuf = RTMemAlloc(cbBuf); if (!pvBuf) { VBoxServiceError("Guest Property: Failed to allocate %zu bytes\n", cbBuf); rc = VERR_NO_MEMORY; break; } char *pszValue; char *pszFlags; uint64_t uTimestamp; rc = VbglR3GuestPropRead(u32ClientId, pszPropName, pvBuf, cbBuf, &pszValue, &uTimestamp, &pszFlags, NULL); if (RT_FAILURE(rc)) { if (rc == VERR_BUFFER_OVERFLOW) { /* try again with a bigger buffer. */ cbBuf *= 2; continue; } if (rc == VERR_NOT_FOUND) VBoxServiceVerbose(2, "Guest Property: %s not found\n", pszPropName); else VBoxServiceError("Guest Property: Failed to query \"%s\": %Rrc\n", pszPropName, rc); break; } VBoxServiceVerbose(2, "Guest Property: Read \"%s\" = \"%s\", timestamp %RU64n\n", pszPropName, pszValue, uTimestamp); *ppszValue = RTStrDup(pszValue); if (!*ppszValue) { VBoxServiceError("Guest Property: RTStrDup failed for \"%s\"\n", pszValue); rc = VERR_NO_MEMORY; break; } if (puTimestamp) *puTimestamp = uTimestamp; if (ppszFlags) *ppszFlags = RTStrDup(pszFlags); break; /* done */ } if (pvBuf) RTMemFree(pvBuf); return rc; }
static int vbglR3DnDHGProcessURIMessages(uint32_t uClientId, uint32_t *puScreenId, char *pszFormat, uint32_t cbFormat, uint32_t *pcbFormatRecv, void **ppvData, uint32_t cbData, size_t *pcbDataRecv) { /* Make a string list out of the uri data. */ RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n"); if (uriList.isEmpty()) return VINF_SUCCESS; uint32_t cbTmpData = _1M * 10; void *pvTmpData = RTMemAlloc(cbTmpData); if (!pvTmpData) return VERR_NO_MEMORY; /* Create and query the drop target directory. */ char pszDropDir[RTPATH_MAX]; int rc = vbglR3DnDCreateDropDir(pszDropDir, sizeof(pszDropDir)); if (RT_FAILURE(rc)) { RTMemFree(pvTmpData); return rc; } /* Patch the old drop data with the new drop directory, so the drop target * can find the files. */ RTCList<RTCString> guestUriList; for (size_t i = 0; i < uriList.size(); ++i) { const RTCString &strUri = uriList.at(i); /* Query the path component of a file URI. If this hasn't a * file scheme, null is returned. */ if (char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO)) { RTCString strFullPath = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath); char *pszNewUri = RTUriFileCreate(strFullPath.c_str()); if (pszNewUri) { guestUriList.append(pszNewUri); RTStrFree(pszNewUri); } } else guestUriList.append(strUri); } /* Cleanup the old data and write the new data back to the event. */ RTMemFree(*ppvData); RTCString newData = RTCString::join(guestUriList, "\r\n") + "\r\n"; *ppvData = RTStrDupN(newData.c_str(), newData.length()); *pcbDataRecv = newData.length() + 1; /* Lists for holding created files & directories in the case of a * rollback. */ RTCList<RTCString> guestDirList; RTCList<RTCString> guestFileList; char pszPathname[RTPATH_MAX]; uint32_t cbPathname = 0; bool fLoop = true; do { uint32_t uNextMsg; uint32_t cNextParms; rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false); DO(("%Rrc - %d\n", rc , uNextMsg)); if (RT_SUCCESS(rc)) { switch(uNextMsg) { case DragAndDropSvc::HOST_DND_HG_SND_DIR: { uint32_t fMode = 0; rc = vbglR3DnDHGProcessSendDirMessage(uClientId, pszPathname, sizeof(pszPathname), &cbPathname, &fMode); if (RT_SUCCESS(rc)) { DO(("Got drop dir: %s - %o - %Rrc\n", pszPathname, fMode, rc)); char *pszNewDir = RTPathJoinA(pszDropDir, pszPathname); rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0); if (!guestDirList.contains(pszNewDir)) guestDirList.append(pszNewDir); } break; } case DragAndDropSvc::HOST_DND_HG_SND_FILE: { uint32_t cbDataRecv; uint32_t fMode = 0; rc = vbglR3DnDHGProcessSendFileMessage(uClientId, pszPathname, sizeof(pszPathname), &cbPathname, pvTmpData, cbTmpData, &cbDataRecv, &fMode); if (RT_SUCCESS(rc)) { char *pszNewFile = RTPathJoinA(pszDropDir, pszPathname); DO(("Got drop file: %s - %d - %o - %Rrc\n", pszPathname, cbDataRecv, fMode, rc)); RTFILE hFile; rc = RTFileOpen(&hFile, pszNewFile, RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE); if (RT_SUCCESS(rc)) { rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL); if (RT_SUCCESS(rc)) { rc = RTFileWrite(hFile, pvTmpData, cbDataRecv, 0); /* Valid UNIX mode? */ if ( RT_SUCCESS(rc) && (fMode & RTFS_UNIX_MASK)) rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR); } RTFileClose(hFile); if (!guestFileList.contains(pszNewFile)) guestFileList.append(pszNewFile); } } break; } case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL: { rc = vbglR3DnDHGProcessCancelMessage(uClientId); if (RT_SUCCESS(rc)) rc = VERR_CANCELLED; /* Break out of the loop. */ } default: fLoop = false; break; } } else { if (rc == VERR_NO_DATA) rc = VINF_SUCCESS; break; } }while(fLoop); RTMemFree(pvTmpData); /* Cleanup on failure or if the user has canceled. */ if (RT_FAILURE(rc)) { /* Remove any stuff created. */ for (size_t i = 0; i < guestFileList.size(); ++i) RTFileDelete(guestFileList.at(i).c_str()); for (size_t i = 0; i < guestDirList.size(); ++i) RTDirRemove(guestDirList.at(i).c_str()); RTDirRemove(pszDropDir); } return rc; }
/** * Gathers VM statistics and reports them to the host. */ static void VBoxServiceVMStatsReport(void) { #if defined(RT_OS_WINDOWS) SYSTEM_INFO systemInfo; PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION pProcInfo; MEMORYSTATUSEX memStatus; uint32_t cbStruct; DWORD cbReturned; Assert(gCtx.pfnGlobalMemoryStatusEx && gCtx.pfnNtQuerySystemInformation); if ( !gCtx.pfnGlobalMemoryStatusEx || !gCtx.pfnNtQuerySystemInformation) return; /* Clear the report so we don't report garbage should NtQuerySystemInformation behave in an unexpected manner. */ VMMDevReportGuestStats req; RT_ZERO(req); /* Query and report guest statistics */ GetSystemInfo(&systemInfo); memStatus.dwLength = sizeof(memStatus); gCtx.pfnGlobalMemoryStatusEx(&memStatus); req.guestStats.u32PageSize = systemInfo.dwPageSize; req.guestStats.u32PhysMemTotal = (uint32_t)(memStatus.ullTotalPhys / _4K); req.guestStats.u32PhysMemAvail = (uint32_t)(memStatus.ullAvailPhys / _4K); /* The current size of the committed memory limit, in bytes. This is physical memory plus the size of the page file, minus a small overhead. */ req.guestStats.u32PageFileSize = (uint32_t)(memStatus.ullTotalPageFile / _4K) - req.guestStats.u32PhysMemTotal; req.guestStats.u32MemoryLoad = memStatus.dwMemoryLoad; req.guestStats.u32StatCaps = VBOX_GUEST_STAT_PHYS_MEM_TOTAL | VBOX_GUEST_STAT_PHYS_MEM_AVAIL | VBOX_GUEST_STAT_PAGE_FILE_SIZE | VBOX_GUEST_STAT_MEMORY_LOAD; #ifdef VBOX_WITH_MEMBALLOON req.guestStats.u32PhysMemBalloon = VBoxServiceBalloonQueryPages(_4K); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PHYS_MEM_BALLOON; #else req.guestStats.u32PhysMemBalloon = 0; #endif if (gCtx.pfnGetPerformanceInfo) { PERFORMANCE_INFORMATION perfInfo; if (gCtx.pfnGetPerformanceInfo(&perfInfo, sizeof(perfInfo))) { req.guestStats.u32Processes = perfInfo.ProcessCount; req.guestStats.u32Threads = perfInfo.ThreadCount; req.guestStats.u32Handles = perfInfo.HandleCount; req.guestStats.u32MemCommitTotal = perfInfo.CommitTotal; /* already in pages */ req.guestStats.u32MemKernelTotal = perfInfo.KernelTotal; /* already in pages */ req.guestStats.u32MemKernelPaged = perfInfo.KernelPaged; /* already in pages */ req.guestStats.u32MemKernelNonPaged = perfInfo.KernelNonpaged; /* already in pages */ req.guestStats.u32MemSystemCache = perfInfo.SystemCache; /* already in pages */ req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PROCESSES | VBOX_GUEST_STAT_THREADS | VBOX_GUEST_STAT_HANDLES | VBOX_GUEST_STAT_MEM_COMMIT_TOTAL | VBOX_GUEST_STAT_MEM_KERNEL_TOTAL | VBOX_GUEST_STAT_MEM_KERNEL_PAGED | VBOX_GUEST_STAT_MEM_KERNEL_NONPAGED | VBOX_GUEST_STAT_MEM_SYSTEM_CACHE; } else VBoxServiceVerbose(3, "VBoxServiceVMStatsReport: GetPerformanceInfo failed with %d\n", GetLastError()); } /* Query CPU load information */ cbStruct = systemInfo.dwNumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); pProcInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)RTMemAlloc(cbStruct); if (!pProcInfo) return; /* Unfortunately GetSystemTimes is XP SP1 and up only, so we need to use the semi-undocumented NtQuerySystemInformation */ NTSTATUS rc = gCtx.pfnNtQuerySystemInformation(SystemProcessorPerformanceInformation, pProcInfo, cbStruct, &cbReturned); if ( !rc && cbReturned == cbStruct) { if (gCtx.au64LastCpuLoad_Kernel == 0) { /* first time */ gCtx.au64LastCpuLoad_Idle[0] = pProcInfo->IdleTime.QuadPart; gCtx.au64LastCpuLoad_Kernel[0] = pProcInfo->KernelTime.QuadPart; gCtx.au64LastCpuLoad_User[0] = pProcInfo->UserTime.QuadPart; Sleep(250); rc = gCtx.pfnNtQuerySystemInformation(SystemProcessorPerformanceInformation, pProcInfo, cbStruct, &cbReturned); Assert(!rc); } uint64_t deltaIdle = (pProcInfo->IdleTime.QuadPart - gCtx.au64LastCpuLoad_Idle[0]); uint64_t deltaKernel = (pProcInfo->KernelTime.QuadPart - gCtx.au64LastCpuLoad_Kernel[0]); uint64_t deltaUser = (pProcInfo->UserTime.QuadPart - gCtx.au64LastCpuLoad_User[0]); deltaKernel -= deltaIdle; /* idle time is added to kernel time */ uint64_t ullTotalTime = deltaIdle + deltaKernel + deltaUser; if (ullTotalTime == 0) /* Prevent division through zero. */ ullTotalTime = 1; req.guestStats.u32CpuLoad_Idle = (uint32_t)(deltaIdle * 100 / ullTotalTime); req.guestStats.u32CpuLoad_Kernel = (uint32_t)(deltaKernel* 100 / ullTotalTime); req.guestStats.u32CpuLoad_User = (uint32_t)(deltaUser * 100 / ullTotalTime); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_CPU_LOAD_IDLE | VBOX_GUEST_STAT_CPU_LOAD_KERNEL | VBOX_GUEST_STAT_CPU_LOAD_USER; gCtx.au64LastCpuLoad_Idle[0] = pProcInfo->IdleTime.QuadPart; gCtx.au64LastCpuLoad_Kernel[0] = pProcInfo->KernelTime.QuadPart; gCtx.au64LastCpuLoad_User[0] = pProcInfo->UserTime.QuadPart; /** @todo SMP: report details for each CPU? */ } for (uint32_t i = 0; i < systemInfo.dwNumberOfProcessors; i++) { req.guestStats.u32CpuId = i; rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics (CPU %u) reported successfully!\n", i); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: DeviceIoControl (stats report) failed with %d\n", GetLastError()); } RTMemFree(pProcInfo); #elif defined(RT_OS_LINUX) VMMDevReportGuestStats req; RT_ZERO(req); PRTSTREAM pStrm; char szLine[256]; char *psz; int rc = RTStrmOpen("/proc/meminfo", "r", &pStrm); if (RT_SUCCESS(rc)) { uint64_t u64Kb; uint64_t u64Total = 0, u64Free = 0, u64Buffers = 0, u64Cached = 0, u64PagedTotal = 0; for (;;) { rc = RTStrmGetLine(pStrm, szLine, sizeof(szLine)); if (RT_FAILURE(rc)) break; if (strstr(szLine, "MemTotal:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[9]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64Total = u64Kb * _1K; } else if (strstr(szLine, "MemFree:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[8]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64Free = u64Kb * _1K; } else if (strstr(szLine, "Buffers:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[8]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64Buffers = u64Kb * _1K; } else if (strstr(szLine, "Cached:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[7]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64Cached = u64Kb * _1K; } else if (strstr(szLine, "SwapTotal:") == szLine) { rc = RTStrToUInt64Ex(RTStrStripL(&szLine[10]), &psz, 0, &u64Kb); if (RT_SUCCESS(rc)) u64PagedTotal = u64Kb * _1K; } } req.guestStats.u32PhysMemTotal = u64Total / _4K; req.guestStats.u32PhysMemAvail = (u64Free + u64Buffers + u64Cached) / _4K; req.guestStats.u32MemSystemCache = (u64Buffers + u64Cached) / _4K; req.guestStats.u32PageFileSize = u64PagedTotal / _4K; RTStrmClose(pStrm); } else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: memory info not available!\n"); req.guestStats.u32PageSize = getpagesize(); req.guestStats.u32StatCaps = VBOX_GUEST_STAT_PHYS_MEM_TOTAL | VBOX_GUEST_STAT_PHYS_MEM_AVAIL | VBOX_GUEST_STAT_MEM_SYSTEM_CACHE | VBOX_GUEST_STAT_PAGE_FILE_SIZE; #ifdef VBOX_WITH_MEMBALLOON req.guestStats.u32PhysMemBalloon = VBoxServiceBalloonQueryPages(_4K); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PHYS_MEM_BALLOON; #else req.guestStats.u32PhysMemBalloon = 0; #endif /** @todo req.guestStats.u32Threads */ /** @todo req.guestStats.u32Processes */ /* req.guestStats.u32Handles doesn't make sense here. */ /** @todo req.guestStats.u32MemoryLoad */ /** @todo req.guestStats.u32MemCommitTotal */ /** @todo req.guestStats.u32MemKernelTotal */ /** @todo req.guestStats.u32MemKernelPaged, make any sense? = u32MemKernelTotal? */ /** @todo req.guestStats.u32MemKernelNonPaged, make any sense? = 0? */ bool fCpuInfoAvail = false; rc = RTStrmOpen("/proc/stat", "r", &pStrm); if (RT_SUCCESS(rc)) { for (;;) { rc = RTStrmGetLine(pStrm, szLine, sizeof(szLine)); if (RT_FAILURE(rc)) break; if ( strstr(szLine, "cpu") == szLine && strlen(szLine) > 3 && RT_C_IS_DIGIT(szLine[3])) { uint32_t u32CpuId; rc = RTStrToUInt32Ex(&szLine[3], &psz, 0, &u32CpuId); if (u32CpuId < VMM_MAX_CPU_COUNT) { uint64_t u64User = 0; if (RT_SUCCESS(rc)) rc = RTStrToUInt64Ex(RTStrStripL(psz), &psz, 0, &u64User); uint64_t u64Nice = 0; if (RT_SUCCESS(rc)) rc = RTStrToUInt64Ex(RTStrStripL(psz), &psz, 0, &u64Nice); uint64_t u64System = 0; if (RT_SUCCESS(rc)) rc = RTStrToUInt64Ex(RTStrStripL(psz), &psz, 0, &u64System); uint64_t u64Idle = 0; if (RT_SUCCESS(rc)) rc = RTStrToUInt64Ex(RTStrStripL(psz), &psz, 0, &u64Idle); uint64_t u64DeltaIdle = u64Idle - gCtx.au64LastCpuLoad_Idle[u32CpuId]; uint64_t u64DeltaSystem = u64System - gCtx.au64LastCpuLoad_Kernel[u32CpuId]; uint64_t u64DeltaUser = u64User - gCtx.au64LastCpuLoad_User[u32CpuId]; uint64_t u64DeltaNice = u64Nice - gCtx.au64LastCpuLoad_Nice[u32CpuId]; uint64_t u64DeltaAll = u64DeltaIdle + u64DeltaSystem + u64DeltaUser + u64DeltaNice; if (u64DeltaAll == 0) /* Prevent division through zero. */ u64DeltaAll = 1; gCtx.au64LastCpuLoad_Idle[u32CpuId] = u64Idle; gCtx.au64LastCpuLoad_Kernel[u32CpuId] = u64System; gCtx.au64LastCpuLoad_User[u32CpuId] = u64User; gCtx.au64LastCpuLoad_Nice[u32CpuId] = u64Nice; req.guestStats.u32CpuId = u32CpuId; req.guestStats.u32CpuLoad_Idle = (uint32_t)(u64DeltaIdle * 100 / u64DeltaAll); req.guestStats.u32CpuLoad_Kernel = (uint32_t)(u64DeltaSystem * 100 / u64DeltaAll); req.guestStats.u32CpuLoad_User = (uint32_t)((u64DeltaUser + u64DeltaNice) * 100 / u64DeltaAll); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_CPU_LOAD_IDLE | VBOX_GUEST_STAT_CPU_LOAD_KERNEL | VBOX_GUEST_STAT_CPU_LOAD_USER; fCpuInfoAvail = true; rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics (CPU %u) reported successfully!\n", u32CpuId); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: stats report failed with rc=%Rrc\n", rc); } else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: skipping information for CPU%u\n", u32CpuId); } } RTStrmClose(pStrm); } if (!fCpuInfoAvail) { VBoxServiceVerbose(3, "VBoxStatsReportStatistics: CPU info not available!\n"); rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics reported successfully!\n"); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: stats report failed with rc=%Rrc\n", rc); } #elif defined(RT_OS_SOLARIS) VMMDevReportGuestStats req; RT_ZERO(req); kstat_ctl_t *pStatKern = kstat_open(); if (pStatKern) { /* * Memory statistics. */ uint64_t u64Total = 0, u64Free = 0, u64Buffers = 0, u64Cached = 0, u64PagedTotal = 0; int rc = -1; kstat_t *pStatPages = kstat_lookup(pStatKern, "unix", 0 /* instance */, "system_pages"); if (pStatPages) { rc = kstat_read(pStatKern, pStatPages, NULL /* optional-copy-buf */); if (rc != -1) { kstat_named_t *pStat = NULL; pStat = (kstat_named_t *)kstat_data_lookup(pStatPages, "pagestotal"); if (pStat) u64Total = pStat->value.ul; pStat = (kstat_named_t *)kstat_data_lookup(pStatPages, "freemem"); if (pStat) u64Free = pStat->value.ul; } } kstat_t *pStatZFS = kstat_lookup(pStatKern, "zfs", 0 /* instance */, "arcstats"); if (pStatZFS) { rc = kstat_read(pStatKern, pStatZFS, NULL /* optional-copy-buf */); if (rc != -1) { kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(pStatZFS, "size"); if (pStat) u64Cached = pStat->value.ul; } } /* * The vminfo are accumulative counters updated every "N" ticks. Let's get the * number of stat updates so far and use that to divide the swap counter. */ kstat_t *pStatInfo = kstat_lookup(pStatKern, "unix", 0 /* instance */, "sysinfo"); if (pStatInfo) { sysinfo_t SysInfo; rc = kstat_read(pStatKern, pStatInfo, &SysInfo); if (rc != -1) { kstat_t *pStatVMInfo = kstat_lookup(pStatKern, "unix", 0 /* instance */, "vminfo"); if (pStatVMInfo) { vminfo_t VMInfo; rc = kstat_read(pStatKern, pStatVMInfo, &VMInfo); if (rc != -1) { Assert(SysInfo.updates != 0); u64PagedTotal = VMInfo.swap_avail / SysInfo.updates; } } } } req.guestStats.u32PhysMemTotal = u64Total; /* already in pages */ req.guestStats.u32PhysMemAvail = u64Free; /* already in pages */ req.guestStats.u32MemSystemCache = u64Cached / _4K; req.guestStats.u32PageFileSize = u64PagedTotal; /* already in pages */ /** @todo req.guestStats.u32Threads */ /** @todo req.guestStats.u32Processes */ /** @todo req.guestStats.u32Handles -- ??? */ /** @todo req.guestStats.u32MemoryLoad */ /** @todo req.guestStats.u32MemCommitTotal */ /** @todo req.guestStats.u32MemKernelTotal */ /** @todo req.guestStats.u32MemKernelPaged */ /** @todo req.guestStats.u32MemKernelNonPaged */ req.guestStats.u32PageSize = getpagesize(); req.guestStats.u32StatCaps = VBOX_GUEST_STAT_PHYS_MEM_TOTAL | VBOX_GUEST_STAT_PHYS_MEM_AVAIL | VBOX_GUEST_STAT_MEM_SYSTEM_CACHE | VBOX_GUEST_STAT_PAGE_FILE_SIZE; #ifdef VBOX_WITH_MEMBALLOON req.guestStats.u32PhysMemBalloon = VBoxServiceBalloonQueryPages(_4K); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PHYS_MEM_BALLOON; #else req.guestStats.u32PhysMemBalloon = 0; #endif /* * CPU statistics. */ cpu_stat_t StatCPU; RT_ZERO(StatCPU); kstat_t *pStatNode = NULL; uint32_t cCPUs = 0; bool fCpuInfoAvail = false; for (pStatNode = pStatKern->kc_chain; pStatNode != NULL; pStatNode = pStatNode->ks_next) { if (!strcmp(pStatNode->ks_module, "cpu_stat")) { rc = kstat_read(pStatKern, pStatNode, &StatCPU); if (rc == -1) break; uint64_t u64Idle = StatCPU.cpu_sysinfo.cpu[CPU_IDLE]; uint64_t u64User = StatCPU.cpu_sysinfo.cpu[CPU_USER]; uint64_t u64System = StatCPU.cpu_sysinfo.cpu[CPU_KERNEL]; uint64_t u64DeltaIdle = u64Idle - gCtx.au64LastCpuLoad_Idle[cCPUs]; uint64_t u64DeltaSystem = u64System - gCtx.au64LastCpuLoad_Kernel[cCPUs]; uint64_t u64DeltaUser = u64User - gCtx.au64LastCpuLoad_User[cCPUs]; uint64_t u64DeltaAll = u64DeltaIdle + u64DeltaSystem + u64DeltaUser; if (u64DeltaAll == 0) /* Prevent division through zero. */ u64DeltaAll = 1; gCtx.au64LastCpuLoad_Idle[cCPUs] = u64Idle; gCtx.au64LastCpuLoad_Kernel[cCPUs] = u64System; gCtx.au64LastCpuLoad_User[cCPUs] = u64User; req.guestStats.u32CpuId = cCPUs; req.guestStats.u32CpuLoad_Idle = (uint32_t)(u64DeltaIdle * 100 / u64DeltaAll); req.guestStats.u32CpuLoad_Kernel = (uint32_t)(u64DeltaSystem * 100 / u64DeltaAll); req.guestStats.u32CpuLoad_User = (uint32_t)(u64DeltaUser * 100 / u64DeltaAll); req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_CPU_LOAD_IDLE | VBOX_GUEST_STAT_CPU_LOAD_KERNEL | VBOX_GUEST_STAT_CPU_LOAD_USER; fCpuInfoAvail = true; rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics (CPU %u) reported successfully!\n", cCPUs); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: stats report failed with rc=%Rrc\n", rc); cCPUs++; } } /* * Report whatever statistics were collected. */ if (!fCpuInfoAvail) { VBoxServiceVerbose(3, "VBoxStatsReportStatistics: CPU info not available!\n"); rc = VbglR3StatReport(&req); if (RT_SUCCESS(rc)) VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics reported successfully!\n"); else VBoxServiceVerbose(3, "VBoxStatsReportStatistics: stats report failed with rc=%Rrc\n", rc); } kstat_close(pStatKern); } #else /* todo: implement for other platforms. */ #endif }
STDMETHODIMP VBoxDnDDropTarget::Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { RT_NOREF(pt); AssertPtrReturn(pDataObject, E_INVALIDARG); AssertPtrReturn(pdwEffect, E_INVALIDARG); LogFlowFunc(("mFormatEtc.cfFormat=%RI16 (%s), pDataObject=0x%p, grfKeyState=0x%x, x=%ld, y=%ld\n", mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat), pDataObject, grfKeyState, pt.x, pt.y)); HRESULT hr = S_OK; if (mFormatEtc.cfFormat) /* Did we get a supported format yet? */ { /* Make sure the data object's data format is still valid. */ hr = pDataObject->QueryGetData(&mFormatEtc); AssertMsg(SUCCEEDED(hr), ("Data format changed to invalid between DragEnter() and Drop(), cfFormat=%RI16 (%s), hr=%Rhrc\n", mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat), hr)); } int rc = VINF_SUCCESS; if (SUCCEEDED(hr)) { STGMEDIUM stgMed; hr = pDataObject->GetData(&mFormatEtc, &stgMed); if (SUCCEEDED(hr)) { /* * First stage: Prepare the access to the storage medium. * For now we only support HGLOBAL stuff. */ PVOID pvData = NULL; /** @todo Put this in an own union? */ switch (mFormatEtc.tymed) { case TYMED_HGLOBAL: pvData = GlobalLock(stgMed.hGlobal); if (!pvData) { LogFlowFunc(("Locking HGLOBAL storage failed with %Rrc\n", RTErrConvertFromWin32(GetLastError()))); rc = VERR_INVALID_HANDLE; hr = E_INVALIDARG; /* Set special hr for OLE. */ } break; default: AssertMsgFailed(("Storage medium type %RI32 supported\n", mFormatEtc.tymed)); rc = VERR_NOT_SUPPORTED; hr = DV_E_TYMED; /* Set special hr for OLE. */ break; } if (RT_SUCCESS(rc)) { /* * Second stage: Do the actual copying of the data object's data, * based on the storage medium type. */ switch (mFormatEtc.cfFormat) { case CF_TEXT: /* Fall through is intentional. */ case CF_UNICODETEXT: { AssertPtr(pvData); size_t cbSize = GlobalSize(pvData); LogFlowFunc(("CF_TEXT/CF_UNICODETEXT 0x%p got %zu bytes\n", pvData, cbSize)); if (cbSize) { char *pszText = NULL; rc = mFormatEtc.cfFormat == CF_TEXT /* ANSI codepage -> UTF-8 */ ? RTStrCurrentCPToUtf8(&pszText, (char *)pvData) /* Unicode -> UTF-8 */ : RTUtf16ToUtf8((PCRTUTF16)pvData, &pszText); if (RT_SUCCESS(rc)) { AssertPtr(pszText); size_t cbText = strlen(pszText) + 1; /* Include termination. */ mpvData = RTMemDup((void *)pszText, cbText); mcbData = cbText; RTStrFree(pszText); pszText = NULL; } } break; } case CF_HDROP: { AssertPtr(pvData); /* Convert to a string list, separated by \r\n. */ DROPFILES *pDropFiles = (DROPFILES *)pvData; AssertPtr(pDropFiles); bool fUnicode = RT_BOOL(pDropFiles->fWide); /* Get the offset of the file list. */ Assert(pDropFiles->pFiles >= sizeof(DROPFILES)); /* Note: This is *not* pDropFiles->pFiles! DragQueryFile only * will work with the plain storage medium pointer! */ HDROP hDrop = (HDROP)(pvData); /* First, get the file count. */ /** @todo Does this work on Windows 2000 / NT4? */ char *pszFiles = NULL; uint32_t cchFiles = 0; UINT cFiles = DragQueryFile(hDrop, UINT32_MAX /* iFile */, NULL /* lpszFile */, 0 /* cchFile */); LogFlowFunc(("CF_HDROP got %RU16 file(s)\n", cFiles)); for (UINT i = 0; i < cFiles; i++) { UINT cch = DragQueryFile(hDrop, i /* File index */, NULL /* Query size first */, 0 /* cchFile */); Assert(cch); if (RT_FAILURE(rc)) break; char *pszFile = NULL; /* UTF-8 version. */ UINT cchFile = 0; if (fUnicode) { /* Allocate enough space (including terminator). */ WCHAR *pwszFile = (WCHAR *)RTMemAlloc((cch + 1) * sizeof(WCHAR)); if (pwszFile) { cchFile = DragQueryFileW(hDrop, i /* File index */, pwszFile, cch + 1 /* Include terminator */); AssertMsg(cchFile == cch, ("cchCopied (%RU16) does not match cchFile (%RU16)\n", cchFile, cch)); rc = RTUtf16ToUtf8(pwszFile, &pszFile); AssertRC(rc); RTMemFree(pwszFile); } else rc = VERR_NO_MEMORY; } else /* ANSI */ { /* Allocate enough space (including terminator). */ pszFile = (char *)RTMemAlloc((cch + 1) * sizeof(char)); if (pszFile) { cchFile = DragQueryFileA(hDrop, i /* File index */, pszFile, cchFile + 1 /* Include terminator */); AssertMsg(cchFile == cch, ("cchCopied (%RU16) does not match cchFile (%RU16)\n", cchFile, cch)); } else rc = VERR_NO_MEMORY; } if (RT_SUCCESS(rc)) { LogFlowFunc(("\tFile: %s (cchFile=%RU32)\n", pszFile, cchFile)); rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFile, cchFile); if (RT_SUCCESS(rc)) cchFiles += cchFile; } if (pszFile) RTStrFree(pszFile); if (RT_FAILURE(rc)) break; /* Add separation between filenames. * Note: Also do this for the last element of the list. */ rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, "\r\n", 2 /* Bytes */); if (RT_SUCCESS(rc)) cchFiles += 2; /* Include \r\n */ } if (RT_SUCCESS(rc)) { cchFiles += 1; /* Add string termination. */ uint32_t cbFiles = cchFiles * sizeof(char); LogFlowFunc(("cFiles=%u, cchFiles=%RU32, cbFiles=%RU32, pszFiles=0x%p\n", cFiles, cchFiles, cbFiles, pszFiles)); /* Translate the list into URI elements. */ DnDURIList lstURI; rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles, DNDURILIST_FLAGS_ABSOLUTE_PATHS); if (RT_SUCCESS(rc)) { RTCString strRoot = lstURI.RootToString(); size_t cbRoot = strRoot.length() + 1; /* Include termination */ mpvData = RTMemAlloc(cbRoot); if (mpvData) { memcpy(mpvData, strRoot.c_str(), cbRoot); mcbData = cbRoot; } else rc = VERR_NO_MEMORY; } } LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n", rc, pszFiles, cFiles, cchFiles)); if (pszFiles) RTStrFree(pszFiles); break; } default: /* Note: Should not happen due to the checks done in DragEnter(). */ AssertMsgFailed(("Format of type %RI16 (%s) not supported\n", mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat))); hr = DV_E_CLIPFORMAT; /* Set special hr for OLE. */ break; } /* * Third stage: Unlock + release access to the storage medium again. */ switch (mFormatEtc.tymed) { case TYMED_HGLOBAL: GlobalUnlock(stgMed.hGlobal); break; default: AssertMsgFailed(("Really should not happen -- see init stage!\n")); break; } } /* Release storage medium again. */ ReleaseStgMedium(&stgMed); /* Signal waiters. */ mDroppedRc = rc; RTSemEventSignal(hEventDrop); } } if (RT_SUCCESS(rc)) { /* Note: pt is not used since we don't need to differentiate within our * proxy window. */ *pdwEffect = VBoxDnDDropTarget::GetDropEffect(grfKeyState, *pdwEffect); } else *pdwEffect = DROPEFFECT_NONE; if (mpWndParent) mpWndParent->hide(); LogFlowFunc(("Returning with hr=%Rhrc (%Rrc), mFormatEtc.cfFormat=%RI16 (%s), *pdwEffect=%RI32\n", hr, rc, mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat), *pdwEffect)); return hr; }
HRESULT VBoxD3DIfCreateForRc(struct VBOXWDDMDISP_RESOURCE *pRc) { PVBOXWDDMDISP_DEVICE pDevice = pRc->pDevice; HRESULT hr = E_FAIL; IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice); if (VBOXWDDMDISP_IS_TEXTURE(pRc->RcDesc.fFlags)) { PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[0]; IDirect3DBaseTexture9 *pD3DIfTex; HANDLE hSharedHandle = pAllocation->hSharedHandle; void **pavClientMem = NULL; VBOXDISP_D3DIFTYPE enmD3DIfType = VBOXDISP_D3DIFTYPE_UNDEFINED; hr = S_OK; if (pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM) { pavClientMem = (void**)RTMemAlloc(sizeof (pavClientMem[0]) * pRc->cAllocations); Assert(pavClientMem); if (pavClientMem) { for (UINT i = 0; i < pRc->cAllocations; ++i) { Assert(pRc->aAllocations[i].pvMem); pavClientMem[i] = pRc->aAllocations[i].pvMem; } } else hr = E_FAIL; } #ifdef DEBUG if (!pRc->RcDesc.fFlags.CubeMap) { PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[0]; uint32_t tstW = pAlloc->SurfDesc.width; uint32_t tstH = pAlloc->SurfDesc.height; for (UINT i = 1; i < pRc->cAllocations; ++i) { tstW /= 2; tstH /= 2; pAlloc = &pRc->aAllocations[i]; Assert((pAlloc->SurfDesc.width == tstW) || (!tstW && (pAlloc->SurfDesc.width==1))); Assert((pAlloc->SurfDesc.height == tstH) || (!tstH && (pAlloc->SurfDesc.height==1))); } } #endif if (SUCCEEDED(hr)) { if (pRc->RcDesc.fFlags.CubeMap) { if ( (pAllocation->SurfDesc.width!=pAllocation->SurfDesc.height) || (pRc->cAllocations%6!=0)) { WARN(("unexpected cubemap texture config: (%d ; %d), allocs: %d", pAllocation->SurfDesc.width, pAllocation->SurfDesc.height, pRc->cAllocations)); hr = E_INVALIDARG; } else { hr = pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9CreateCubeTexture((IDirect3DDevice9Ex *)pDevice9If, pAllocation->SurfDesc.d3dWidth, VBOXDISP_CUBEMAP_LEVELS_COUNT(pRc), vboxDDI2D3DUsage(pRc->RcDesc.fFlags), vboxDDI2D3DFormat(pRc->RcDesc.enmFormat), vboxDDI2D3DPool(pRc->RcDesc.enmPool), (IDirect3DCubeTexture9**)&pD3DIfTex, #ifdef VBOXWDDMDISP_DEBUG_NOSHARED NULL, #else pRc->RcDesc.fFlags.SharedResource ? &hSharedHandle : NULL, #endif pavClientMem); Assert(hr == S_OK); Assert(pD3DIfTex); enmD3DIfType = VBOXDISP_D3DIFTYPE_CUBE_TEXTURE; } } else if (pRc->RcDesc.fFlags.Volume) { hr = pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9CreateVolumeTexture((IDirect3DDevice9Ex *)pDevice9If, pAllocation->SurfDesc.d3dWidth, pAllocation->SurfDesc.height, pAllocation->SurfDesc.depth, pRc->cAllocations, vboxDDI2D3DUsage(pRc->RcDesc.fFlags), vboxDDI2D3DFormat(pRc->RcDesc.enmFormat), vboxDDI2D3DPool(pRc->RcDesc.enmPool), (IDirect3DVolumeTexture9**)&pD3DIfTex, #ifdef VBOXWDDMDISP_DEBUG_NOSHARED NULL, #else pRc->RcDesc.fFlags.SharedResource ? &hSharedHandle : NULL, #endif pavClientMem); Assert(hr == S_OK); Assert(pD3DIfTex); enmD3DIfType = VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE; } else { hr = pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9CreateTexture((IDirect3DDevice9Ex *)pDevice9If, pAllocation->SurfDesc.d3dWidth, pAllocation->SurfDesc.height, pRc->cAllocations, vboxDDI2D3DUsage(pRc->RcDesc.fFlags), vboxDDI2D3DFormat(pRc->RcDesc.enmFormat), vboxDDI2D3DPool(pRc->RcDesc.enmPool), (IDirect3DTexture9**)&pD3DIfTex, #ifdef VBOXWDDMDISP_DEBUG_NOSHARED NULL, #else pRc->RcDesc.fFlags.SharedResource ? &hSharedHandle : NULL, #endif pavClientMem); Assert(hr == S_OK); Assert(pD3DIfTex); enmD3DIfType = VBOXDISP_D3DIFTYPE_TEXTURE; } if (SUCCEEDED(hr)) { Assert(pD3DIfTex); Assert(enmD3DIfType != VBOXDISP_D3DIFTYPE_UNDEFINED); #ifndef VBOXWDDMDISP_DEBUG_NOSHARED Assert(!!(pRc->RcDesc.fFlags.SharedResource) == !!(hSharedHandle)); #endif for (UINT i = 0; i < pRc->cAllocations; ++i) { PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[i]; pAlloc->enmD3DIfType = enmD3DIfType; pAlloc->pD3DIf = pD3DIfTex; pAlloc->hSharedHandle = hSharedHandle; if (i > 0) pD3DIfTex->AddRef(); } } } if (pavClientMem) RTMemFree(pavClientMem); } else if (pRc->RcDesc.fFlags.RenderTarget || pRc->RcDesc.fFlags.Primary) { for (UINT i = 0; i < pRc->cAllocations; ++i) { PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i]; HANDLE hSharedHandle = pAllocation->hSharedHandle; IDirect3DSurface9* pD3D9Surf; if ( #ifdef VBOX_WITH_CROGL (pDevice->pAdapter->u32VBox3DCaps & CR_VBOX_CAP_TEX_PRESENT) || #endif pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC) { hr = pDevice9If->CreateRenderTarget(pAllocation->SurfDesc.width, pAllocation->SurfDesc.height, vboxDDI2D3DFormat(pRc->RcDesc.enmFormat), vboxDDI2D3DMultiSampleType(pRc->RcDesc.enmMultisampleType), pRc->RcDesc.MultisampleQuality, !pRc->RcDesc.fFlags.NotLockable /* BOOL Lockable */, &pD3D9Surf, #ifdef VBOXWDDMDISP_DEBUG_NOSHARED NULL #else pRc->RcDesc.fFlags.SharedResource ? &hSharedHandle : NULL #endif ); Assert(hr == S_OK); } else if (pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE) { do { BOOL bNeedPresent; if (pRc->cAllocations != 1) { WARN(("unexpected config: more than one (%d) shared primary for rc", pRc->cAllocations)); hr = E_FAIL; break; } PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainFindCreate(pDevice, pAllocation, &bNeedPresent); Assert(bNeedPresent); if (!pSwapchain) { WARN(("vboxWddmSwapchainFindCreate failed")); hr = E_OUTOFMEMORY; break; } hr = vboxWddmSwapchainChkCreateIf(pDevice, pSwapchain); if (!SUCCEEDED(hr)) { WARN(("vboxWddmSwapchainChkCreateIf failed hr 0x%x", hr)); Assert(pAllocation->enmD3DIfType == VBOXDISP_D3DIFTYPE_UNDEFINED); Assert(!pAllocation->pD3DIf); vboxWddmSwapchainDestroy(pDevice, pSwapchain); break; } Assert(pAllocation->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE); Assert(pAllocation->pD3DIf); pD3D9Surf = (IDirect3DSurface9*)pAllocation->pD3DIf; break; } while (0); } else { WARN(("unexpected alloc type %d", pAllocation->enmType)); hr = E_FAIL; } if (SUCCEEDED(hr)) { Assert(pD3D9Surf); pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE; pAllocation->pD3DIf = pD3D9Surf; #ifndef VBOXWDDMDISP_DEBUG_NOSHARED Assert(!!(pRc->RcDesc.fFlags.SharedResource) == !!(hSharedHandle)); #endif pAllocation->hSharedHandle = hSharedHandle; hr = S_OK; continue; /* fail branch */ pD3D9Surf->Release(); } for (UINT j = 0; j < i; ++j) { pRc->aAllocations[j].pD3DIf->Release(); } break; } if (SUCCEEDED(hr)) { if (pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM) { Assert(0); vboxDispD3DIfSurfSynchMem(pRc); } } } else if (pRc->RcDesc.fFlags.ZBuffer) { for (UINT i = 0; i < pRc->cAllocations; ++i) { PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i]; IDirect3DSurface9 *pD3D9Surf; hr = pDevice9If->CreateDepthStencilSurface(pAllocation->SurfDesc.width, pAllocation->SurfDesc.height, vboxDDI2D3DFormat(pRc->RcDesc.enmFormat), vboxDDI2D3DMultiSampleType(pRc->RcDesc.enmMultisampleType), pRc->RcDesc.MultisampleQuality, TRUE /* @todo: BOOL Discard */, &pD3D9Surf, NULL /*HANDLE* pSharedHandle*/); Assert(hr == S_OK); if (hr == S_OK) { Assert(pD3D9Surf); pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE; pAllocation->pD3DIf = pD3D9Surf; } else { for (UINT j = 0; j < i; ++j) { pRc->aAllocations[j].pD3DIf->Release(); } break; } } if (SUCCEEDED(hr)) { if (pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM) { vboxDispD3DIfSurfSynchMem(pRc); } } } else if (pRc->RcDesc.fFlags.VertexBuffer) { for (UINT i = 0; i < pRc->cAllocations; ++i) { PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i]; IDirect3DVertexBuffer9 *pD3D9VBuf; hr = pDevice9If->CreateVertexBuffer(pAllocation->SurfDesc.width, vboxDDI2D3DUsage(pRc->RcDesc.fFlags) & (~D3DUSAGE_DYNAMIC) /* <- avoid using dynamic to ensure wine does not switch do user buffer */ , pRc->RcDesc.Fvf, vboxDDI2D3DPool(pRc->RcDesc.enmPool), &pD3D9VBuf, NULL /*HANDLE* pSharedHandle*/); Assert(hr == S_OK); if (hr == S_OK) { Assert(pD3D9VBuf); pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_VERTEXBUFFER; pAllocation->pD3DIf = pD3D9VBuf; } else { for (UINT j = 0; j < i; ++j) { pRc->aAllocations[j].pD3DIf->Release(); } break; } } if (SUCCEEDED(hr)) { if (pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM) { vboxDispD3DIfSurfSynchMem(pRc); } } } else if (pRc->RcDesc.fFlags.IndexBuffer) { for (UINT i = 0; i < pRc->cAllocations; ++i) { PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i]; IDirect3DIndexBuffer9 *pD3D9IBuf; hr = pDevice9If->CreateIndexBuffer(pAllocation->SurfDesc.width, vboxDDI2D3DUsage(pRc->RcDesc.fFlags), vboxDDI2D3DFormat(pRc->RcDesc.enmFormat), vboxDDI2D3DPool(pRc->RcDesc.enmPool), &pD3D9IBuf, NULL /*HANDLE* pSharedHandle*/ ); Assert(hr == S_OK); if (hr == S_OK) { Assert(pD3D9IBuf); pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_INDEXBUFFER; pAllocation->pD3DIf = pD3D9IBuf; } else { for (UINT j = 0; j < i; ++j) { pRc->aAllocations[j].pD3DIf->Release(); } break; } } if (SUCCEEDED(hr)) { if (pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM) { vboxDispD3DIfSurfSynchMem(pRc); } } } else { hr = E_FAIL; WARN(("unsupported rc flags, %d", pRc->RcDesc.fFlags.Value)); } return hr; }
RTDECL(int) RTLocalIpcSessionConnect(PRTLOCALIPCSESSION phSession, const char *pszName, uint32_t fFlags) { AssertPtrReturn(phSession, VERR_INVALID_POINTER); AssertPtrReturn(pszName, VERR_INVALID_POINTER); AssertReturn(*pszName, VERR_INVALID_PARAMETER); AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* Flags currently unused, must be 0. */ PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)RTMemAlloc(sizeof(*pThis)); if (!pThis) return VERR_NO_MEMORY; pThis->u32Magic = RTLOCALIPCSESSION_MAGIC; pThis->cRefs = 1; /* The one we return. */ pThis->fIOPending = false; pThis->fZeroByteRead = false; pThis->fCancelled = false; pThis->pbBounceBuf = NULL; pThis->cbBounceBufAlloc = 0; pThis->cbBounceBufUsed = 0; int rc = RTCritSectInit(&pThis->CritSect); if (RT_SUCCESS(rc)) { pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL /*lpName*/); if (pThis->hEvent != NULL) { RT_ZERO(pThis->OverlappedIO); pThis->OverlappedIO.Internal = STATUS_PENDING; pThis->OverlappedIO.hEvent = pThis->hEvent; PSECURITY_DESCRIPTOR pSecDesc; rc = rtLocalIpcServerWinAllocSecurityDescriptior(&pSecDesc, false /* Client */); if (RT_SUCCESS(rc)) { char *pszPipe; if (RTStrAPrintf(&pszPipe, "%s%s", RTLOCALIPC_WIN_PREFIX, pszName)) { SECURITY_ATTRIBUTES SecAttrs; SecAttrs.nLength = sizeof(SECURITY_ATTRIBUTES); SecAttrs.lpSecurityDescriptor = pSecDesc; SecAttrs.bInheritHandle = FALSE; HANDLE hPipe = CreateFile(pszPipe, /* pipe name */ GENERIC_READ /* read and write access */ | GENERIC_WRITE, 0, /* no sharing */ &SecAttrs, /* lpSecurityAttributes */ OPEN_EXISTING, /* opens existing pipe */ FILE_FLAG_OVERLAPPED, /* default attributes */ NULL); /* no template file */ RTStrFree(pszPipe); if (hPipe != INVALID_HANDLE_VALUE) { LocalFree(pSecDesc); pThis->hNmPipe = hPipe; *phSession = pThis; return VINF_SUCCESS; } else rc = RTErrConvertFromWin32(GetLastError()); } else rc = VERR_NO_MEMORY; LocalFree(pSecDesc); } BOOL fRc = CloseHandle(pThis->hEvent); AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc); } else rc = RTErrConvertFromWin32(GetLastError()); int rc2 = RTCritSectDelete(&pThis->CritSect); AssertRC(rc2); } RTMemFree(pThis); return rc; }
RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *pszCmdLine, const char *pszSeparators) { /* * Some input validation. */ AssertPtr(pszCmdLine); AssertPtr(pcArgs); AssertPtr(ppapszArgv); if (!pszSeparators) pszSeparators = " \t\n\r"; else AssertPtr(pszSeparators); size_t const cchSeparators = strlen(pszSeparators); AssertReturn(cchSeparators > 0, VERR_INVALID_PARAMETER); /* * Parse the command line and chop off it into argv individual argv strings. */ int rc = VINF_SUCCESS; const char *pszSrc = pszCmdLine; char *pszDup = (char *)RTMemAlloc(strlen(pszSrc) + 1); char *pszDst = pszDup; if (!pszDup) return VERR_NO_STR_MEMORY; char **papszArgs = NULL; unsigned iArg = 0; while (*pszSrc) { /* Skip stuff */ rc = rtGetOptSkipDelimiters(&pszSrc, pszSeparators, cchSeparators); if (RT_FAILURE(rc)) break; if (!*pszSrc) break; /* Start a new entry. */ if ((iArg % 32) == 0) { void *pvNew = RTMemRealloc(papszArgs, (iArg + 33) * sizeof(char *)); if (!pvNew) { rc = VERR_NO_MEMORY; break; } papszArgs = (char **)pvNew; } papszArgs[iArg++] = pszDst; /* Parse and copy the string over. */ RTUNICP CpQuote = 0; RTUNICP Cp; for (;;) { rc = RTStrGetCpEx(&pszSrc, &Cp); if (RT_FAILURE(rc) || !Cp) break; if (!CpQuote) { if (Cp == '"' || Cp == '\'') CpQuote = Cp; else if (rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators)) break; else pszDst = RTStrPutCp(pszDst, Cp); } else if (CpQuote != Cp) pszDst = RTStrPutCp(pszDst, Cp); else CpQuote = 0; } *pszDst++ = '\0'; if (RT_FAILURE(rc) || !Cp) break; } if (RT_FAILURE(rc)) { RTMemFree(pszDup); RTMemFree(papszArgs); return rc; } /* * Terminate the array. * Check for empty string to make sure we've got an array. */ if (iArg == 0) { RTMemFree(pszDup); papszArgs = (char **)RTMemAlloc(1 * sizeof(char *)); if (!papszArgs) return VERR_NO_MEMORY; } papszArgs[iArg] = NULL; *pcArgs = iArg; *ppapszArgv = papszArgs; return VINF_SUCCESS; }
RTDECL(int) RTHandleTableAlloc(RTHANDLETABLE hHandleTable, void *pvObj, uint32_t *ph) { /* validate the input */ PRTHANDLETABLEINT pThis = (PRTHANDLETABLEINT)hHandleTable; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, VERR_INVALID_HANDLE); AssertReturn(!(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT), VERR_INVALID_FUNCTION); AssertReturn(!RTHT_IS_FREE(pvObj), VERR_INVALID_PARAMETER); AssertPtrReturn(ph, VERR_INVALID_POINTER); *ph = pThis->uBase - 1; /* * Allocation loop. */ rtHandleTableLock(pThis); int rc; do { /* * Try grab a free entry from the head of the free list. */ uint32_t i = pThis->iFreeHead; if (i != NIL_RTHT_INDEX) { PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)rtHandleTableLookupSimpleIdx(pThis, i); Assert(pFree); if (i == pThis->iFreeTail) pThis->iFreeTail = pThis->iFreeHead = NIL_RTHT_INDEX; else pThis->iFreeHead = RTHT_GET_FREE_IDX(pFree); pThis->cCurAllocated++; Assert(pThis->cCurAllocated <= pThis->cCur); /* * Setup the entry and return. */ PRTHTENTRY pEntry = (PRTHTENTRY)pFree; pEntry->pvObj = pvObj; *ph = i + pThis->uBase; rc = VINF_SUCCESS; } /* * Must expand the handle table, unless it's full. */ else if (pThis->cCur >= pThis->cMax) { rc = VERR_NO_MORE_HANDLES; Assert(pThis->cCur == pThis->cCurAllocated); } else { /* * Do we have to expand the 1st level table too? */ uint32_t const iLevel1 = pThis->cCur / RTHT_LEVEL2_ENTRIES; uint32_t cLevel1 = iLevel1 >= pThis->cLevel1 ? pThis->cLevel1 + PAGE_SIZE / sizeof(void *) : 0; if (cLevel1 > pThis->cMax / RTHT_LEVEL2_ENTRIES) cLevel1 = pThis->cMax / RTHT_LEVEL2_ENTRIES; Assert(!cLevel1 || pThis->cMax / RTHT_LEVEL2_ENTRIES >= RTHT_LEVEL1_DYN_ALLOC_THRESHOLD); /* leave the lock (never do fancy stuff from behind a spinlock). */ rtHandleTableUnlock(pThis); /* * Do the allocation(s). */ rc = VERR_TRY_AGAIN; void **papvLevel1 = NULL; if (cLevel1) { papvLevel1 = (void **)RTMemAlloc(sizeof(void *) * cLevel1); if (!papvLevel1) return VERR_NO_MEMORY; } PRTHTENTRY paTable = (PRTHTENTRY)RTMemAlloc(sizeof(*paTable) * RTHT_LEVEL2_ENTRIES); if (!paTable) { RTMemFree(papvLevel1); return VERR_NO_MEMORY; } /* re-enter the lock. */ rtHandleTableLock(pThis); /* * Insert the new bits, but be a bit careful as someone might have * raced us expanding the table. */ /* deal with the 1st level lookup expansion first */ if (cLevel1) { Assert(papvLevel1); if (cLevel1 > pThis->cLevel1) { /* Replace the 1st level table. */ memcpy(papvLevel1, pThis->papvLevel1, sizeof(void *) * pThis->cLevel1); memset(&papvLevel1[pThis->cLevel1], 0, sizeof(void *) * (cLevel1 - pThis->cLevel1)); pThis->cLevel1 = cLevel1; void **papvTmp = pThis->papvLevel1; pThis->papvLevel1 = papvLevel1; papvLevel1 = papvTmp; } /* free the obsolete one (outside the lock of course) */ rtHandleTableUnlock(pThis); RTMemFree(papvLevel1); rtHandleTableLock(pThis); } /* insert the table we allocated. */ uint32_t iLevel1New = pThis->cCur / RTHT_LEVEL2_ENTRIES; if ( iLevel1New < pThis->cLevel1 && pThis->cCur < pThis->cMax) { pThis->papvLevel1[iLevel1New] = paTable; /* link all entries into a free list. */ Assert(!(pThis->cCur % RTHT_LEVEL2_ENTRIES)); for (i = 0; i < RTHT_LEVEL2_ENTRIES - 1; i++) RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[i], i + 1 + pThis->cCur); RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[RTHT_LEVEL2_ENTRIES - 1], NIL_RTHT_INDEX); /* join the free list with the other. */ if (pThis->iFreeTail == NIL_RTHT_INDEX) pThis->iFreeHead = pThis->cCur; else { PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupSimpleIdx(pThis, pThis->iFreeTail); Assert(pPrev); RTHT_SET_FREE_IDX(pPrev, pThis->cCur); } pThis->iFreeTail = pThis->cCur + RTHT_LEVEL2_ENTRIES - 1; pThis->cCur += RTHT_LEVEL2_ENTRIES; } else { /* free the table (raced someone, and we lost). */ rtHandleTableUnlock(pThis); RTMemFree(paTable); rtHandleTableLock(pThis); } rc = VERR_TRY_AGAIN; } } while (rc == VERR_TRY_AGAIN); rtHandleTableUnlock(pThis); return rc; }
/** * Allocate memory from the heap. * * @returns Pointer to allocated memory. * @param pHeap Heap handle. * @param enmTag Statistics tag. Statistics are collected on a per tag * basis in addition to a global one. Thus we can easily * identify how memory is used by the VM. See MM_TAG_*. * @param cbSize Size of the block. * @param fZero Whether or not to zero the memory block. */ void *mmR3HeapAlloc(PMMHEAP pHeap, MMTAG enmTag, size_t cbSize, bool fZero) { #ifdef MMR3HEAP_WITH_STATISTICS RTCritSectEnter(&pHeap->Lock); /* * Find/alloc statistics nodes. */ pHeap->Stat.cAllocations++; PMMHEAPSTAT pStat = (PMMHEAPSTAT)RTAvlULGet(&pHeap->pStatTree, (AVLULKEY)enmTag); if (pStat) { pStat->cAllocations++; RTCritSectLeave(&pHeap->Lock); } else { pStat = (PMMHEAPSTAT)RTMemAllocZ(sizeof(MMHEAPSTAT)); if (!pStat) { pHeap->Stat.cFailures++; AssertMsgFailed(("Failed to allocate heap stat record.\n")); RTCritSectLeave(&pHeap->Lock); return NULL; } pStat->Core.Key = (AVLULKEY)enmTag; pStat->pHeap = pHeap; RTAvlULInsert(&pHeap->pStatTree, &pStat->Core); pStat->cAllocations++; RTCritSectLeave(&pHeap->Lock); /* register the statistics */ PUVM pUVM = pHeap->pUVM; const char *pszTag = mmGetTagName(enmTag); STAMR3RegisterFU(pUVM, &pStat->cbCurAllocated, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of bytes currently allocated.", "/MM/R3Heap/%s", pszTag); STAMR3RegisterFU(pUVM, &pStat->cAllocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.", "/MM/R3Heap/%s/cAllocations", pszTag); STAMR3RegisterFU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.", "/MM/R3Heap/%s/cReallocations", pszTag); STAMR3RegisterFU(pUVM, &pStat->cFrees, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.", "/MM/R3Heap/%s/cFrees", pszTag); STAMR3RegisterFU(pUVM, &pStat->cFailures, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of failures.", "/MM/R3Heap/%s/cFailures", pszTag); STAMR3RegisterFU(pUVM, &pStat->cbAllocated, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Total number of bytes allocated.", "/MM/R3Heap/%s/cbAllocated", pszTag); STAMR3RegisterFU(pUVM, &pStat->cbFreed, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Total number of bytes freed.", "/MM/R3Heap/%s/cbFreed", pszTag); } #endif /* * Validate input. */ if (cbSize == 0) { #ifdef MMR3HEAP_WITH_STATISTICS RTCritSectEnter(&pHeap->Lock); pStat->cFailures++; pHeap->Stat.cFailures++; RTCritSectLeave(&pHeap->Lock); #endif return NULL; } /* * Allocate heap block. */ cbSize = RT_ALIGN_Z(cbSize, MMR3HEAP_SIZE_ALIGNMENT) + sizeof(MMHEAPHDR); PMMHEAPHDR pHdr = (PMMHEAPHDR)(fZero ? RTMemAllocZ(cbSize) : RTMemAlloc(cbSize)); if (!pHdr) { AssertMsgFailed(("Failed to allocate heap block %d, enmTag=%x(%.4s).\n", cbSize, enmTag, &enmTag)); #ifdef MMR3HEAP_WITH_STATISTICS RTCritSectEnter(&pHeap->Lock); pStat->cFailures++; pHeap->Stat.cFailures++; RTCritSectLeave(&pHeap->Lock); #endif return NULL; } Assert(!((uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1))); RTCritSectEnter(&pHeap->Lock); /* * Init and link in the header. */ pHdr->pNext = NULL; pHdr->pPrev = pHeap->pTail; if (pHdr->pPrev) pHdr->pPrev->pNext = pHdr; else pHeap->pHead = pHdr; pHeap->pTail = pHdr; #ifdef MMR3HEAP_WITH_STATISTICS pHdr->pStat = pStat; #else pHdr->pStat = &pHeap->Stat; #endif pHdr->cbSize = cbSize; /* * Update statistics */ #ifdef MMR3HEAP_WITH_STATISTICS pStat->cbAllocated += cbSize; pStat->cbCurAllocated += cbSize; pHeap->Stat.cbAllocated += cbSize; pHeap->Stat.cbCurAllocated += cbSize; #endif RTCritSectLeave(&pHeap->Lock); return pHdr + 1; }
/** * 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; }
/** * Find IO port range for the parallel port and return the lower address. * * @returns parallel port IO address. * @param DevInst Device Instance for parallel port. */ static uint32_t drvHostWinFindIORangeResource(const DEVINST DevInst) { uint8_t *pBuf = NULL; short wHeaderSize; uint32_t u32Size; CONFIGRET cmRet; LOG_CONF firstLogConf; LOG_CONF nextLogConf; RES_DES rdPrevResDes; uint32_t u32ParportAddr = 0; wHeaderSize = sizeof(IO_DES); cmRet = CM_Get_First_Log_Conf(&firstLogConf, DevInst, ALLOC_LOG_CONF); if (cmRet != CR_SUCCESS) { cmRet = CM_Get_First_Log_Conf(&firstLogConf, DevInst, BOOT_LOG_CONF); if (cmRet != CR_SUCCESS) return 0; } cmRet = CM_Get_Next_Res_Des(&nextLogConf, firstLogConf, 2, 0L, 0L); if (cmRet != CR_SUCCESS) { CM_Free_Res_Des_Handle(firstLogConf); return 0; } /* This loop is based on the fact that only one resourece is assigned to * the LPT port. If multiple resources (address range) are assigned to * to LPT port, it will pick and return the last one */ for (;;) { u32Size = 0; cmRet = CM_Get_Res_Des_Data_Size((PULONG)(&u32Size), nextLogConf, 0L); if (cmRet != CR_SUCCESS) { LogFlowFunc(("Failed to get Size \n")); CM_Free_Res_Des_Handle(nextLogConf); break; } pBuf = (uint8_t *)RTMemAlloc(u32Size + 1); if (!pBuf) { LogFlowFunc(("Failed to get Buf %d\n", u32Size)); CM_Free_Res_Des_Handle(nextLogConf); break; } cmRet = CM_Get_Res_Des_Data(nextLogConf, pBuf, u32Size, 0L); if (cmRet != CR_SUCCESS) { LogFlowFunc(("Failed to get Des Data \n")); CM_Free_Res_Des_Handle(nextLogConf); if (pBuf) RTMemFree(pBuf); break; } LogFlowFunc(("call GetIOResource\n")); if (pBuf) u32ParportAddr = ((IO_DES *)pBuf)->IOD_Alloc_Base; LogFlowFunc(("called GetIOResource, ret=%#x\n", u32ParportAddr)); rdPrevResDes = 0; cmRet = CM_Get_Next_Res_Des(&rdPrevResDes, nextLogConf, 2, 0L, 0L); if (pBuf) RTMemFree(pBuf); if (cmRet != CR_SUCCESS) break; CM_Free_Res_Des_Handle(nextLogConf); nextLogConf = rdPrevResDes; } CM_Free_Res_Des_Handle(nextLogConf); LogFlowFunc(("return u32ParportAddr=%#x", u32ParportAddr)); return u32ParportAddr; }
int vbsfPathGuestToHost(SHFLCLIENTDATA *pClient, SHFLROOT hRoot, PCSHFLSTRING pGuestString, uint32_t cbGuestString, char **ppszHostPath, uint32_t *pcbHostPathRoot, uint32_t fu32Options, uint32_t *pfu32PathFlags) { #ifdef VBOX_STRICT /* * Check that the pGuestPath has correct size and encoding. */ if (ShflStringIsValidIn(pGuestString, cbGuestString, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)) == false) { LogFunc(("Invalid input string\n")); return VERR_INTERNAL_ERROR; } #else NOREF(cbGuestString); #endif /* * Resolve the root handle into a string. */ uint32_t cbRootLen = 0; const char *pszRoot = NULL; int rc = vbsfMappingsQueryHostRootEx(hRoot, &pszRoot, &cbRootLen); if (RT_FAILURE(rc)) { LogFunc(("invalid root\n")); return rc; } AssertReturn(cbRootLen > 0, VERR_INTERNAL_ERROR_2); /* vbsfMappingsQueryHostRootEx ensures this. */ /* * Get the UTF8 string with the relative path provided by the guest. * If guest uses UTF-16 then convert it to UTF-8. */ uint32_t cbGuestPath = 0; /* Shut up MSC */ const char *pchGuestPath = NULL; /* Ditto. */ char *pchGuestPathAllocated = NULL; /* Converted from UTF-16. */ if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8)) { /* UTF-8 */ cbGuestPath = pGuestString->u16Length; pchGuestPath = pGuestString->String.ach; } else { /* UTF-16 */ #ifdef RT_OS_DARWIN /* Misplaced hack! See todo! */ uint32_t cwcSrc = 0; PRTUTF16 pwszSrc = NULL; rc = vbsfNormalizeStringDarwin(&pGuestString->String.ucs2[0], pGuestString->u16Length / sizeof(RTUTF16), &pwszSrc, &cwcSrc); #else uint32_t const cwcSrc = pGuestString->u16Length / sizeof(RTUTF16); PCRTUTF16 const pwszSrc = &pGuestString->String.ucs2[0]; #endif if (RT_SUCCESS(rc)) { size_t cbPathAsUtf8 = RTUtf16CalcUtf8Len(pwszSrc); if (cbPathAsUtf8 >= cwcSrc) { /* Allocate buffer that will be able to contain the converted UTF-8 string. */ pchGuestPathAllocated = (char *)RTMemAlloc(cbPathAsUtf8 + 1); if (RT_LIKELY(pchGuestPathAllocated != NULL)) { if (RT_LIKELY(cbPathAsUtf8)) { size_t cchActual; char *pszDst = pchGuestPathAllocated; rc = RTUtf16ToUtf8Ex(pwszSrc, cwcSrc, &pszDst, cbPathAsUtf8 + 1, &cchActual); AssertRC(rc); AssertStmt(RT_FAILURE(rc) || cchActual == cbPathAsUtf8, rc = VERR_INTERNAL_ERROR_4); Assert(strlen(pszDst) == cbPathAsUtf8); } if (RT_SUCCESS(rc)) { /* Terminate the string. */ pchGuestPathAllocated[cbPathAsUtf8] = '\0'; cbGuestPath = (uint32_t)cbPathAsUtf8; Assert(cbGuestPath == cbPathAsUtf8); pchGuestPath = pchGuestPathAllocated; } } else { rc = VERR_NO_MEMORY; } } else { AssertFailed(); rc = VERR_INTERNAL_ERROR_3; } #ifdef RT_OS_DARWIN RTMemFree(pwszSrc); #endif } } char *pszFullPath = NULL; if (RT_SUCCESS(rc)) { LogFlowFunc(("Root %s path %.*s\n", pszRoot, cbGuestPath, pchGuestPath)); /* * Allocate enough memory to build the host full path from the root and the relative path. */ const uint32_t cbFullPathAlloc = cbRootLen + 1 + cbGuestPath + 1; /* root + possible_slash + relative + 0 */ pszFullPath = (char *)RTMemAlloc(cbFullPathAlloc); if (RT_LIKELY(pszFullPath != NULL)) { /* Buffer for the verified guest path. */ char *pchVerifiedPath = (char *)RTMemAlloc(cbGuestPath + 1); if (RT_LIKELY(pchVerifiedPath != NULL)) { /* Init the pointer for the guest relative path. */ uint32_t cbSrc = cbGuestPath; const char *pchSrc = pchGuestPath; /* Strip leading delimiters from the path the guest specified. */ while ( cbSrc > 0 && *pchSrc == pClient->PathDelimiter) { ++pchSrc; --cbSrc; } /* * Iterate the guest path components, verify each of them replacing delimiters with the host slash. */ char *pchDst = pchVerifiedPath; bool fLastComponentHasWildcard = false; for (; cbSrc > 0; --cbSrc, ++pchSrc) { if (RT_LIKELY(*pchSrc != pClient->PathDelimiter)) { if (RT_LIKELY(vbsfPathIsValidNameChar(*pchSrc))) { if (pfu32PathFlags && vbsfPathIsWildcardChar(*pchSrc)) { fLastComponentHasWildcard = true; } *pchDst++ = *pchSrc; } else { rc = VERR_INVALID_NAME; break; } } else { /* Replace with the host slash. */ *pchDst++ = RTPATH_SLASH; if (pfu32PathFlags && fLastComponentHasWildcard && cbSrc > 1) { /* Processed component has a wildcard and there are more characters in the path. */ *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_PREFIX; } fLastComponentHasWildcard = false; } } if (RT_SUCCESS(rc)) { *pchDst++ = 0; /* Construct the full host path removing '.' and '..'. */ rc = vbsfPathAbs(pszRoot, pchVerifiedPath, pszFullPath, cbFullPathAlloc); if (RT_SUCCESS(rc)) { if (pfu32PathFlags && fLastComponentHasWildcard) { *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_LAST; } /* Check if the full path is still within the shared folder. */ if (fu32Options & VBSF_O_PATH_CHECK_ROOT_ESCAPE) { if (!RTPathStartsWith(pszFullPath, pszRoot)) { rc = VERR_INVALID_NAME; } } if (RT_SUCCESS(rc)) { /* * If the host file system is case sensitive and the guest expects * a case insensitive fs, then correct the path components casing. */ if ( vbsfIsHostMappingCaseSensitive(hRoot) && !vbsfIsGuestMappingCaseSensitive(hRoot)) { const bool fWildCard = RT_BOOL(fu32Options & VBSF_O_PATH_WILDCARD); const bool fPreserveLastComponent = RT_BOOL(fu32Options & VBSF_O_PATH_PRESERVE_LAST_COMPONENT); rc = vbsfCorrectPathCasing(pClient, pszFullPath, strlen(pszFullPath), fWildCard, fPreserveLastComponent); } if (RT_SUCCESS(rc)) { LogFlowFunc(("%s\n", pszFullPath)); /* Return the full host path. */ *ppszHostPath = pszFullPath; if (pcbHostPathRoot) { /* Return the length of the root path without the trailing slash. */ *pcbHostPathRoot = RTPATH_IS_SLASH(pszFullPath[cbRootLen - 1]) ? cbRootLen - 1 : /* pszRoot already had the trailing slash. */ cbRootLen; /* pszRoot did not have the trailing slash. */ } } } } else { LogFunc(("vbsfPathAbs %Rrc\n", rc)); } } RTMemFree(pchVerifiedPath); } else { rc = VERR_NO_MEMORY; } } else { rc = VERR_NO_MEMORY; } } /* * Cleanup. */ RTMemFree(pchGuestPathAllocated); if (RT_SUCCESS(rc)) { return rc; } /* * Cleanup on failure. */ RTMemFree(pszFullPath); LogFunc(("%Rrc\n", rc)); return rc; }
RTDECL(int) RTTimerCreate(PRTTIMER *ppTimer, unsigned uMilliesInterval, PFNRTTIMER pfnTimer, void *pvUser) { #ifndef USE_WINMM /* * On windows we'll have to set the timer resolution before * we start the timer. */ ULONG ulMax = UINT32_MAX; ULONG ulMin = UINT32_MAX; ULONG ulCur = UINT32_MAX; NtQueryTimerResolution(&ulMax, &ulMin, &ulCur); Log(("NtQueryTimerResolution -> ulMax=%lu00ns ulMin=%lu00ns ulCur=%lu00ns\n", ulMax, ulMin, ulCur)); if (ulCur > ulMin && ulCur > 10000 /* = 1ms */) { if (NtSetTimerResolution(10000, TRUE, &ulCur) >= 0) Log(("Changed timer resolution to 1ms.\n")); else if (NtSetTimerResolution(20000, TRUE, &ulCur) >= 0) Log(("Changed timer resolution to 2ms.\n")); else if (NtSetTimerResolution(40000, TRUE, &ulCur) >= 0) Log(("Changed timer resolution to 4ms.\n")); else if (ulMin <= 50000 && NtSetTimerResolution(ulMin, TRUE, &ulCur) >= 0) Log(("Changed timer resolution to %lu *100ns.\n", ulMin)); else { AssertMsgFailed(("Failed to configure timer resolution!\n")); return VERR_INTERNAL_ERROR; } } #endif /* !USE_WINN */ /* * Create new timer. */ int rc = VERR_IPE_UNINITIALIZED_STATUS; PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer)); if (pTimer) { pTimer->u32Magic = RTTIMER_MAGIC; pTimer->pvUser = pvUser; pTimer->pfnTimer = pfnTimer; pTimer->iTick = 0; pTimer->uMilliesInterval = uMilliesInterval; #ifdef USE_WINMM /* sync kill doesn't work. */ pTimer->TimerId = timeSetEvent(uMilliesInterval, 0, rttimerCallback, (DWORD_PTR)pTimer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); if (pTimer->TimerId) { ULONG ulMax = UINT32_MAX; ULONG ulMin = UINT32_MAX; ULONG ulCur = UINT32_MAX; NtQueryTimerResolution(&ulMax, &ulMin, &ulCur); Log(("NtQueryTimerResolution -> ulMax=%lu00ns ulMin=%lu00ns ulCur=%lu00ns\n", ulMax, ulMin, ulCur)); *ppTimer = pTimer; return VINF_SUCCESS; } rc = VERR_INVALID_PARAMETER; #else /* !USE_WINMM */ /* * Create Win32 event semaphore. */ pTimer->iError = 0; pTimer->hTimer = CreateWaitableTimer(NULL, TRUE, NULL); if (pTimer->hTimer) { #ifdef USE_APC /* * Create wait semaphore. */ pTimer->hevWait = CreateEvent(NULL, FALSE, FALSE, NULL); if (pTimer->hevWait) #endif { /* * Kick off the timer thread. */ rc = RTThreadCreate(&pTimer->Thread, rttimerCallback, pTimer, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "Timer"); if (RT_SUCCESS(rc)) { /* * Wait for the timer to successfully create the timer * If we don't get a response in 10 secs, then we assume we're screwed. */ rc = RTThreadUserWait(pTimer->Thread, 10000); if (RT_SUCCESS(rc)) { rc = pTimer->iError; if (RT_SUCCESS(rc)) { *ppTimer = pTimer; return VINF_SUCCESS; } } ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); RTThreadWait(pTimer->Thread, 250, NULL); CancelWaitableTimer(pTimer->hTimer); } #ifdef USE_APC CloseHandle(pTimer->hevWait); #endif } CloseHandle(pTimer->hTimer); } #endif /* !USE_WINMM */ AssertMsgFailed(("Failed to create timer uMilliesInterval=%d. rc=%d\n", uMilliesInterval, rc)); RTMemFree(pTimer); } else rc = VERR_NO_MEMORY; return rc; }
/** * Corrects the casing of the final component * * @returns * @param pClient . * @param pszFullPath . * @param pszStartComponent . */ static int vbsfCorrectCasing(SHFLCLIENTDATA *pClient, char *pszFullPath, char *pszStartComponent) { Log2(("vbsfCorrectCasing: %s %s\n", pszFullPath, pszStartComponent)); AssertReturn((uintptr_t)pszFullPath < (uintptr_t)pszStartComponent - 1U, VERR_INTERNAL_ERROR_2); AssertReturn(pszStartComponent[-1] == RTPATH_DELIMITER, VERR_INTERNAL_ERROR_5); /* * Allocate a buffer that can hold really long file name entries as well as * the initial search pattern. */ size_t cchComponent = strlen(pszStartComponent); size_t cchParentDir = pszStartComponent - pszFullPath; size_t cchFullPath = cchParentDir + cchComponent; Assert(strlen(pszFullPath) == cchFullPath); size_t cbDirEntry = 4096; if (cchFullPath + 4 > cbDirEntry - RT_OFFSETOF(RTDIRENTRYEX, szName)) cbDirEntry = RT_OFFSETOF(RTDIRENTRYEX, szName) + cchFullPath + 4; PRTDIRENTRYEX pDirEntry = (PRTDIRENTRYEX)RTMemAlloc(cbDirEntry); if (pDirEntry == NULL) return VERR_NO_MEMORY; /* * Construct the search criteria in the szName member of pDirEntry. */ /** @todo This is quite inefficient, especially for directories with many * files. If any of the typically case sensitive host systems start * supporting opendir wildcard filters, it would make sense to build * one here with '?' for case foldable charaters. */ /** @todo Use RTDirOpen here and drop the whole uncessary path copying? */ int rc = RTPathJoinEx(pDirEntry->szName, cbDirEntry - RT_OFFSETOF(RTDIRENTRYEX, szName), pszFullPath, cchParentDir, RT_STR_TUPLE("*")); AssertRC(rc); if (RT_SUCCESS(rc)) { RTDIR hSearch = NULL; rc = RTDirOpenFiltered(&hSearch, pDirEntry->szName, RTDIRFILTER_WINNT, 0 /*fFlags*/); if (RT_SUCCESS(rc)) { for (;;) { size_t cbDirEntrySize = cbDirEntry; rc = RTDirReadEx(hSearch, pDirEntry, &cbDirEntrySize, RTFSOBJATTRADD_NOTHING, SHFL_RT_LINK(pClient)); if (rc == VERR_NO_MORE_FILES) break; if ( rc != VINF_SUCCESS && rc != VWRN_NO_DIRENT_INFO) { if ( rc == VERR_NO_TRANSLATION || rc == VERR_INVALID_UTF8_ENCODING) continue; AssertMsgFailed(("%Rrc\n", rc)); break; } Log2(("vbsfCorrectCasing: found %s\n", &pDirEntry->szName[0])); if ( pDirEntry->cbName == cchComponent && !RTStrICmp(pszStartComponent, &pDirEntry->szName[0])) { Log(("Found original name %s (%s)\n", &pDirEntry->szName[0], pszStartComponent)); strcpy(pszStartComponent, &pDirEntry->szName[0]); rc = VINF_SUCCESS; break; } } RTDirClose(hSearch); } } if (RT_FAILURE(rc)) Log(("vbsfCorrectCasing %s failed with %Rrc\n", pszStartComponent, rc)); RTMemFree(pDirEntry); return rc; }
/** * One test iteration with one file. * * The test is very simple, we load the file three times * into two different regions. The first two into each of the * regions the for compare usage. The third is loaded into one * and then relocated between the two and other locations a few times. * * @returns number of errors. * @param pszFilename The file to load the mess with. */ static int testLdrOne(const char *pszFilename) { RTLDRMOD hLdrMod; int rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_WHATEVER, &hLdrMod); if (RT_FAILURE(rc)) { RTPrintf("tstLdr: Failed to open '%s', rc=%Rrc. aborting test.\n", pszFilename, rc); Assert(hLdrMod == NIL_RTLDRMOD); return 1; } int rcRet = 1; size_t cb = RTLdrSize(hLdrMod); if (cb > 100) { void *pvBits = RTMemAlloc(cb); if (pvBits) { RTUINTPTR Addr = 0xc0000000; rc = RTLdrGetBits(hLdrMod, pvBits, Addr, testGetImport, NULL); if (RT_SUCCESS(rc)) { RTUINTPTR Value; rc = RTLdrGetSymbolEx(hLdrMod, pvBits, Addr, "Entrypoint", &Value); if (RT_SUCCESS(rc)) { unsigned off = Value - Addr; if (off < cb) { DISCPUSTATE Cpu; memset(&Cpu, 0, sizeof(Cpu)); Cpu.mode = CPUMODE_32BIT; if (MyDisBlock(&Cpu, (uintptr_t)pvBits + off, 200, Addr - (uintptr_t)pvBits)) { RTUINTPTR Addr2 = 0xd0000000; rc = RTLdrRelocate(hLdrMod, pvBits, Addr2, Addr, testGetImport, NULL); if (RT_SUCCESS(rc)) { if (MyDisBlock(&Cpu, (uintptr_t)pvBits + off, 200, Addr2 - (uintptr_t)pvBits)) rcRet = 0; else RTPrintf("tstLdr: Disassembly failed!\n"); } else RTPrintf("tstLdr: Relocate of '%s' from %#x to %#x failed, rc=%Rrc. Aborting test.\n", pszFilename, Addr2, Addr, rc); } else RTPrintf("tstLdr: Disassembly failed!\n"); } else RTPrintf("tstLdr: Invalid value for symbol '%s' in '%s'. off=%#x Value=%#x\n", "Entrypoint", pszFilename, off, Value); } else RTPrintf("tstLdr: Failed to resolve symbol '%s' in '%s', rc=%Rrc.\n", "Entrypoint", pszFilename, rc); } else RTPrintf("tstLdr: Failed to get bits for '%s', rc=%Rrc. aborting test\n", pszFilename, rc); RTMemFree(pvBits); } else RTPrintf("tstLdr: Out of memory '%s' cb=%d. aborting test.\n", pszFilename, cb); } else RTPrintf("tstLdr: Size is odd, '%s'. aborting test.\n", pszFilename); /* cleanup */ rc = RTLdrClose(hLdrMod); if (RT_FAILURE(rc)) { RTPrintf("tstLdr: Failed to close '%s', rc=%Rrc.\n", pszFilename, rc); rcRet++; } return rcRet; }
/** * 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; }
int DisplaySourceBitmap::initSourceBitmap(unsigned aScreenId, DISPLAYFBINFO *pFBInfo) { int rc = VINF_SUCCESS; if (pFBInfo->w == 0 || pFBInfo->h == 0) { return VERR_NOT_SUPPORTED; } BYTE *pAddress = NULL; ULONG ulWidth = 0; ULONG ulHeight = 0; ULONG ulBitsPerPixel = 0; ULONG ulBytesPerLine = 0; BitmapFormat_T bitmapFormat = BitmapFormat_Opaque; if (pFBInfo->pu8FramebufferVRAM && pFBInfo->u16BitsPerPixel == 32) { /* From VRAM. */ LogFunc(("%d from VRAM\n", aScreenId)); pAddress = pFBInfo->pu8FramebufferVRAM; ulWidth = pFBInfo->w; ulHeight = pFBInfo->h; ulBitsPerPixel = pFBInfo->u16BitsPerPixel; ulBytesPerLine = pFBInfo->u32LineSize; bitmapFormat = BitmapFormat_BGR; m.pu8Allocated = NULL; } else { /* Allocated byffer */ LogFunc(("%d allocated\n", aScreenId)); pAddress = NULL; ulWidth = pFBInfo->w; ulHeight = pFBInfo->h; ulBitsPerPixel = 32; ulBytesPerLine = ulWidth * 4; bitmapFormat = BitmapFormat_BGR; m.pu8Allocated = (uint8_t *)RTMemAlloc(ulBytesPerLine * ulHeight); if (m.pu8Allocated == NULL) { rc = VERR_NO_MEMORY; } else { pAddress = m.pu8Allocated; } } if (RT_SUCCESS(rc)) { m.pu8Address = pAddress; m.ulWidth = ulWidth; m.ulHeight = ulHeight; m.ulBitsPerPixel = ulBitsPerPixel; m.ulBytesPerLine = ulBytesPerLine; m.bitmapFormat = bitmapFormat; } return rc; }
/** * Shows a balloon message using VBoxTray's notification area in the * Windows task bar. * * @param hwndParent Window handle of parent. * @param string_size Size of variable string. * @param variables The actual variable string. * @param stacktop Pointer to a pointer to the current stack. */ VBOXINSTALLHELPER_EXPORT VBoxTrayShowBallonMsg(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) { EXDLL_INIT(); char szMsg[256]; char szTitle[128]; HRESULT hr = vboxPopString(szMsg, sizeof(szMsg) / sizeof(char)); if (SUCCEEDED(hr)) hr = vboxPopString(szTitle, sizeof(szTitle) / sizeof(char)); /** @todo Do we need to restore the stack on failure? */ if (SUCCEEDED(hr)) { RTR3InitDll(0); uint32_t cbMsg = sizeof(VBOXTRAYIPCMSG_SHOWBALLOONMSG) + strlen(szMsg) + 1 /* Include terminating zero */ + strlen(szTitle) + 1; /* Dito. */ Assert(cbMsg); PVBOXTRAYIPCMSG_SHOWBALLOONMSG pIpcMsg = (PVBOXTRAYIPCMSG_SHOWBALLOONMSG)RTMemAlloc(cbMsg); if (pIpcMsg) { /* Stuff in the strings. */ memcpy(pIpcMsg->szMsgContent, szMsg, strlen(szMsg) + 1); memcpy(pIpcMsg->szMsgTitle, szTitle, strlen(szTitle) + 1); /* Pop off the values in reverse order from the stack. */ if (SUCCEEDED(hr)) hr = vboxPopULong((ULONG*)&pIpcMsg->uType); if (SUCCEEDED(hr)) hr = vboxPopULong((ULONG*)&pIpcMsg->uShowMS); if (SUCCEEDED(hr)) { RTLOCALIPCSESSION hSession = 0; int rc = vboxConnectToVBoxTray(&hSession); if (RT_SUCCESS(rc)) { VBOXTRAYIPCHEADER ipcHdr = { VBOXTRAY_IPC_HDR_MAGIC, 0 /* Header version */, VBOXTRAYIPCMSGTYPE_SHOWBALLOONMSG, cbMsg }; rc = RTLocalIpcSessionWrite(hSession, &ipcHdr, sizeof(ipcHdr)); if (RT_SUCCESS(rc)) rc = RTLocalIpcSessionWrite(hSession, pIpcMsg, cbMsg); int rc2 = RTLocalIpcSessionClose(hSession); if (RT_SUCCESS(rc)) rc = rc2; } if (RT_FAILURE(rc)) hr = __HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE); } RTMemFree(pIpcMsg); } else hr = __HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); } /* Push simple return value on stack. */ SUCCEEDED(hr) ? pushstring("0") : pushstring("1"); }
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; }
int vmsvga3dLoadExec(PVGASTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) { RT_NOREF(uPass); PVMSVGA3DSTATE pState = pThis->svga.p3dState; AssertReturn(pState, VERR_NO_MEMORY); int rc; uint32_t cContexts, cSurfaces; LogFlow(("vmsvga3dLoadExec:\n")); #ifndef RT_OS_DARWIN /** @todo r=bird: this is normally done on the EMT, so for DARWIN we do that when loading saved state too now. See DevVGA-SVGA.cpp */ /* Must initialize now as the recreation calls below rely on an initialized 3d subsystem. */ vmsvga3dPowerOn(pThis); #endif /* Get the generic 3d state first. */ rc = SSMR3GetStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL); AssertRCReturn(rc, rc); cContexts = pState->cContexts; cSurfaces = pState->cSurfaces; pState->cContexts = 0; pState->cSurfaces = 0; /* Fetch all active contexts. */ for (uint32_t i = 0; i < cContexts; i++) { PVMSVGA3DCONTEXT pContext; uint32_t cid; /* Get the context id */ rc = SSMR3GetU32(pSSM, &cid); AssertRCReturn(rc, rc); if (cid != SVGA3D_INVALID_ID) { uint32_t cPixelShaderConst, cVertexShaderConst, cPixelShaders, cVertexShaders; LogFlow(("vmsvga3dLoadExec: Loading cid=%#x\n", cid)); #ifdef VMSVGA3D_OPENGL if (cid == VMSVGA3D_SHARED_CTX_ID) { i--; /* Not included in cContexts. */ pContext = &pState->SharedCtx; if (pContext->id != VMSVGA3D_SHARED_CTX_ID) { rc = vmsvga3dContextDefineOgl(pThis, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX); AssertRCReturn(rc, rc); } } else #endif { rc = vmsvga3dContextDefine(pThis, cid); AssertRCReturn(rc, rc); pContext = pState->papContexts[i]; } AssertReturn(pContext->id == cid, VERR_INTERNAL_ERROR); rc = SSMR3GetStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL); AssertRCReturn(rc, rc); cPixelShaders = pContext->cPixelShaders; cVertexShaders = pContext->cVertexShaders; cPixelShaderConst = pContext->state.cPixelShaderConst; cVertexShaderConst = pContext->state.cVertexShaderConst; pContext->cPixelShaders = 0; pContext->cVertexShaders = 0; pContext->state.cPixelShaderConst = 0; pContext->state.cVertexShaderConst = 0; /* Fetch all pixel shaders. */ for (uint32_t j = 0; j < cPixelShaders; j++) { VMSVGA3DSHADER shader; uint32_t shid; /* Fetch the id first. */ rc = SSMR3GetU32(pSSM, &shid); AssertRCReturn(rc, rc); if (shid != SVGA3D_INVALID_ID) { uint32_t *pData; /* Fetch a copy of the shader struct. */ rc = SSMR3GetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL); AssertRCReturn(rc, rc); pData = (uint32_t *)RTMemAlloc(shader.cbData); AssertReturn(pData, VERR_NO_MEMORY); rc = SSMR3GetMem(pSSM, pData, shader.cbData); AssertRCReturn(rc, rc); rc = vmsvga3dShaderDefine(pThis, cid, shid, shader.type, shader.cbData, pData); AssertRCReturn(rc, rc); RTMemFree(pData); } } /* Fetch all vertex shaders. */ for (uint32_t j = 0; j < cVertexShaders; j++) { VMSVGA3DSHADER shader; uint32_t shid; /* Fetch the id first. */ rc = SSMR3GetU32(pSSM, &shid); AssertRCReturn(rc, rc); if (shid != SVGA3D_INVALID_ID) { uint32_t *pData; /* Fetch a copy of the shader struct. */ rc = SSMR3GetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL); AssertRCReturn(rc, rc); pData = (uint32_t *)RTMemAlloc(shader.cbData); AssertReturn(pData, VERR_NO_MEMORY); rc = SSMR3GetMem(pSSM, pData, shader.cbData); AssertRCReturn(rc, rc); rc = vmsvga3dShaderDefine(pThis, cid, shid, shader.type, shader.cbData, pData); AssertRCReturn(rc, rc); RTMemFree(pData); } } /* Fetch pixel shader constants. */ for (uint32_t j = 0; j < cPixelShaderConst; j++) { VMSVGASHADERCONST ShaderConst; rc = SSMR3GetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL); AssertRCReturn(rc, rc); if (ShaderConst.fValid) { rc = vmsvga3dShaderSetConst(pThis, cid, j, SVGA3D_SHADERTYPE_PS, ShaderConst.ctype, 1, ShaderConst.value); AssertRCReturn(rc, rc); } } /* Fetch vertex shader constants. */ for (uint32_t j = 0; j < cVertexShaderConst; j++) { VMSVGASHADERCONST ShaderConst; rc = SSMR3GetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL); AssertRCReturn(rc, rc); if (ShaderConst.fValid) { rc = vmsvga3dShaderSetConst(pThis, cid, j, SVGA3D_SHADERTYPE_VS, ShaderConst.ctype, 1, ShaderConst.value); AssertRCReturn(rc, rc); } } if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_TEX_STAGES) { /* Load texture stage and samplers state. */ /* Number of stages/samplers. */ uint32_t cStages; rc = SSMR3GetU32(pSSM, &cStages); AssertRCReturn(rc, rc); /* Number of states. */ uint32_t cTextureStates; rc = SSMR3GetU32(pSSM, &cTextureStates); AssertRCReturn(rc, rc); for (uint32_t iStage = 0; iStage < cStages; ++iStage) { for (uint32_t j = 0; j < cTextureStates; ++j) { SVGA3dTextureState textureState; SSMR3GetU32(pSSM, &textureState.stage); uint32_t u32Name; SSMR3GetU32(pSSM, &u32Name); textureState.name = (SVGA3dTextureStateName)u32Name; rc = SSMR3GetU32(pSSM, &textureState.value); AssertRCReturn(rc, rc); if ( iStage < RT_ELEMENTS(pContext->state.aTextureStates) && j < RT_ELEMENTS(pContext->state.aTextureStates[0])) { pContext->state.aTextureStates[iStage][j] = textureState; } } } } if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA) { VMSVGA3DQUERY query; RT_ZERO(query); rc = SSMR3GetStructEx(pSSM, &query, sizeof(query), 0, g_aVMSVGA3DQUERYFields, NULL); AssertRCReturn(rc, rc); switch (query.enmQueryState) { case VMSVGA3DQUERYSTATE_BUILDING: /* Start collecting data. */ vmsvga3dQueryBegin(pThis, cid, SVGA3D_QUERYTYPE_OCCLUSION); /* Partial result. */ pContext->occlusion.u32QueryResult = query.u32QueryResult; break; case VMSVGA3DQUERYSTATE_ISSUED: /* Guest ended the query but did not read result. Result is restored. */ query.enmQueryState = VMSVGA3DQUERYSTATE_SIGNALED; RT_FALL_THRU(); case VMSVGA3DQUERYSTATE_SIGNALED: /* Create the query object. */ vmsvga3dOcclusionQueryCreate(pState, pContext); /* Update result and state. */ pContext->occlusion.enmQueryState = query.enmQueryState; pContext->occlusion.u32QueryResult = query.u32QueryResult; break; default: AssertFailed(); RT_FALL_THRU(); case VMSVGA3DQUERYSTATE_NULL: RT_ZERO(pContext->occlusion); break; } } } } #ifdef VMSVGA3D_OPENGL /* Make the shared context the current one. */ if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID) VMSVGA3D_SET_CURRENT_CONTEXT(pState, &pState->SharedCtx); #endif /* Fetch all surfaces. */ for (uint32_t i = 0; i < cSurfaces; i++) { uint32_t sid; /* Fetch the id first. */ rc = SSMR3GetU32(pSSM, &sid); AssertRCReturn(rc, rc); if (sid != SVGA3D_INVALID_ID) { VMSVGA3DSURFACE surface; LogFlow(("vmsvga3dLoadExec: Loading sid=%#x\n", sid)); /* Fetch the surface structure first. */ rc = SSMR3GetStructEx(pSSM, &surface, sizeof(surface), 0, g_aVMSVGA3DSURFACEFields, NULL); AssertRCReturn(rc, rc); { uint32_t cMipLevels = surface.faces[0].numMipLevels * surface.cFaces; PVMSVGA3DMIPMAPLEVEL pMipmapLevel = (PVMSVGA3DMIPMAPLEVEL)RTMemAlloc(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL)); AssertReturn(pMipmapLevel, VERR_NO_MEMORY); SVGA3dSize *pMipmapLevelSize = (SVGA3dSize *)RTMemAlloc(cMipLevels * sizeof(SVGA3dSize)); AssertReturn(pMipmapLevelSize, VERR_NO_MEMORY); /* Load the mip map level info. */ for (uint32_t face=0; face < surface.cFaces; face++) { for (uint32_t j = 0; j < surface.faces[0].numMipLevels; j++) { uint32_t idx = j + face * surface.faces[0].numMipLevels; /* Load the mip map level struct. */ rc = SSMR3GetStructEx(pSSM, &pMipmapLevel[idx], sizeof(pMipmapLevel[idx]), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL); AssertRCReturn(rc, rc); pMipmapLevelSize[idx] = pMipmapLevel[idx].mipmapSize; } } rc = vmsvga3dSurfaceDefine(pThis, sid, surface.surfaceFlags, surface.format, surface.faces, surface.multiSampleCount, surface.autogenFilter, cMipLevels, pMipmapLevelSize); AssertRCReturn(rc, rc); RTMemFree(pMipmapLevelSize); RTMemFree(pMipmapLevel); } PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid]; Assert(pSurface->id == sid); pSurface->fDirty = false; /* Load the mip map level data. */ for (uint32_t j = 0; j < pSurface->faces[0].numMipLevels * pSurface->cFaces; j++) { PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[j]; bool fDataPresent = false; /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */ Assert(pMipmapLevel->cbSurface); AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR); /* Fetch the data present boolean first. */ rc = SSMR3GetBool(pSSM, &fDataPresent); AssertRCReturn(rc, rc); Log(("Surface sid=%x: load mipmap level %d with %x bytes data (present=%d).\n", sid, j, pMipmapLevel->cbSurface, fDataPresent)); if (fDataPresent) { rc = SSMR3GetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface); AssertRCReturn(rc, rc); pMipmapLevel->fDirty = true; pSurface->fDirty = true; } else { pMipmapLevel->fDirty = false; } } } } #ifdef VMSVGA3D_OPENGL /* Reinitialize the shared context. */ LogFlow(("vmsvga3dLoadExec: pState->SharedCtx.id=%#x\n", pState->SharedCtx.id)); if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID) { rc = vmsvga3dLoadReinitContext(pThis, &pState->SharedCtx); AssertRCReturn(rc, rc); } #endif /* Reinitialize all active contexts. */ for (uint32_t i = 0; i < pState->cContexts; i++) { PVMSVGA3DCONTEXT pContext = pState->papContexts[i]; if (pContext->id != SVGA3D_INVALID_ID) { rc = vmsvga3dLoadReinitContext(pThis, pContext); AssertRCReturn(rc, rc); } } LogFlow(("vmsvga3dLoadExec: return success\n")); return VINF_SUCCESS; }
/** * Fetches more data from the file system. * * @returns IPRT status code * @param pThis The directory instance data. */ static int rtDirNtFetchMore(PRTDIR pThis) { Assert(!pThis->fDataUnread); /* * Allocate the buffer the first time around. * We do this in lazy fashion as some users of RTDirOpen will not actually * list any files, just open it for various reasons. */ bool fFirst = false; if (!pThis->pabBuffer) { fFirst = false; pThis->cbBufferAlloc = _256K; pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc); if (!pThis->pabBuffer) { do { pThis->cbBufferAlloc /= 4; pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc); } while (pThis->pabBuffer == NULL && pThis->cbBufferAlloc > _4K); if (!pThis->pabBuffer) return VERR_NO_MEMORY; } } /* * Read more. */ NTSTATUS rcNt; IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER; if (pThis->enmInfoClass != (FILE_INFORMATION_CLASS)0) { #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (pThis->enmInfoClass == FileMaximumInformation) { Ios.Information = 0; Ios.Status = rcNt = NtQueryDirectoryObject(pThis->hDir, pThis->pabBuffer, pThis->cbBufferAlloc, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, FALSE /*RestartScan*/, &pThis->uObjDirCtx, (PULONG)&Ios.Information); } else #endif rcNt = NtQueryDirectoryFile(pThis->hDir, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, pThis->pabBuffer, pThis->cbBufferAlloc, pThis->enmInfoClass, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->pNtFilterStr, FALSE /*RestartScan */); } else { /* * The first time around we have figure which info class we can use. * We prefer one which gives us file IDs, but we'll settle for less. */ pThis->enmInfoClass = FileIdBothDirectoryInformation; rcNt = NtQueryDirectoryFile(pThis->hDir, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, pThis->pabBuffer, pThis->cbBufferAlloc, pThis->enmInfoClass, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->pNtFilterStr, FALSE /*RestartScan */); if (!NT_SUCCESS(rcNt)) { pThis->enmInfoClass = FileBothDirectoryInformation; rcNt = NtQueryDirectoryFile(pThis->hDir, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, pThis->pabBuffer, pThis->cbBufferAlloc, pThis->enmInfoClass, RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, pThis->pNtFilterStr, FALSE /*RestartScan */); } } if (!NT_SUCCESS(rcNt)) { if (rcNt == STATUS_NO_MORE_FILES || rcNt == STATUS_NO_MORE_ENTRIES) return VERR_NO_MORE_FILES; return RTErrConvertFromNtStatus(rcNt); } Assert(Ios.Information > sizeof(*pThis->uCurData.pBoth)); /* * Set up the data members. */ pThis->uCurData.u = (uintptr_t)pThis->pabBuffer; pThis->cbBuffer = Ios.Information; int rc = rtDirNtCheckRecord(pThis); pThis->fDataUnread = RT_SUCCESS(rc); return rc; }
VBGLR3DECL(int) VbglR3DnDProcessNextMessage(CPVBGLR3DNDHGCMEVENT pEvent) { /* Validate input */ AssertPtrReturn(pEvent, VERR_INVALID_POINTER); uint32_t uMsg = 0; uint32_t uNumParms = 0; const uint32_t ccbFormats = _64K; const uint32_t ccbData = _1M; int rc = vbglR3DnDQueryNextHostMessageType(g_clientId, &uMsg, &uNumParms, true); if (RT_SUCCESS(rc)) { DO(("Got message %d\n", uMsg)); switch(uMsg) { case DragAndDropSvc::HOST_DND_HG_EVT_ENTER: case DragAndDropSvc::HOST_DND_HG_EVT_MOVE: case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED: { pEvent->uType = uMsg; pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats)); if (!pEvent->pszFormats) return VERR_NO_MEMORY; rc = vbglR3DnDHGProcessActionMessage(g_clientId, uMsg, &pEvent->uScreenId, &pEvent->u.a.uXpos, &pEvent->u.a.uYpos, &pEvent->u.a.uDefAction, &pEvent->u.a.uAllActions, pEvent->pszFormats, ccbFormats, &pEvent->cbFormats); break; } case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE: { pEvent->uType = uMsg; rc = vbglR3DnDHGProcessLeaveMessage(g_clientId); break; } case DragAndDropSvc::HOST_DND_HG_SND_DATA: { pEvent->uType = uMsg; pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats)); if (!pEvent->pszFormats) return VERR_NO_MEMORY; pEvent->u.b.pvData = RTMemAlloc(ccbData); if (!pEvent->u.b.pvData) { RTMemFree(pEvent->pszFormats); pEvent->pszFormats = NULL; return VERR_NO_MEMORY; } rc = vbglR3DnDHGProcessSendDataMessage(g_clientId, &pEvent->uScreenId, pEvent->pszFormats, ccbFormats, &pEvent->cbFormats, &pEvent->u.b.pvData, ccbData, &pEvent->u.b.cbData); break; } #ifdef VBOX_WITH_DRAG_AND_DROP_GH case DragAndDropSvc::HOST_DND_GH_REQ_PENDING: { pEvent->uType = uMsg; rc = vbglR3DnDGHProcessRequestPendingMessage(g_clientId, &pEvent->uScreenId); break; } case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED: { pEvent->uType = uMsg; pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats)); if (!pEvent->pszFormats) return VERR_NO_MEMORY; rc = vbglR3DnDGHProcessDroppedMessage(g_clientId, pEvent->pszFormats, ccbFormats, &pEvent->cbFormats, &pEvent->u.a.uDefAction); break; } #endif /* VBOX_WITH_DRAG_AND_DROP_GH */ case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL: { pEvent->uType = uMsg; rc = vbglR3DnDHGProcessCancelMessage(g_clientId); if (RT_SUCCESS(rc)) rc = VERR_CANCELLED; break; } default: AssertMsgFailedReturn(("Message %u isn't expected in this context", uMsg), VERR_INVALID_PARAMETER); break; } } return rc; }
RTDECL(int) RTPipeCreate(PRTPIPE phPipeRead, PRTPIPE phPipeWrite, uint32_t fFlags) { AssertPtrReturn(phPipeRead, VERR_INVALID_POINTER); AssertPtrReturn(phPipeWrite, VERR_INVALID_POINTER); AssertReturn(!(fFlags & ~RTPIPE_C_VALID_MASK), VERR_INVALID_PARAMETER); /* * Create the pipe and clear/set the close-on-exec flag as required. */ int aFds[2] = {-1, -1}; static int s_iNewPipeSyscall = 0; if (my_pipe_wrapper(aFds, &s_iNewPipeSyscall)) return RTErrConvertFromErrno(errno); int rc = VINF_SUCCESS; if (s_iNewPipeSyscall > 0) { /* created with close-on-exec set. */ if (fFlags & RTPIPE_C_INHERIT_READ) { if (fcntl(aFds[0], F_SETFD, 0)) rc = RTErrConvertFromErrno(errno); } if (fFlags & RTPIPE_C_INHERIT_WRITE) { if (fcntl(aFds[1], F_SETFD, 0)) rc = RTErrConvertFromErrno(errno); } } else { /* created with close-on-exec cleared. */ if (!(fFlags & RTPIPE_C_INHERIT_READ)) { if (fcntl(aFds[0], F_SETFD, FD_CLOEXEC)) rc = RTErrConvertFromErrno(errno); } if (!(fFlags & RTPIPE_C_INHERIT_WRITE)) { if (fcntl(aFds[1], F_SETFD, FD_CLOEXEC)) rc = RTErrConvertFromErrno(errno); } } if (RT_SUCCESS(rc)) { /* * Create the two handles. */ RTPIPEINTERNAL *pThisR = (RTPIPEINTERNAL *)RTMemAlloc(sizeof(RTPIPEINTERNAL)); if (pThisR) { RTPIPEINTERNAL *pThisW = (RTPIPEINTERNAL *)RTMemAlloc(sizeof(RTPIPEINTERNAL)); if (pThisW) { pThisR->u32Magic = RTPIPE_MAGIC; pThisW->u32Magic = RTPIPE_MAGIC; pThisR->fd = aFds[0]; pThisW->fd = aFds[1]; pThisR->fRead = true; pThisW->fRead = false; pThisR->u32State = RTPIPE_POSIX_BLOCKING; pThisW->u32State = RTPIPE_POSIX_BLOCKING; *phPipeRead = pThisR; *phPipeWrite = pThisW; /* * Before we leave, make sure to shut up SIGPIPE. */ signal(SIGPIPE, SIG_IGN); return VINF_SUCCESS; } RTMemFree(pThisR); rc = VERR_NO_MEMORY; } else rc = VERR_NO_MEMORY; } close(aFds[0]); close(aFds[1]); return rc; }
static int crVrScrCompositorRectsAssignBuffer(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRects) { Assert(cRects); if (pCompositor->cRectsBuffer >= cRects) { pCompositor->cRects = cRects; return VINF_SUCCESS; } if (pCompositor->cRectsBuffer) { Assert(pCompositor->paSrcRects); RTMemFree(pCompositor->paSrcRects); pCompositor->paSrcRects = NULL; Assert(pCompositor->paDstRects); RTMemFree(pCompositor->paDstRects); pCompositor->paDstRects = NULL; Assert(pCompositor->paDstUnstretchedRects); RTMemFree(pCompositor->paDstUnstretchedRects); pCompositor->paDstUnstretchedRects = NULL; } else { Assert(!pCompositor->paSrcRects); Assert(!pCompositor->paDstRects); Assert(!pCompositor->paDstUnstretchedRects); } pCompositor->paSrcRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paSrcRects) * cRects); if (pCompositor->paSrcRects) { pCompositor->paDstRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstRects) * cRects); if (pCompositor->paDstRects) { pCompositor->paDstUnstretchedRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstUnstretchedRects) * cRects); if (pCompositor->paDstUnstretchedRects) { pCompositor->cRects = cRects; pCompositor->cRectsBuffer = cRects; return VINF_SUCCESS; } RTMemFree(pCompositor->paDstRects); pCompositor->paDstRects = NULL; } else { WARN(("RTMemAlloc failed!")); } RTMemFree(pCompositor->paSrcRects); pCompositor->paSrcRects = NULL; } else { WARN(("RTMemAlloc failed!")); } pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED; pCompositor->cRectsBuffer = 0; return VERR_NO_MEMORY; }
/** * @callback_method_impl{dtrace_pops_t,dtps_provide} */ static void vboxDtPOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc) { PSUPDRVVDTPROVIDERCORE pProv = (PSUPDRVVDTPROVIDERCORE)pvProv; AssertPtrReturnVoid(pProv); LOG_DTRACE(("%s: %p / %p pDtProbeDesc=%p\n", __FUNCTION__, pProv, pProv->TracerData.DTrace.idProvider, pDtProbeDesc)); if (pDtProbeDesc) return; /* We don't generate probes, so never mind these requests. */ if (pProv->TracerData.DTrace.fZombie) return; dtrace_provider_id_t const idProvider = pProv->TracerData.DTrace.idProvider; AssertPtrReturnVoid(idProvider); AssertPtrReturnVoid(pProv->pHdr); AssertReturnVoid(pProv->pHdr->offProbeLocs != 0); uint32_t const cProbeLocs = pProv->pHdr->cbProbeLocs / sizeof(VTGPROBELOC); /* Need a buffer for extracting the function names and mangling them in case of collision. */ size_t const cbFnNmBuf = _4K + _1K; char *pszFnNmBuf = (char *)RTMemAlloc(cbFnNmBuf); if (!pszFnNmBuf) return; /* * Itereate the probe location list and register all probes related to * this provider. */ uint16_t const idxProv = (uint16_t)((PVTGDESCPROVIDER)((uintptr_t)pProv->pHdr + pProv->pHdr->offProviders) - pProv->pDesc); uint32_t idxProbeLoc; for (idxProbeLoc = 0; idxProbeLoc < cProbeLocs; idxProbeLoc++) { /* Skip probe location belonging to other providers or once that we've already reported. */ PCVTGPROBELOC pProbeLocRO = &pProv->paProbeLocsRO[idxProbeLoc]; PVTGDESCPROBE pProbeDesc = pProbeLocRO->pProbe; if (pProbeDesc->idxProvider != idxProv) continue; uint32_t *pidProbe; if (!pProv->fUmod) pidProbe = (uint32_t *)&pProbeLocRO->idProbe; else pidProbe = &pProv->paR0ProbeLocs[idxProbeLoc].idProbe; if (*pidProbe != 0) continue; /* The function name may need to be stripped since we're using C++ compilers for most of the code. ASSUMES nobody are brave/stupid enough to use function pointer returns without typedef'ing properly them (e.g. signal). */ const char *pszPrbName = vboxDtVtgGetString(pProv->pHdr, pProbeDesc->offName); const char *pszFunc = pProbeLocRO->pszFunction; const char *psz = strchr(pProbeLocRO->pszFunction, '('); size_t cch; if (psz) { /* skip blanks preceeding the parameter parenthesis. */ while ( (uintptr_t)psz > (uintptr_t)pProbeLocRO->pszFunction && RT_C_IS_BLANK(psz[-1])) psz--; /* Find the start of the function name. */ pszFunc = psz - 1; while ((uintptr_t)pszFunc > (uintptr_t)pProbeLocRO->pszFunction) { char ch = pszFunc[-1]; if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != ':') break; pszFunc--; } cch = psz - pszFunc; } else cch = strlen(pszFunc); RTStrCopyEx(pszFnNmBuf, cbFnNmBuf, pszFunc, cch); /* Look up the probe, if we have one in the same function, mangle the function name a little to avoid having to deal with having multiple location entries with the same probe ID. (lazy bird) */ Assert(!*pidProbe); if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE) { RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u", pProbeLocRO->uLine); if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE) { unsigned iOrd = 2; while (iOrd < 128) { RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u-%u", pProbeLocRO->uLine, iOrd); if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) == DTRACE_IDNONE) break; iOrd++; } if (iOrd >= 128) { LogRel(("VBoxDrv: More than 128 duplicate probe location instances %s at line %u in function %s [%s], probe %s\n", pProbeLocRO->uLine, pProbeLocRO->pszFunction, pszFnNmBuf, pszPrbName)); continue; } } } /* Create the probe. */ AssertCompile(sizeof(*pidProbe) == sizeof(dtrace_id_t)); *pidProbe = dtrace_probe_create(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName, 1 /*aframes*/, (void *)(uintptr_t)idxProbeLoc); pProv->TracerData.DTrace.cProvidedProbes++; } RTMemFree(pszFnNmBuf); LOG_DTRACE(("%s: returns\n", __FUNCTION__)); }
static DECLCALLBACK(int) drvHostALSAAudioInitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg, PDMAUDIORECSOURCE enmRecSource, uint32_t *pcSamples) { NOREF(pInterface); AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); AssertPtrReturn(pCfg, VERR_INVALID_POINTER); int rc; PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn; snd_pcm_t *phPCM = NULL; do { ALSAAUDIOSTREAMCFG req; req.fmt = drvHostALSAAudioFmtToALSA(pCfg->enmFormat); req.freq = pCfg->uHz; req.nchannels = pCfg->cChannels; req.period_size = s_ALSAConf.period_size_in; req.buffer_size = s_ALSAConf.buffer_size_in; ALSAAUDIOSTREAMCFG obt; rc = drvHostALSAAudioOpen(true /* fIn */, &req, &obt, &phPCM); if (RT_FAILURE(rc)) break; PDMAUDIOFMT enmFormat; PDMAUDIOENDIANNESS enmEnd; rc = drvHostALSAAudioALSAToFmt(obt.fmt, &enmFormat, &enmEnd); if (RT_FAILURE(rc)) break; PDMAUDIOSTREAMCFG streamCfg; streamCfg.uHz = obt.freq; streamCfg.cChannels = obt.nchannels; streamCfg.enmFormat = enmFormat; streamCfg.enmEndianness = enmEnd; rc = drvAudioStreamCfgToProps(&streamCfg, &pHstStrmIn->Props); if (RT_FAILURE(rc)) break; AssertBreakStmt(obt.samples, rc = VERR_INVALID_PARAMETER); size_t cbBuf = obt.samples * (1 << pHstStrmIn->Props.cShift); AssertBreakStmt(cbBuf, rc = VERR_INVALID_PARAMETER); pThisStrmIn->pvBuf = RTMemAlloc(cbBuf); if (!pThisStrmIn->pvBuf) { LogRel(("ALSA: Not enough memory for input ADC buffer (%RU32 samples, each %d bytes)\n", obt.samples, 1 << pHstStrmIn->Props.cShift)); rc = VERR_NO_MEMORY; break; } pThisStrmIn->cbBuf = cbBuf; pThisStrmIn->phPCM = phPCM; if (pcSamples) *pcSamples = obt.samples; } while (0); if (RT_FAILURE(rc)) drvHostALSAAudioClose(&phPCM); LogFlowFuncLeaveRC(rc); return rc; }
int main(int argc, char **argv) { /* * Init IPRT. */ int rc = RTR3InitExe(argc, &argv, 0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); /* * Locate a native DTrace command binary. */ bool fIsNativeDTrace = false; char szDTraceCmd[RTPATH_MAX]; szDTraceCmd[0] = '\0'; #if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) /* * 1. Try native first on platforms where it's applicable. */ static const char * const s_apszNativeDTrace[] = { "/usr/sbin/dtrace", "/sbin/dtrace", "/usr/bin/dtrace", "/bin/dtrace", "/usr/local/sbin/dtrace", "/usr/local/bin/dtrace" }; if (!RTEnvExist("VBOX_DTRACE_NO_NATIVE")) for (uint32_t i = 0; i < RT_ELEMENTS(s_apszNativeDTrace); i++) if (RTFileExists(s_apszNativeDTrace[i])) { fIsNativeDTrace = true; strcpy(szDTraceCmd, s_apszNativeDTrace[i]); # ifdef RT_OS_LINUX /** @todo Warn if the dtrace modules haven't been loaded or vboxdrv isn't * compiled against them. */ # endif break; } if (szDTraceCmd[0] == '\0') #endif { /* * 2. VBoxDTrace extension pack installed? * * Note! We cannot use the COM API here because this program is usually * run thru sudo or directly as root, even if the target * VirtualBox process is running as regular user. This is due to * the privileges required to run dtrace scripts on a host. */ rc = RTPathAppPrivateArch(szDTraceCmd, sizeof(szDTraceCmd)); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), VBOX_EXTPACK_INSTALL_DIR RTPATH_SLASH_STR VBOX_EXTPACK_VBOXDTRACE_MANGLED_NAME); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), RTBldCfgTargetDotArch()); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), "VBoxDTraceCmd"); if (RT_SUCCESS(rc)) rc = RTStrCat(szDTraceCmd, sizeof(szDTraceCmd), RTLdrGetSuff()); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing extension pack path: %Rrc", rc); if (!RTFileExists(szDTraceCmd)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unable to find a DTrace implementation. VBoxDTrace Extension Pack installed?"); fIsNativeDTrace = false; } /* * Construct a new command line that includes our libary. */ char szDTraceLibDir[RTPATH_MAX]; rc = RTPathAppPrivateNoArch(szDTraceLibDir, sizeof(szDTraceLibDir)); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceLibDir, sizeof(szDTraceLibDir), "dtrace" RTPATH_SLASH_STR "lib"); if (RT_SUCCESS(rc)) rc = RTPathAppend(szDTraceLibDir, sizeof(szDTraceLibDir), RTBldCfgTargetArch()); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing dtrace library path for VBox: %Rrc", rc); char **papszArgs = (char **)RTMemAlloc((argc + 3) * sizeof(char *)); if (!papszArgs) return RTMsgErrorExit(RTEXITCODE_FAILURE, "No memory for argument list."); int cArgs = 1; papszArgs[0] = fIsNativeDTrace ? szDTraceCmd : argv[0]; if (argc > 1) { papszArgs[cArgs++] = (char *)"-L"; papszArgs[cArgs++] = szDTraceLibDir; } for (int i = 1; i < argc; i++) papszArgs[cArgs++] = argv[i]; papszArgs[cArgs] = NULL; Assert(cArgs <= argc + 3); /* * The native DTrace we execute as a sub-process and wait for. */ RTEXITCODE rcExit; if (fIsNativeDTrace) { RTPROCESS hProc; rc = RTProcCreate(szDTraceCmd, papszArgs, RTENV_DEFAULT, 0, &hProc); if (RT_SUCCESS(rc)) { RTPROCSTATUS Status; rc = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &Status); if (RT_SUCCESS(rc)) { if (Status.enmReason == RTPROCEXITREASON_NORMAL) rcExit = (RTEXITCODE)Status.iStatus; else rcExit = RTEXITCODE_FAILURE; } else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error waiting for child process: %Rrc", rc); } else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error executing '%s': %Rrc", szDTraceCmd, rc); } /* * While the VBoxDTrace we load and call the main function of. */ else { RTERRINFOSTATIC ErrInfo; RTLDRMOD hMod; rc = SUPR3HardenedLdrLoadPlugIn(szDTraceCmd, &hMod, RTErrInfoInitStatic(&ErrInfo)); if (RT_SUCCESS(rc)) { PFNVBOXDTRACEMAIN pfnVBoxDTraceMain; rc = RTLdrGetSymbol(hMod, "VBoxDTraceMain", (void **)&pfnVBoxDTraceMain); if (RT_SUCCESS(rc)) rcExit = (RTEXITCODE)pfnVBoxDTraceMain(cArgs, papszArgs); else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error locating 'VBoxDTraceMain' in '%s': %Rrc", szDTraceCmd, rc); } else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error loading '%s': %Rrc (%s)", szDTraceCmd, rc, ErrInfo.szMsg); } return rcExit; }