HRESULT SystemProperties::getStorageControllerHotplugCapable(StorageControllerType_T aControllerType, BOOL *aHotplugCapable) { switch (aControllerType) { case StorageControllerType_IntelAhci: case StorageControllerType_USB: *aHotplugCapable = true; break; case StorageControllerType_LsiLogic: case StorageControllerType_LsiLogicSas: case StorageControllerType_BusLogic: case StorageControllerType_NVMe: case StorageControllerType_PIIX3: case StorageControllerType_PIIX4: case StorageControllerType_ICH6: case StorageControllerType_I82078: *aHotplugCapable = false; break; default: AssertMsgFailedReturn(("Invalid controller type %d\n", aControllerType), E_FAIL); } return S_OK; }
int DnDHGSendDataMessage::currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { if (!m_pNextPathMsg) return VERR_NO_DATA; /* Fill the data out of our current queued message. */ int rc = m_pNextPathMsg->currentMessage(uMsg, cParms, paParms); /* Has this message more data to deliver? */ if (!m_pNextPathMsg->isMessageWaiting()) { delete m_pNextPathMsg; m_pNextPathMsg = NULL; } /* File data to send? */ if (!m_pNextPathMsg) { if (m_uriList.isEmpty()) return rc; /* Create new messages based on our internal path list. Currently * this could be directories or regular files. */ PathEntry nextPath = m_uriList.first(); if (RTFS_IS_DIRECTORY(nextPath.m_fMode)) m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strGuestPath, nextPath.m_fMode, nextPath.m_cbSize, &DnDHGSendDataMessage::progressCallback, this); else if (RTFS_IS_FILE(nextPath.m_fMode)) m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strHostPath, nextPath.m_strGuestPath, nextPath.m_fMode, nextPath.m_cbSize, &DnDHGSendDataMessage::progressCallback, this); else AssertMsgFailedReturn(("type '%d' is not supported for path '%s'", nextPath.m_fMode, nextPath.m_strHostPath.c_str()), VERR_NO_DATA); m_uriList.removeFirst(); } return rc; }
/** * @interface_method_impl{DBGCCMDHLP,pfnVarFromDbgfAddr} */ static DECLCALLBACK(int) dbgcHlpVarFromDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGFADDRESS pAddress, PDBGCVAR pResult) { AssertPtrReturn(pAddress, VERR_INVALID_POINTER); AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER); AssertPtrReturn(pResult, VERR_INVALID_POINTER); switch (pAddress->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) { case DBGFADDRESS_FLAGS_FAR16: case DBGFADDRESS_FLAGS_FAR32: case DBGFADDRESS_FLAGS_FAR64: DBGCVAR_INIT_GC_FAR(pResult, pAddress->Sel, pAddress->off); break; case DBGFADDRESS_FLAGS_FLAT: DBGCVAR_INIT_GC_FLAT(pResult, pAddress->FlatPtr); break; case DBGFADDRESS_FLAGS_PHYS: DBGCVAR_INIT_GC_PHYS(pResult, pAddress->FlatPtr); break; default: DBGCVAR_INIT(pResult); AssertMsgFailedReturn(("%#x\n", pAddress->fFlags), VERR_INVALID_PARAMETER); break; } return VINF_SUCCESS; }
int DnDHGSendDataMessage::currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { if (!m_pNextPathMsg) return VERR_NO_DATA; /* Fill the data out of our current queued message. */ int rc = m_pNextPathMsg->currentMessage(uMsg, cParms, paParms); /* Has this message more data to deliver? */ if (!m_pNextPathMsg->isMessageWaiting()) { delete m_pNextPathMsg; m_pNextPathMsg = NULL; } /* File/directory data to send? */ if (!m_pNextPathMsg) { if (m_lstURI.IsEmpty()) return rc; /* Create new messages based on our internal path list. Currently * this could be directories or regular files. */ const DnDURIObject &nextObj = m_lstURI.First(); try { uint32_t fMode = nextObj.GetMode(); LogFlowFunc(("Processing srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n", nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str(), fMode, nextObj.GetSize(), RTFS_IS_DIRECTORY(fMode), RTFS_IS_FILE(fMode))); if (RTFS_IS_DIRECTORY(fMode)) m_pNextPathMsg = new DnDHGSendDirPrivate(nextObj, &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */, this /* pvProgressUser */); else if (RTFS_IS_FILE(fMode)) m_pNextPathMsg = new DnDHGSendFilePrivate(nextObj, &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */, this /* pvProgressUser */); else AssertMsgFailedReturn(("fMode=0x%x is not supported for srcPath=%s, dstPath=%s\n", fMode, nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str()), VERR_NO_DATA); m_lstURI.RemoveFirst(); } catch(std::bad_alloc &) { rc = VERR_NO_MEMORY; } } return rc; }
KHLP_DECL(int) kHlpGetEnv(const char *pszVar, char *pszVal, KSIZE cchVal) { int rc = RTEnvGetEx(RTENV_DEFAULT, pszVar, pszVal, cchVal, NULL); switch (rc) { case VINF_SUCCESS: return 0; case VERR_ENV_VAR_NOT_FOUND: return KERR_ENVVAR_NOT_FOUND; case VERR_BUFFER_OVERFLOW: return KERR_BUFFER_OVERFLOW; default: AssertMsgFailedReturn(("%Rrc\n", rc), rc); } }
/** * EMT worker for DBGFR3BpClear(). * * @returns VBox status code. * @param pVM Pointer to the VM. * @param iBp The id of the breakpoint which should be removed (cleared). * @thread EMT * @internal */ static DECLCALLBACK(int) dbgfR3BpClear(PVM pVM, uint32_t iBp) { /* * Validate input. */ PDBGFBP pBp = dbgfR3BpGet(pVM, iBp); if (!pBp) return VERR_DBGF_BP_NOT_FOUND; /* * Disarm the breakpoint if it's enabled. */ if (pBp->fEnabled) { pBp->fEnabled = false; int rc; switch (pBp->enmType) { case DBGFBPTYPE_REG: rc = dbgfR3BpRegDisarm(pVM, pBp); break; case DBGFBPTYPE_INT3: rc = dbgfR3BpInt3Disarm(pVM, pBp); break; case DBGFBPTYPE_REM: #ifdef VBOX_WITH_REM rc = REMR3BreakpointClear(pVM, pBp->GCPtr); #else rc = IEMBreakpointClear(pVM, pBp->GCPtr); #endif break; default: AssertMsgFailedReturn(("Invalid enmType=%d!\n", pBp->enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE); } AssertRCReturn(rc, rc); } /* * Free the breakpoint. */ dbgfR3BpFree(pVM, pBp); return VINF_SUCCESS; }
/** * EMT worker for DBGFR3BpEnable(). * * @returns VBox status code. * @param pVM Pointer to the VM. * @param iBp The id of the breakpoint which should be enabled. * @thread EMT * @internal */ static DECLCALLBACK(int) dbgfR3BpEnable(PVM pVM, uint32_t iBp) { /* * Validate input. */ PDBGFBP pBp = dbgfR3BpGet(pVM, iBp); if (!pBp) return VERR_DBGF_BP_NOT_FOUND; /* * Already enabled? */ if (pBp->fEnabled) return VINF_DBGF_BP_ALREADY_ENABLED; /* * Remove the breakpoint. */ int rc; pBp->fEnabled = true; switch (pBp->enmType) { case DBGFBPTYPE_REG: rc = dbgfR3BpRegArm(pVM, pBp); break; case DBGFBPTYPE_INT3: rc = dbgfR3BpInt3Arm(pVM, pBp); break; case DBGFBPTYPE_REM: #ifdef VBOX_WITH_REM rc = REMR3BreakpointSet(pVM, pBp->GCPtr); #else rc = IEMBreakpointSet(pVM, pBp->GCPtr); #endif break; default: AssertMsgFailedReturn(("Invalid enmType=%d!\n", pBp->enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE); } if (RT_FAILURE(rc)) pBp->fEnabled = false; return rc; }
RTDECL(int) RTDirOpenFiltered(PRTDIR *ppDir, const char *pszPath, RTDIRFILTER enmFilter, uint32_t fOpen) { /* * Validate input. */ AssertMsgReturn(VALID_PTR(ppDir), ("%p\n", ppDir), VERR_INVALID_POINTER); AssertMsgReturn(VALID_PTR(pszPath), ("%p\n", pszPath), VERR_INVALID_POINTER); AssertReturn(!(fOpen & ~RTDIROPEN_FLAGS_NO_SYMLINKS), VERR_INVALID_FLAGS); switch (enmFilter) { case RTDIRFILTER_UNIX: case RTDIRFILTER_UNIX_UPCASED: AssertMsgFailed(("%d is not implemented!\n", enmFilter)); return VERR_NOT_IMPLEMENTED; case RTDIRFILTER_NONE: case RTDIRFILTER_WINNT: break; default: AssertMsgFailedReturn(("%d\n", enmFilter), VERR_INVALID_PARAMETER); } /* * Find the last component, i.e. where the filter criteria starts and the dir name ends. */ const char *pszFilter; if (enmFilter == RTDIRFILTER_NONE) pszFilter = NULL; else { pszFilter = RTPathFilename(pszPath); if (!pszFilter) /* trailing slash => directory to read => no filter. */ enmFilter = RTDIRFILTER_NONE; } /* * Call worker common with RTDirOpen which will verify the path, allocate * and initialize the handle, and finally call the backend. */ int rc = rtDirOpenCommon(ppDir, pszPath, pszFilter, enmFilter); LogFlow(("RTDirOpenFiltered(%p:{%p}, %p:{%s}, %d): return %Rrc\n", ppDir, *ppDir, pszPath, pszPath, enmFilter, rc)); return rc; }
/** * EMT worker for DBGFR3BpDisable(). * * @returns VBox status code. * @param pVM The VM handle. * @param iBp The id of the breakpoint which should be disabled. * @thread EMT * @internal */ static DECLCALLBACK(int) dbgfR3BpDisable(PVM pVM, uint32_t iBp) { /* * Validate input. */ PDBGFBP pBp = dbgfR3BpGet(pVM, iBp); if (!pBp) return VERR_DBGF_BP_NOT_FOUND; /* * Already enabled? */ if (!pBp->fEnabled) return VINF_DBGF_BP_ALREADY_DISABLED; /* * Remove the breakpoint. */ pBp->fEnabled = false; int rc; switch (pBp->enmType) { case DBGFBPTYPE_REG: rc = dbgfR3BpRegDisarm(pVM, pBp); break; case DBGFBPTYPE_INT3: rc = dbgfR3BpInt3Disarm(pVM, pBp); break; case DBGFBPTYPE_REM: rc = REMR3BreakpointClear(pVM, pBp->GCPtr); break; default: AssertMsgFailedReturn(("Invalid enmType=%d!\n", pBp->enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE); } return rc; }
HRESULT USBController::getUSBStandard(USHORT *aUSBStandard) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); switch (m->bd->enmType) { case USBControllerType_OHCI: *aUSBStandard = 0x0101; break; case USBControllerType_EHCI: *aUSBStandard = 0x0200; break; case USBControllerType_XHCI: *aUSBStandard = 0x0200; break; default: AssertMsgFailedReturn(("Invalid controller type %d\n", m->bd->enmType), E_FAIL); } return S_OK; }
DECLHIDDEN(PVDSCRIPTASTCORE) vdScriptAstNodeAlloc(VDSCRIPTASTCLASS enmClass) { size_t cbAlloc = 0; switch (enmClass) { case VDSCRIPTASTCLASS_FUNCTION: cbAlloc = sizeof(VDSCRIPTASTFN); break; case VDSCRIPTASTCLASS_FUNCTIONARG: cbAlloc = sizeof(VDSCRIPTASTFNARG); break; case VDSCRIPTASTCLASS_DECLARATION: cbAlloc = sizeof(VDSCRIPTASTDECL); break; case VDSCRIPTASTCLASS_STATEMENT: cbAlloc = sizeof(VDSCRIPTASTSTMT); break; case VDSCRIPTASTCLASS_EXPRESSION: cbAlloc = sizeof(VDSCRIPTASTEXPR); break; case VDSCRIPTASTCLASS_IDENTIFIER: case VDSCRIPTASTCLASS_INVALID: default: AssertMsgFailedReturn(("Invalid AST node class given %d\n", enmClass), NULL); } PVDSCRIPTASTCORE pAstNode = (PVDSCRIPTASTCORE)RTMemAllocZ(cbAlloc); if (pAstNode) { pAstNode->enmClass = enmClass; RTListInit(&pAstNode->ListNode); } return pAstNode; }
static int emR3ExecuteInstructionWorker(PVM pVM, PVMCPU pVCpu, int rcRC) #endif { #ifdef LOG_ENABLED PCPUMCTX pCtx = pVCpu->em.s.pCtx; #endif int rc; NOREF(rcRC); /* * * The simple solution is to use the recompiler. * The better solution is to disassemble the current instruction and * try handle as many as possible without using REM. * */ #ifdef LOG_ENABLED /* * Disassemble the instruction if requested. */ if (pszPrefix) { DBGFR3InfoLog(pVM, "cpumguest", pszPrefix); DBGFR3DisasInstrCurrentLog(pVCpu, pszPrefix); } #endif /* LOG_ENABLED */ #if 0 /* Try our own instruction emulator before falling back to the recompiler. */ DISCPUSTATE Cpu; rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &Cpu, "GEN EMU"); if (RT_SUCCESS(rc)) { switch (Cpu.pCurInstr->uOpcode) { /* @todo we can do more now */ case OP_MOV: case OP_AND: case OP_OR: case OP_XOR: case OP_POP: case OP_INC: case OP_DEC: case OP_XCHG: STAM_PROFILE_START(&pVCpu->em.s.StatMiscEmu, a); rc = EMInterpretInstructionCpuUpdtPC(pVM, pVCpu, &Cpu, CPUMCTX2CORE(pCtx), 0); if (RT_SUCCESS(rc)) { #ifdef EM_NOTIFY_HWACCM if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC) HWACCMR3NotifyEmulated(pVCpu); #endif STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a); return rc; } if (rc != VERR_EM_INTERPRETER) AssertMsgFailedReturn(("rc=%Rrc\n", rc), rc); STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a); break; } } #endif /* 0 */ STAM_PROFILE_START(&pVCpu->em.s.StatREMEmu, a); Log(("EMINS: %04x:%RGv RSP=%RGv\n", pCtx->cs.Sel, (RTGCPTR)pCtx->rip, (RTGCPTR)pCtx->rsp)); #ifdef VBOX_WITH_REM EMRemLock(pVM); /* Flush the recompiler TLB if the VCPU has changed. */ if (pVM->em.s.idLastRemCpu != pVCpu->idCpu) CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_ALL); pVM->em.s.idLastRemCpu = pVCpu->idCpu; rc = REMR3EmulateInstruction(pVM, pVCpu); EMRemUnlock(pVM); #else rc = VBOXSTRICTRC_TODO(IEMExecOne(pVCpu)); NOREF(pVM); #endif STAM_PROFILE_STOP(&pVCpu->em.s.StatREMEmu, a); #ifdef EM_NOTIFY_HWACCM if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC) HWACCMR3NotifyEmulated(pVCpu); #endif return rc; }
/** * Display several info items. * * This is intended used by the fatal error dump only. * * @returns * @param pVM Pointer to the VM. * @param pszIncludePat Simple string pattern of info items to include. * @param pszExcludePat Simple string pattern of info items to exclude. * @param pszSepFmt Item separator format string. The item name will be * given as parameter. * @param pHlp The output helper functions. If NULL the logger * will be used. * * @threads EMT */ VMMR3DECL(int) DBGFR3InfoMulti(PVM pVM, const char *pszIncludePat, const char *pszExcludePat, const char *pszSepFmt, PCDBGFINFOHLP pHlp) { /* * Validate input. */ VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); AssertPtrReturn(pszIncludePat, VERR_INVALID_POINTER); AssertPtrReturn(pszExcludePat, VERR_INVALID_POINTER); if (pHlp) { AssertPtrReturn(pHlp->pfnPrintf, VERR_INVALID_POINTER); AssertPtrReturn(pHlp->pfnPrintfV, VERR_INVALID_POINTER); } else pHlp = &g_dbgfR3InfoLogHlp; size_t const cchIncludePat = strlen(pszIncludePat); size_t const cchExcludePat = strlen(pszExcludePat); const char *pszArgs = ""; /* * Enumerate the info handlers and call the ones matching. * Note! We won't leave the critical section here... */ int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect); AssertRC(rc); rc = VWRN_NOT_FOUND; for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; pInfo; pInfo = pInfo->pNext) { if ( RTStrSimplePatternMultiMatch(pszIncludePat, cchIncludePat, pInfo->szName, pInfo->cchName, NULL) && !RTStrSimplePatternMultiMatch(pszExcludePat, cchExcludePat, pInfo->szName, pInfo->cchName, NULL)) { pHlp->pfnPrintf(pHlp, pszSepFmt, pInfo->szName); rc = VINF_SUCCESS; switch (pInfo->enmType) { case DBGFINFOTYPE_DEV: if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)pInfo->u.Dev.pfnHandler, 3, pInfo->u.Dev.pDevIns, pHlp, pszArgs); else pInfo->u.Dev.pfnHandler(pInfo->u.Dev.pDevIns, pHlp, pszArgs); break; case DBGFINFOTYPE_DRV: if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)pInfo->u.Drv.pfnHandler, 3, pInfo->u.Drv.pDrvIns, pHlp, pszArgs); else pInfo->u.Drv.pfnHandler(pInfo->u.Drv.pDrvIns, pHlp, pszArgs); break; case DBGFINFOTYPE_INT: if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)pInfo->u.Int.pfnHandler, 3, pVM, pHlp, pszArgs); else pInfo->u.Int.pfnHandler(pVM, pHlp, pszArgs); break; case DBGFINFOTYPE_EXT: if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)pInfo->u.Ext.pfnHandler, 3, pInfo->u.Ext.pvUser, pHlp, pszArgs); else pInfo->u.Ext.pfnHandler(pInfo->u.Ext.pvUser, pHlp, pszArgs); break; default: AssertMsgFailedReturn(("Invalid info type enmType=%d\n", pInfo->enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE); } } } int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect); AssertRC(rc2); return rc; }
/** * Worker for DBGFR3Info and DBGFR3InfoEx. * * @returns VBox status code. * @param pVM Pointer to the VM. * @param idCpu Which CPU to run EMT bound handlers on. * VMCPUID_ANY or a valid CPU ID. * @param pszName What to dump. * @param pszArgs Arguments, optional. * @param pHlp Output helper, optional. */ static DECLCALLBACK(int) dbgfR3Info(PVM pVM, VMCPUID idCpu, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp) { /* * Validate input. */ AssertPtrReturn(pszName, VERR_INVALID_POINTER); if (pHlp) { if ( !pHlp->pfnPrintf || !pHlp->pfnPrintfV) { AssertMsgFailed(("A pHlp member is missing!\n")); return VERR_INVALID_PARAMETER; } } else pHlp = &g_dbgfR3InfoLogHlp; /* * Find the info handler. */ size_t cchName = strlen(pszName); int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect); AssertRC(rc); PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; for (; pInfo; pInfo = pInfo->pNext) if ( pInfo->cchName == cchName && !memcmp(pInfo->szName, pszName, cchName)) break; if (pInfo) { /* * Found it. * Make a copy of it on the stack so we can leave the crit sect. * Switch on the type and invoke the handler. */ DBGFINFO Info = *pInfo; rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect); AssertRC(rc); rc = VINF_SUCCESS; switch (Info.enmType) { case DBGFINFOTYPE_DEV: if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWait(pVM, idCpu, (PFNRT)Info.u.Dev.pfnHandler, 3, Info.u.Dev.pDevIns, pHlp, pszArgs); else Info.u.Dev.pfnHandler(Info.u.Dev.pDevIns, pHlp, pszArgs); break; case DBGFINFOTYPE_DRV: if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWait(pVM, idCpu, (PFNRT)Info.u.Drv.pfnHandler, 3, Info.u.Drv.pDrvIns, pHlp, pszArgs); else Info.u.Drv.pfnHandler(Info.u.Drv.pDrvIns, pHlp, pszArgs); break; case DBGFINFOTYPE_INT: if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWait(pVM, idCpu, (PFNRT)Info.u.Int.pfnHandler, 3, pVM, pHlp, pszArgs); else Info.u.Int.pfnHandler(pVM, pHlp, pszArgs); break; case DBGFINFOTYPE_EXT: if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWait(pVM, idCpu, (PFNRT)Info.u.Ext.pfnHandler, 3, Info.u.Ext.pvUser, pHlp, pszArgs); else Info.u.Ext.pfnHandler(Info.u.Ext.pvUser, pHlp, pszArgs); break; default: AssertMsgFailedReturn(("Invalid info type enmType=%d\n", Info.enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE); } } else { rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect); AssertRC(rc); rc = VERR_FILE_NOT_FOUND; } return rc; }
RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cchAbsPath) { int rc; /* * Validation. */ AssertPtr(pszAbsPath); AssertPtr(pszPath); if (RT_UNLIKELY(!*pszPath)) return VERR_INVALID_PARAMETER; /* * Make a clean working copy of the input. */ size_t cchPath = strlen(pszPath); if (cchPath > PATH_MAX) { LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cchAbsPath, VERR_FILENAME_TOO_LONG)); return VERR_FILENAME_TOO_LONG; } char szTmpPath[PATH_MAX + 1]; memcpy(szTmpPath, pszPath, cchPath + 1); size_t cchTmpPath = fsCleanPath(szTmpPath); /* * Handle "." specially (fsCleanPath does). */ if (szTmpPath[0] == '.' && !szTmpPath[1]) return RTPathGetCurrent(pszAbsPath, cchAbsPath); /* * Do we have a root slash? */ char *pszCur = szTmpPath; #ifdef HAVE_DRIVE if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/') pszCur += 3; # ifdef HAVE_UNC else if (pszCur[0] == '/' && pszCur[1] == '/') pszCur += 2; # endif #else /* !HAVE_DRIVE */ if (pszCur[0] == '/') pszCur += 1; #endif /* !HAVE_DRIVE */ else { /* * No, prepend the current directory to the relative path. */ char szCurDir[RTPATH_MAX]; rc = RTPathGetCurrent(szCurDir, sizeof(szCurDir)); AssertRCReturn(rc, rc); size_t cchCurDir = fsCleanPath(szCurDir); /* paranoia */ if (cchCurDir + cchTmpPath + 1 > PATH_MAX) { LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cchAbsPath, VERR_FILENAME_TOO_LONG)); return VERR_FILENAME_TOO_LONG; } memmove(szTmpPath + cchCurDir + 1, szTmpPath, cchTmpPath + 1); memcpy(szTmpPath, szCurDir, cchCurDir); szTmpPath[cchCurDir] = '/'; #ifdef HAVE_DRIVE if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/') pszCur += 3; # ifdef HAVE_UNC else if (pszCur[0] == '/' && pszCur[1] == '/') pszCur += 2; # endif #else if (pszCur[0] == '/') pszCur += 1; #endif else AssertMsgFailedReturn(("pszCur=%s\n", pszCur), VERR_INTERNAL_ERROR); } char *pszTop = pszCur; /* * Get rid of double dot path components by evaluating them. */ for (;;) { if ( pszCur[0] == '.' && pszCur[1] == '.' && (!pszCur[2] || pszCur[2] == '/')) { /* rewind to the previous component if any */ char *pszPrev = pszCur - 1; if (pszPrev > pszTop) while (*--pszPrev != '/') ; AssertMsg(*pszPrev == '/', ("szTmpPath={%s}, pszPrev=+%u\n", szTmpPath, pszPrev - szTmpPath)); memmove(pszPrev, pszCur + 2, strlen(pszCur + 2) + 1); pszCur = pszPrev; } else { /* advance to end of component. */ while (*pszCur && *pszCur != '/') pszCur++; } if (!*pszCur) break; /* skip the slash */ ++pszCur; } if (pszCur < pszTop) { /* * We overwrote the root slash with '\0', restore it. */ *pszCur++ = '/'; *pszCur = '\0'; } else if (pszCur > pszTop && pszCur[-1] == '/') { /* * Extra trailing slash in a non-root path, remove it. * (A bit questionable...) */ *--pszCur = '\0'; } /* * Copy the result to the user buffer. */ cchTmpPath = pszCur - szTmpPath; if (cchTmpPath < cchAbsPath) { memcpy(pszAbsPath, szTmpPath, cchTmpPath + 1); rc = VINF_SUCCESS; } else rc = VERR_BUFFER_OVERFLOW; LogFlow(("RTPathAbs(%p:{%s}, %p:{%s}, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, RT_SUCCESS(rc) ? pszAbsPath : "<failed>", cchAbsPath, rc)); return rc; }
RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags, PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser, const char *pszPassword, PRTPROCESS phProcess) { int rc; /* * Input validation */ AssertPtrReturn(pszExec, VERR_INVALID_POINTER); AssertReturn(*pszExec, VERR_INVALID_PARAMETER); AssertReturn(!(fFlags & ~RTPROC_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER); AssertReturn(!(fFlags & RTPROC_FLAGS_DETACHED) || !phProcess, VERR_INVALID_PARAMETER); AssertReturn(hEnv != NIL_RTENV, VERR_INVALID_PARAMETER); AssertPtrReturn(papszArgs, VERR_INVALID_PARAMETER); AssertPtrNullReturn(pszAsUser, VERR_INVALID_POINTER); AssertReturn(!pszAsUser || *pszAsUser, VERR_INVALID_PARAMETER); AssertReturn(!pszPassword || pszAsUser, VERR_INVALID_PARAMETER); AssertPtrNullReturn(pszPassword, VERR_INVALID_POINTER); #if defined(RT_OS_OS2) if (fFlags & RTPROC_FLAGS_DETACHED) return VERR_PROC_DETACH_NOT_SUPPORTED; #endif /* * Get the file descriptors for the handles we've been passed. */ PCRTHANDLE paHandles[3] = { phStdIn, phStdOut, phStdErr }; int aStdFds[3] = { -1, -1, -1 }; for (int i = 0; i < 3; i++) { if (paHandles[i]) { AssertPtrReturn(paHandles[i], VERR_INVALID_POINTER); switch (paHandles[i]->enmType) { case RTHANDLETYPE_FILE: aStdFds[i] = paHandles[i]->u.hFile != NIL_RTFILE ? (int)RTFileToNative(paHandles[i]->u.hFile) : -2 /* close it */; break; case RTHANDLETYPE_PIPE: aStdFds[i] = paHandles[i]->u.hPipe != NIL_RTPIPE ? (int)RTPipeToNative(paHandles[i]->u.hPipe) : -2 /* close it */; break; case RTHANDLETYPE_SOCKET: aStdFds[i] = paHandles[i]->u.hSocket != NIL_RTSOCKET ? (int)RTSocketToNative(paHandles[i]->u.hSocket) : -2 /* close it */; break; default: AssertMsgFailedReturn(("%d: %d\n", i, paHandles[i]->enmType), VERR_INVALID_PARAMETER); } /** @todo check the close-on-execness of these handles? */ } } for (int i = 0; i < 3; i++) if (aStdFds[i] == i) aStdFds[i] = -1; for (int i = 0; i < 3; i++) AssertMsgReturn(aStdFds[i] < 0 || aStdFds[i] > i, ("%i := %i not possible because we're lazy\n", i, aStdFds[i]), VERR_NOT_SUPPORTED); /* * Resolve the user id if specified. */ uid_t uid = ~(uid_t)0; gid_t gid = ~(gid_t)0; if (pszAsUser) { rc = rtCheckCredentials(pszAsUser, pszPassword, &gid, &uid); if (RT_FAILURE(rc)) return rc; } /* * Create the child environment if either RTPROC_FLAGS_PROFILE or * RTPROC_FLAGS_ENV_CHANGE_RECORD are in effect. */ RTENV hEnvToUse = hEnv; if ( (fFlags & (RTPROC_FLAGS_ENV_CHANGE_RECORD | RTPROC_FLAGS_PROFILE)) && ( (fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD) || hEnv == RTENV_DEFAULT) ) { if (fFlags & RTPROC_FLAGS_PROFILE) rc = rtProcPosixCreateProfileEnv(&hEnvToUse, pszAsUser); else rc = RTEnvClone(&hEnvToUse, RTENV_DEFAULT); if (RT_SUCCESS(rc)) { if ((fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD) && hEnv != RTENV_DEFAULT) rc = RTEnvApplyChanges(hEnvToUse, hEnv); if (RT_FAILURE(rc)) RTEnvDestroy(hEnvToUse); } if (RT_FAILURE(rc)) return rc; } /* * Check for execute access to the file. */ char szRealExec[RTPATH_MAX]; if (access(pszExec, X_OK)) { rc = errno; if ( !(fFlags & RTPROC_FLAGS_SEARCH_PATH) || rc != ENOENT || RTPathHavePath(pszExec) ) rc = RTErrConvertFromErrno(rc); else { /* search */ char *pszPath = RTEnvDupEx(hEnvToUse, "PATH"); rc = RTPathTraverseList(pszPath, ':', rtPathFindExec, (void *)pszExec, &szRealExec[0]); RTStrFree(pszPath); if (RT_SUCCESS(rc)) pszExec = szRealExec; else rc = rc == VERR_END_OF_STRING ? VERR_FILE_NOT_FOUND : rc; } if (RT_FAILURE(rc)) return rtProcPosixCreateReturn(rc, hEnvToUse, hEnv); } pid_t pid = -1; const char * const *papszEnv = RTEnvGetExecEnvP(hEnvToUse); AssertPtrReturn(papszEnv, rtProcPosixCreateReturn(VERR_INVALID_HANDLE, hEnvToUse, hEnv)); /* * Take care of detaching the process. * * HACK ALERT! Put the process into a new process group with pgid = pid * to make sure it differs from that of the parent process to ensure that * the IPRT waitpid call doesn't race anyone (read XPCOM) doing group wide * waits. setsid() includes the setpgid() functionality. * 2010-10-11 XPCOM no longer waits for anything, but it cannot hurt. */ #ifndef RT_OS_OS2 if (fFlags & RTPROC_FLAGS_DETACHED) { # ifdef RT_OS_SOLARIS int templateFd = -1; if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT)) { templateFd = rtSolarisContractPreFork(); if (templateFd == -1) return rtProcPosixCreateReturn(VERR_OPEN_FAILED, hEnvToUse, hEnv); } # endif /* RT_OS_SOLARIS */ pid = fork(); if (!pid) { # ifdef RT_OS_SOLARIS if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT)) rtSolarisContractPostForkChild(templateFd); # endif setsid(); /* see comment above */ pid = -1; /* Child falls through to the actual spawn code below. */ } else { # ifdef RT_OS_SOLARIS if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT)) rtSolarisContractPostForkParent(templateFd, pid); # endif if (pid > 0) { /* Must wait for the temporary process to avoid a zombie. */ int status = 0; pid_t pidChild = 0; /* Restart if we get interrupted. */ do { pidChild = waitpid(pid, &status, 0); } while ( pidChild == -1 && errno == EINTR); /* Assume that something wasn't found. No detailed info. */ if (status) return rtProcPosixCreateReturn(VERR_PROCESS_NOT_FOUND, hEnvToUse, hEnv); if (phProcess) *phProcess = 0; return rtProcPosixCreateReturn(VINF_SUCCESS, hEnvToUse, hEnv); } return rtProcPosixCreateReturn(RTErrConvertFromErrno(errno), hEnvToUse, hEnv); } } #endif /* * Spawn the child. * * Any spawn code MUST not execute any atexit functions if it is for a * detached process. It would lead to running the atexit functions which * make only sense for the parent. libORBit e.g. gets confused by multiple * execution. Remember, there was only a fork() so far, and until exec() * is successfully run there is nothing which would prevent doing anything * silly with the (duplicated) file descriptors. */ #ifdef HAVE_POSIX_SPAWN /** @todo OS/2: implement DETACHED (BACKGROUND stuff), see VbglR3Daemonize. */ if ( uid == ~(uid_t)0 && gid == ~(gid_t)0) { /* Spawn attributes. */ posix_spawnattr_t Attr; rc = posix_spawnattr_init(&Attr); if (!rc) { /* Indicate that process group and signal mask are to be changed, and that the child should use default signal actions. */ rc = posix_spawnattr_setflags(&Attr, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF); Assert(rc == 0); /* The child starts in its own process group. */ if (!rc) { rc = posix_spawnattr_setpgroup(&Attr, 0 /* pg == child pid */); Assert(rc == 0); } /* Unmask all signals. */ if (!rc) { sigset_t SigMask; sigemptyset(&SigMask); rc = posix_spawnattr_setsigmask(&Attr, &SigMask); Assert(rc == 0); } /* File changes. */ posix_spawn_file_actions_t FileActions; posix_spawn_file_actions_t *pFileActions = NULL; if ((aStdFds[0] != -1 || aStdFds[1] != -1 || aStdFds[2] != -1) && !rc) { rc = posix_spawn_file_actions_init(&FileActions); if (!rc) { pFileActions = &FileActions; for (int i = 0; i < 3; i++) { int fd = aStdFds[i]; if (fd == -2) rc = posix_spawn_file_actions_addclose(&FileActions, i); else if (fd >= 0 && fd != i) { rc = posix_spawn_file_actions_adddup2(&FileActions, fd, i); if (!rc) { for (int j = i + 1; j < 3; j++) if (aStdFds[j] == fd) { fd = -1; break; } if (fd >= 0) rc = posix_spawn_file_actions_addclose(&FileActions, fd); } } if (rc) break; } } } if (!rc) rc = posix_spawn(&pid, pszExec, pFileActions, &Attr, (char * const *)papszArgs, (char * const *)papszEnv); /* cleanup */ int rc2 = posix_spawnattr_destroy(&Attr); Assert(rc2 == 0); NOREF(rc2); if (pFileActions) { rc2 = posix_spawn_file_actions_destroy(pFileActions); Assert(rc2 == 0); } /* return on success.*/ if (!rc) { /* For a detached process this happens in the temp process, so * it's not worth doing anything as this process must exit. */ if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(0); if (phProcess) *phProcess = pid; return rtProcPosixCreateReturn(VINF_SUCCESS, hEnvToUse, hEnv); } } /* For a detached process this happens in the temp process, so * it's not worth doing anything as this process must exit. */ if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(124); } else #endif { #ifdef RT_OS_SOLARIS int templateFd = -1; if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT)) { templateFd = rtSolarisContractPreFork(); if (templateFd == -1) return rtProcPosixCreateReturn(VERR_OPEN_FAILED, hEnvToUse, hEnv); } #endif /* RT_OS_SOLARIS */ pid = fork(); if (!pid) { #ifdef RT_OS_SOLARIS if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT)) rtSolarisContractPostForkChild(templateFd); #endif /* RT_OS_SOLARIS */ if (!(fFlags & RTPROC_FLAGS_DETACHED)) setpgid(0, 0); /* see comment above */ /* * Change group and user if requested. */ #if 1 /** @todo This needs more work, see suplib/hardening. */ if (pszAsUser) { int ret = initgroups(pszAsUser, gid); if (ret) { if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(126); else exit(126); } } if (gid != ~(gid_t)0) { if (setgid(gid)) { if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(126); else exit(126); } } if (uid != ~(uid_t)0) { if (setuid(uid)) { if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(126); else exit(126); } } #endif /* * Some final profile environment tweaks, if running as user. */ if ( (fFlags & RTPROC_FLAGS_PROFILE) && pszAsUser && ( (fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD) || hEnv == RTENV_DEFAULT) ) { rc = rtProcPosixAdjustProfileEnvFromChild(hEnvToUse, fFlags, hEnv); papszEnv = RTEnvGetExecEnvP(hEnvToUse); if (RT_FAILURE(rc) || !papszEnv) { if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(126); else exit(126); } } /* * Unset the signal mask. */ sigset_t SigMask; sigemptyset(&SigMask); rc = sigprocmask(SIG_SETMASK, &SigMask, NULL); Assert(rc == 0); /* * Apply changes to the standard file descriptor and stuff. */ for (int i = 0; i < 3; i++) { int fd = aStdFds[i]; if (fd == -2) close(i); else if (fd >= 0) { int rc2 = dup2(fd, i); if (rc2 != i) { if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(125); else exit(125); } for (int j = i + 1; j < 3; j++) if (aStdFds[j] == fd) { fd = -1; break; } if (fd >= 0) close(fd); } } /* * Finally, execute the requested program. */ rc = execve(pszExec, (char * const *)papszArgs, (char * const *)papszEnv); if (errno == ENOEXEC) { /* This can happen when trying to start a shell script without the magic #!/bin/sh */ RTAssertMsg2Weak("Cannot execute this binary format!\n"); } else RTAssertMsg2Weak("execve returns %d errno=%d\n", rc, errno); RTAssertReleasePanic(); if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(127); else exit(127); } #ifdef RT_OS_SOLARIS if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT)) rtSolarisContractPostForkParent(templateFd, pid); #endif /* RT_OS_SOLARIS */ if (pid > 0) { /* For a detached process this happens in the temp process, so * it's not worth doing anything as this process must exit. */ if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(0); if (phProcess) *phProcess = pid; return rtProcPosixCreateReturn(VINF_SUCCESS, hEnvToUse, hEnv); } /* For a detached process this happens in the temp process, so * it's not worth doing anything as this process must exit. */ if (fFlags & RTPROC_FLAGS_DETACHED) _Exit(124); return rtProcPosixCreateReturn(RTErrConvertFromErrno(errno), hEnvToUse, hEnv); } return rtProcPosixCreateReturn(VERR_NOT_IMPLEMENTED, hEnvToUse, hEnv); }
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; }
RTDECL(int) RTGetOpt(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion) { /* * Reset the variables kept in state. */ pState->pDef = NULL; pState->uIndex = UINT32_MAX; /* * Make sure the union is completely cleared out, whatever happens below. */ pValueUnion->u64 = 0; pValueUnion->pDef = NULL; /* * The next option. */ bool fShort; int iThis; const char *pszArgThis; PCRTGETOPTDEF pOpt; if (pState->pszNextShort) { /* * We've got short options left over from the previous call. */ pOpt = rtGetOptSearchShort(*pState->pszNextShort, pState->paOptions, pState->cOptions, pState->fFlags); if (!pOpt) { pValueUnion->psz = pState->pszNextShort; return VERR_GETOPT_UNKNOWN_OPTION; } pState->pszNextShort++; pszArgThis = pState->pszNextShort - 2; iThis = pState->iNext; fShort = true; } else { /* * Pop off the next argument. Sorting options and dealing with the * dash-dash makes this a little extra complicated. */ for (;;) { if (pState->iNext >= pState->argc) return 0; if (pState->cNonOptions) { if (pState->cNonOptions == INT32_MAX) { pValueUnion->psz = pState->argv[pState->iNext++]; return VINF_GETOPT_NOT_OPTION; } if (pState->iNext + pState->cNonOptions >= pState->argc) { pState->cNonOptions = INT32_MAX; continue; } } iThis = pState->iNext++; pszArgThis = pState->argv[iThis + pState->cNonOptions]; /* * Do a long option search first and then a short option one. * This way we can make sure single dash long options doesn't * get mixed up with short ones. */ pOpt = rtGetOptSearchLong(pszArgThis, pState->paOptions, pState->cOptions, pState->fFlags); if ( !pOpt && pszArgThis[0] == '-' && pszArgThis[1] != '-' && pszArgThis[1] != '\0') { pOpt = rtGetOptSearchShort(pszArgThis[1], pState->paOptions, pState->cOptions, pState->fFlags); fShort = pOpt != NULL; } else fShort = false; /* Look for dash-dash. */ if (!pOpt && !strcmp(pszArgThis, "--")) { rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]); pState->cNonOptions = INT32_MAX; continue; } /* Options first hacks. */ if (pState->fFlags & RTGETOPTINIT_FLAGS_OPTS_FIRST) { if (pOpt) rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]); else if (*pszArgThis == '-') { pValueUnion->psz = pszArgThis; return VERR_GETOPT_UNKNOWN_OPTION; } else { /* not an option, add it to the non-options and try again. */ pState->iNext--; pState->cNonOptions++; /* Switch to returning non-options if we've reached the end. */ if (pState->iNext + pState->cNonOptions >= pState->argc) pState->cNonOptions = INT32_MAX; continue; } } /* done */ break; } } if (pOpt) { pValueUnion->pDef = pOpt; /* in case of no value or error. */ if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING) { /* * Find the argument value. * * A value is required with the argument. We're trying to be * understanding here and will permit any of the following: * -svalue, -s value, -s:value and -s=value * (Ditto for long options.) */ const char *pszValue; if (fShort) { if (pszArgThis[2] == '\0') { if (iThis + 1 >= pState->argc) return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; pszValue = pState->argv[iThis + pState->cNonOptions + 1]; rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]); pState->iNext++; } else /* same argument. */ pszValue = &pszArgThis[2 + (pszArgThis[2] == ':' || pszArgThis[2] == '=')]; if (pState->pszNextShort) { pState->pszNextShort = NULL; pState->iNext++; } } else { size_t cchLong = strlen(pOpt->pszLong); if (pOpt->fFlags & RTGETOPT_FLAG_INDEX) { if (pszArgThis[cchLong] == '\0') return VERR_GETOPT_INDEX_MISSING; uint32_t uIndex; char *pszRet = NULL; int rc = RTStrToUInt32Ex(&pszArgThis[cchLong], &pszRet, 10, &uIndex); if (rc == VWRN_TRAILING_CHARS) { if ( pszRet[0] != ':' && pszRet[0] != '=') return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; pState->uIndex = uIndex; pszValue = pszRet + 1; } else if (rc == VINF_SUCCESS) { if (iThis + 1 >= pState->argc) return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; pState->uIndex = uIndex; pszValue = pState->argv[iThis + pState->cNonOptions + 1]; rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]); pState->iNext++; } else AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */ } else { if (pszArgThis[cchLong] == '\0') { if (iThis + 1 >= pState->argc) return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; pszValue = pState->argv[iThis + pState->cNonOptions + 1]; rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]); pState->iNext++; } else /* same argument. */ pszValue = &pszArgThis[cchLong + 1]; } } /* * Set up the ValueUnion. */ int rc = rtGetOptProcessValue(pOpt->fFlags, pszValue, pValueUnion); if (RT_FAILURE(rc)) return rc; } else if (fShort) { /* * Deal with "compressed" short option lists, correcting the next * state variables for the start and end cases. */ if (pszArgThis[2]) { if (!pState->pszNextShort) { /* start */ pState->pszNextShort = &pszArgThis[2]; pState->iNext--; } } else if (pState->pszNextShort) { /* end */ pState->pszNextShort = NULL; pState->iNext++; } } else if (pOpt->fFlags & RTGETOPT_FLAG_INDEX) { size_t cchLong = strlen(pOpt->pszLong); if (pszArgThis[cchLong] == '\0') return VERR_GETOPT_INDEX_MISSING; uint32_t uIndex; if (RTStrToUInt32Full(&pszArgThis[cchLong], 10, &uIndex) == VINF_SUCCESS) pState->uIndex = uIndex; else AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */ } pState->pDef = pOpt; return pOpt->iShort; } /* * Not a known option argument. If it starts with a switch char (-) we'll * fail with unknown option, and if it doesn't we'll return it as a non-option. */ if (*pszArgThis == '-') { pValueUnion->psz = pszArgThis; return VERR_GETOPT_UNKNOWN_OPTION; } pValueUnion->psz = pszArgThis; return VINF_GETOPT_NOT_OPTION; }
/** * Internal worker routine. * * On x86 the typical stack frame layout is like this: * .. .. * 16 parameter 2 * 12 parameter 1 * 8 parameter 0 * 4 return address * 0 old ebp; current ebp points here * * @todo Add AMD64 support (needs teaming up with the module management for * unwind tables). */ static int dbgfR3StackWalk(PUVM pUVM, VMCPUID idCpu, RTDBGAS hAs, PDBGFSTACKFRAME pFrame) { /* * Stop if we got a read error in the previous run. */ if (pFrame->fFlags & DBGFSTACKFRAME_FLAGS_LAST) return VERR_NO_MORE_FILES; /* * Read the raw frame data. */ const DBGFADDRESS AddrOldPC = pFrame->AddrPC; const unsigned cbRetAddr = DBGFReturnTypeSize(pFrame->enmReturnType); unsigned cbStackItem; switch (AddrOldPC.fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) { case DBGFADDRESS_FLAGS_FAR16: cbStackItem = 2; break; case DBGFADDRESS_FLAGS_FAR32: cbStackItem = 4; break; case DBGFADDRESS_FLAGS_FAR64: cbStackItem = 8; break; case DBGFADDRESS_FLAGS_RING0: cbStackItem = sizeof(RTHCUINTPTR); break; default: switch (pFrame->enmReturnType) { case DBGFRETURNTYPE_FAR16: case DBGFRETURNTYPE_IRET16: case DBGFRETURNTYPE_IRET32_V86: case DBGFRETURNTYPE_NEAR16: cbStackItem = 2; break; case DBGFRETURNTYPE_FAR32: case DBGFRETURNTYPE_IRET32: case DBGFRETURNTYPE_IRET32_PRIV: case DBGFRETURNTYPE_NEAR32: cbStackItem = 4; break; case DBGFRETURNTYPE_FAR64: case DBGFRETURNTYPE_IRET64: case DBGFRETURNTYPE_NEAR64: cbStackItem = 8; break; default: AssertMsgFailed(("%d\n", pFrame->enmReturnType)); cbStackItem = 4; break; } } union { uint64_t *pu64; uint32_t *pu32; uint16_t *pu16; uint8_t *pb; void *pv; } u, uRet, uArgs, uBp; size_t cbRead = cbRetAddr + cbStackItem + sizeof(pFrame->Args); u.pv = alloca(cbRead); uBp = u; uRet.pb = u.pb + cbStackItem; uArgs.pb = u.pb + cbStackItem + cbRetAddr; Assert(DBGFADDRESS_IS_VALID(&pFrame->AddrFrame)); int rc = dbgfR3Read(pUVM, idCpu, u.pv, pFrame->fFlags & DBGFSTACKFRAME_FLAGS_ALL_VALID ? &pFrame->AddrReturnFrame : &pFrame->AddrFrame, cbRead, &cbRead); if ( RT_FAILURE(rc) || cbRead < cbRetAddr + cbStackItem) pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_LAST; /* * The first step is taken in a different way than the others. */ if (!(pFrame->fFlags & DBGFSTACKFRAME_FLAGS_ALL_VALID)) { pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_ALL_VALID; pFrame->iFrame = 0; /* Current PC - set by caller, just find symbol & line. */ if (DBGFADDRESS_IS_VALID(&pFrame->AddrPC)) { pFrame->pSymPC = DBGFR3AsSymbolByAddrA(pUVM, hAs, &pFrame->AddrPC, RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, NULL /*poffDisp*/, NULL /*phMod*/); pFrame->pLinePC = DBGFR3AsLineByAddrA(pUVM, hAs, &pFrame->AddrPC, NULL /*poffDisp*/, NULL /*phMod*/); } } else /* 2nd and subsequent steps */ { /* frame, pc and stack is taken from the existing frames return members. */ pFrame->AddrFrame = pFrame->AddrReturnFrame; pFrame->AddrPC = pFrame->AddrReturnPC; pFrame->pSymPC = pFrame->pSymReturnPC; pFrame->pLinePC = pFrame->pLineReturnPC; /* increment the frame number. */ pFrame->iFrame++; } /* * Return Frame address. */ pFrame->AddrReturnFrame = pFrame->AddrFrame; switch (cbStackItem) { case 2: pFrame->AddrReturnFrame.off = *uBp.pu16; break; case 4: pFrame->AddrReturnFrame.off = *uBp.pu32; break; case 8: pFrame->AddrReturnFrame.off = *uBp.pu64; break; default: AssertMsgFailedReturn(("cbStackItem=%d\n", cbStackItem), VERR_DBGF_STACK_IPE_1); } pFrame->AddrReturnFrame.FlatPtr += pFrame->AddrReturnFrame.off - pFrame->AddrFrame.off; /* * Return PC and Stack Addresses. */ /** @todo AddrReturnStack is not correct for stdcall and pascal. (requires scope info) */ pFrame->AddrReturnStack = pFrame->AddrFrame; pFrame->AddrReturnStack.off += cbStackItem + cbRetAddr; pFrame->AddrReturnStack.FlatPtr += cbStackItem + cbRetAddr; pFrame->AddrReturnPC = pFrame->AddrPC; switch (pFrame->enmReturnType) { case DBGFRETURNTYPE_NEAR16: if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC)) { pFrame->AddrReturnPC.FlatPtr += *uRet.pu16 - pFrame->AddrReturnPC.off; pFrame->AddrReturnPC.off = *uRet.pu16; } else DBGFR3AddrFromFlat(pUVM, &pFrame->AddrReturnPC, *uRet.pu16); break; case DBGFRETURNTYPE_NEAR32: if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC)) { pFrame->AddrReturnPC.FlatPtr += *uRet.pu32 - pFrame->AddrReturnPC.off; pFrame->AddrReturnPC.off = *uRet.pu32; } else DBGFR3AddrFromFlat(pUVM, &pFrame->AddrReturnPC, *uRet.pu32); break; case DBGFRETURNTYPE_NEAR64: if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC)) { pFrame->AddrReturnPC.FlatPtr += *uRet.pu64 - pFrame->AddrReturnPC.off; pFrame->AddrReturnPC.off = *uRet.pu64; } else DBGFR3AddrFromFlat(pUVM, &pFrame->AddrReturnPC, *uRet.pu64); break; case DBGFRETURNTYPE_FAR16: DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[1], uRet.pu16[0]); break; case DBGFRETURNTYPE_FAR32: DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]); break; case DBGFRETURNTYPE_FAR64: DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[4], uRet.pu64[0]); break; case DBGFRETURNTYPE_IRET16: DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[1], uRet.pu16[0]); break; case DBGFRETURNTYPE_IRET32: DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]); break; case DBGFRETURNTYPE_IRET32_PRIV: DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]); break; case DBGFRETURNTYPE_IRET32_V86: DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]); break; case DBGFRETURNTYPE_IRET64: DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[4], uRet.pu64[0]); break; default: AssertMsgFailed(("enmReturnType=%d\n", pFrame->enmReturnType)); return VERR_INVALID_PARAMETER; } pFrame->pSymReturnPC = DBGFR3AsSymbolByAddrA(pUVM, hAs, &pFrame->AddrReturnPC, RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, NULL /*poffDisp*/, NULL /*phMod*/); pFrame->pLineReturnPC = DBGFR3AsLineByAddrA(pUVM, hAs, &pFrame->AddrReturnPC, NULL /*poffDisp*/, NULL /*phMod*/); /* * Frame bitness flag. */ switch (cbStackItem) { case 2: pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_16BIT; break; case 4: pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_32BIT; break; case 8: pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_64BIT; break; default: AssertMsgFailedReturn(("cbStackItem=%d\n", cbStackItem), VERR_DBGF_STACK_IPE_2); } /* * The arguments. */ memcpy(&pFrame->Args, uArgs.pv, sizeof(pFrame->Args)); return VINF_SUCCESS; }
int vboxClipboardUtf16WinToLin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest, size_t cwDest) { size_t cwDestPos; LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u, pu16Dest=%p, cwDest=%u\n", cwSrc, pwszSrc, cwSrc, pu16Dest, cwDest)); /* A buffer of size 0 may not be an error, but it is not a good idea either. */ Assert(cwDest > 0); if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest)) { LogRel(("vboxClipboardUtf16WinToLin: received an invalid ptr, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest)); AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER); } /* We only take little endian Utf16 */ if (pwszSrc[0] == UTF16BEMARKER) { LogRel(("vboxClipboardUtf16WinToLin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n")); AssertMsgFailedReturn(("received a big endian string\n"), VERR_INVALID_PARAMETER); } if (cwDest == 0) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } if (cwSrc == 0) { pu16Dest[0] = 0; LogFlowFunc(("received empty string. Returning VINF_SUCCESS\n")); return VINF_SUCCESS; } /* Prepend the Utf16 byte order marker if it is missing. */ if (pwszSrc[0] == UTF16LEMARKER) { cwDestPos = 0; } else { pu16Dest[0] = UTF16LEMARKER; cwDestPos = 1; } for (size_t i = 0; i < cwSrc; ++i, ++cwDestPos) { if (pwszSrc[i] == 0) { break; } if (cwDestPos == cwDest) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } if ( (i + 1 < cwSrc) && (pwszSrc[i] == CARRIAGERETURN) && (pwszSrc[i + 1] == LINEFEED)) { ++i; } pu16Dest[cwDestPos] = pwszSrc[i]; } /* Terminating zero */ if (cwDestPos == cwDest) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } pu16Dest[cwDestPos] = 0; LogFlowFunc(("set string %ls. Returning\n", pu16Dest + 1)); return VINF_SUCCESS; }
QString UINativeHotKey::toString(int iKeyCode) { QString strKeyName; #ifdef Q_WS_WIN /* MapVirtualKey doesn't distinguish between right and left vkeys, * even under XP, despite that it stated in MSDN. Do it by hands. * Besides that it can't recognize such virtual keys as * VK_DIVIDE & VK_PAUSE, this is also known bug. */ int iScan; switch (iKeyCode) { /* Processing special keys... */ case VK_PAUSE: iScan = 0x45 << 16; break; case VK_RSHIFT: iScan = 0x36 << 16; break; case VK_RCONTROL: iScan = (0x1D << 16) | (1 << 24); break; case VK_RMENU: iScan = (0x38 << 16) | (1 << 24); break; /* Processing extended keys... */ case VK_APPS: case VK_LWIN: case VK_RWIN: case VK_NUMLOCK: iScan = (::MapVirtualKey(iKeyCode, 0) | 256) << 16; break; default: iScan = ::MapVirtualKey(iKeyCode, 0) << 16; } TCHAR *pKeyName = new TCHAR[256]; if (::GetKeyNameText(iScan, pKeyName, 256)) { strKeyName = QString::fromUtf16(pKeyName); } else { AssertMsgFailed(("That key have no name!\n")); strKeyName = UIHostComboEditor::tr("<key_%1>").arg(iKeyCode); } delete[] pKeyName; #endif /* Q_WS_WIN */ #ifdef Q_WS_X11 if (char *pNativeKeyName = ::XKeysymToString((KeySym)iKeyCode)) { strKeyName = m_keyNames[pNativeKeyName].isEmpty() ? QString(pNativeKeyName) : m_keyNames[pNativeKeyName]; } else { AssertMsgFailed(("That key have no name!\n")); strKeyName = UIHostComboEditor::tr("<key_%1>").arg(iKeyCode); } #endif /* Q_WS_X11 */ #ifdef Q_WS_MAC UInt32 modMask = DarwinKeyCodeToDarwinModifierMask(iKeyCode); switch (modMask) { case shiftKey: case optionKey: case controlKey: case cmdKey: strKeyName = UIHostComboEditor::tr("Left "); break; case rightShiftKey: case rightOptionKey: case rightControlKey: case kEventKeyModifierRightCmdKeyMask: strKeyName = UIHostComboEditor::tr("Right "); break; default: AssertMsgFailedReturn(("modMask=%#x\n", modMask), QString()); } switch (modMask) { case shiftKey: case rightShiftKey: strKeyName += QChar(kShiftUnicode); break; case optionKey: case rightOptionKey: strKeyName += QChar(kOptionUnicode); break; case controlKey: case rightControlKey: strKeyName += QChar(kControlUnicode); break; case cmdKey: case kEventKeyModifierRightCmdKeyMask: strKeyName += QChar(kCommandUnicode); break; } #endif /* Q_WS_MAC */ return strKeyName; }
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; }
/** * Converts a kLdr error code to an IPRT one. */ static int rtkldrConvertError(int krc) { if (!krc) return VINF_SUCCESS; switch (krc) { case KERR_INVALID_PARAMETER: return VERR_INVALID_PARAMETER; case KERR_INVALID_HANDLE: return VERR_INVALID_HANDLE; case KERR_NO_MEMORY: return VERR_NO_MEMORY; case KLDR_ERR_UNKNOWN_FORMAT: case KLDR_ERR_MZ_NOT_SUPPORTED: return VERR_MZ_EXE_NOT_SUPPORTED; case KLDR_ERR_NE_NOT_SUPPORTED: return VERR_NE_EXE_NOT_SUPPORTED; case KLDR_ERR_LX_NOT_SUPPORTED: return VERR_LX_EXE_NOT_SUPPORTED; case KLDR_ERR_LE_NOT_SUPPORTED: return VERR_LE_EXE_NOT_SUPPORTED; case KLDR_ERR_PE_NOT_SUPPORTED: return VERR_PE_EXE_NOT_SUPPORTED; case KLDR_ERR_ELF_NOT_SUPPORTED: return VERR_ELF_EXE_NOT_SUPPORTED; case KLDR_ERR_MACHO_NOT_SUPPORTED: return VERR_INVALID_EXE_SIGNATURE; case KLDR_ERR_AOUT_NOT_SUPPORTED: return VERR_AOUT_EXE_NOT_SUPPORTED; case KLDR_ERR_MODULE_NOT_FOUND: return VERR_MODULE_NOT_FOUND; case KLDR_ERR_PREREQUISITE_MODULE_NOT_FOUND: return VERR_MODULE_NOT_FOUND; case KLDR_ERR_MAIN_STACK_ALLOC_FAILED: return VERR_NO_MEMORY; case KERR_BUFFER_OVERFLOW: return VERR_BUFFER_OVERFLOW; case KLDR_ERR_SYMBOL_NOT_FOUND: return VERR_SYMBOL_NOT_FOUND; case KLDR_ERR_FORWARDER_SYMBOL: return VERR_BAD_EXE_FORMAT; case KLDR_ERR_BAD_FIXUP: AssertMsgFailedReturn(("KLDR_ERR_BAD_FIXUP\n"), VERR_BAD_EXE_FORMAT); case KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS: return VERR_BAD_EXE_FORMAT; case KLDR_ERR_NO_DEBUG_INFO: return VERR_FILE_NOT_FOUND; case KLDR_ERR_ALREADY_MAPPED: return VERR_WRONG_ORDER; case KLDR_ERR_NOT_MAPPED: return VERR_WRONG_ORDER; case KLDR_ERR_ADDRESS_OVERFLOW: return VERR_NUMBER_TOO_BIG; case KLDR_ERR_TODO: return VERR_NOT_IMPLEMENTED; case KLDR_ERR_NOT_LOADED_DYNAMICALLY: case KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE: case KLDR_ERR_TOO_LONG_FORWARDER_CHAIN: case KLDR_ERR_MODULE_TERMINATING: case KLDR_ERR_PREREQUISITE_MODULE_TERMINATING: case KLDR_ERR_MODULE_INIT_FAILED: case KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED: case KLDR_ERR_MODULE_INIT_FAILED_ALREADY: case KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED_ALREADY: case KLDR_ERR_PREREQUISITE_RECURSED_TOO_DEEPLY: case KLDR_ERR_THREAD_ATTACH_FAILED: case KRDR_ERR_TOO_MANY_MAPPINGS: case KLDR_ERR_NOT_DLL: case KLDR_ERR_NOT_EXE: AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE); case KLDR_ERR_PE_UNSUPPORTED_MACHINE: case KLDR_ERR_PE_BAD_FILE_HEADER: case KLDR_ERR_PE_BAD_OPTIONAL_HEADER: case KLDR_ERR_PE_BAD_SECTION_HEADER: case KLDR_ERR_PE_BAD_FORWARDER: case KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND: case KLDR_ERR_PE_BAD_FIXUP: case KLDR_ERR_PE_BAD_IMPORT: AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE); case KLDR_ERR_LX_BAD_HEADER: case KLDR_ERR_LX_BAD_LOADER_SECTION: case KLDR_ERR_LX_BAD_FIXUP_SECTION: case KLDR_ERR_LX_BAD_OBJECT_TABLE: case KLDR_ERR_LX_BAD_PAGE_MAP: case KLDR_ERR_LX_BAD_ITERDATA: case KLDR_ERR_LX_BAD_ITERDATA2: case KLDR_ERR_LX_BAD_BUNDLE: case KLDR_ERR_LX_NO_SONAME: case KLDR_ERR_LX_BAD_SONAME: case KLDR_ERR_LX_BAD_FORWARDER: case KLDR_ERR_LX_NRICHAIN_NOT_SUPPORTED: AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE); case KLDR_ERR_MACHO_OTHER_ENDIAN_NOT_SUPPORTED: case KLDR_ERR_MACHO_BAD_HEADER: case KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE: case KLDR_ERR_MACHO_UNSUPPORTED_MACHINE: case KLDR_ERR_MACHO_BAD_LOAD_COMMAND: case KLDR_ERR_MACHO_UNKNOWN_LOAD_COMMAND: case KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND: case KLDR_ERR_MACHO_BAD_SECTION: case KLDR_ERR_MACHO_UNSUPPORTED_SECTION: #ifdef KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION case KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION: case KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION: #endif case KLDR_ERR_MACHO_UNKNOWN_SECTION: case KLDR_ERR_MACHO_BAD_SECTION_ORDER: case KLDR_ERR_MACHO_BIT_MIX: case KLDR_ERR_MACHO_BAD_OBJECT_FILE: case KLDR_ERR_MACHO_BAD_SYMBOL: case KLDR_ERR_MACHO_UNSUPPORTED_FIXUP_TYPE: AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE); default: if (RT_FAILURE(krc)) return krc; AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_NO_TRANSLATION); } }
extern "C" int RTWinSocketPair(int domain, int type, int protocol, SOCKET socket_vector[2]) { LogFlowFunc(("ENTER: domain:%d, type:%d, protocol:%d, socket_vector:%p\n", domain, type, protocol, socket_vector)); switch (domain) { case AF_INET: break; case AF_INET6: /* I dobt we really need it. */ default: AssertMsgFailedReturn(("Unsuported domain:%d\n", domain), VERR_INVALID_PARAMETER); } switch(type) { case SOCK_STREAM: case SOCK_DGRAM: break; default: AssertMsgFailedReturn(("Unsuported type:%d\n", type), VERR_INVALID_PARAMETER); } AssertPtrReturn(socket_vector, VERR_INVALID_PARAMETER); if (!socket_vector) return VERR_INVALID_PARAMETER; socket_vector[0] = socket_vector[1] = INVALID_SOCKET; SOCKET listener = INVALID_SOCKET; union { struct sockaddr_in in_addr; struct sockaddr addr; } sa[2]; int cb = sizeof(sa); memset(&sa, 0, cb); sa[0].in_addr.sin_family = domain; sa[0].in_addr.sin_addr.s_addr = RT_H2N_U32(INADDR_LOOPBACK); sa[0].in_addr.sin_port = 0; cb = sizeof(sa[0]); if (type == SOCK_STREAM) { listener = WSASocket(domain, type, protocol, 0, NULL, 0); if (listener == INVALID_SOCKET) { return VERR_INTERNAL_ERROR; } int reuse = 1; cb = sizeof(int); int rc = setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, cb); if (rc) { goto close_socket; } cb = sizeof(sa[0]); rc = bind(listener, &sa[0].addr, cb); if(rc) { goto close_socket; } memset(&sa[0], 0, cb); rc = getsockname(listener, &sa[0].addr, &cb); if (rc) { goto close_socket; } rc = listen(listener, 1); if (rc) { goto close_socket; } socket_vector[0] = WSASocket(domain, type, protocol, 0, NULL, 0); if (socket_vector[0] == INVALID_SOCKET) { goto close_socket; } rc = connect(socket_vector[0], &sa[0].addr, cb); if (rc) goto close_socket; socket_vector[1] = accept(listener, NULL, NULL); if (socket_vector[1] == INVALID_SOCKET) { goto close_socket; } closesocket(listener); } else { socket_vector[0] = WSASocket(domain, type, protocol, 0, NULL, 0); cb = sizeof(sa[0]); int rc = bind(socket_vector[0], &sa[0].addr, cb); Assert(rc != SOCKET_ERROR); if (rc == SOCKET_ERROR) { goto close_socket; } sa[1].in_addr.sin_family = domain; sa[1].in_addr.sin_addr.s_addr = RT_H2N_U32(INADDR_LOOPBACK); sa[1].in_addr.sin_port = 0; socket_vector[1] = WSASocket(domain, type, protocol, 0, NULL, 0); rc = bind(socket_vector[1], &sa[1].addr, cb); Assert(rc != SOCKET_ERROR); if (rc == SOCKET_ERROR) { goto close_socket; } { u_long mode = 0; rc = ioctlsocket(socket_vector[0], FIONBIO, &mode); AssertMsgReturn(rc != SOCKET_ERROR, ("ioctl error: %d\n", WSAGetLastError()), VERR_INTERNAL_ERROR); rc = ioctlsocket(socket_vector[1], FIONBIO, &mode); AssertMsgReturn(rc != SOCKET_ERROR, ("ioctl error: %d\n", WSAGetLastError()), VERR_INTERNAL_ERROR); } memset(&sa, 0, 2 * cb); rc = getsockname(socket_vector[0], &sa[0].addr, &cb); Assert(rc != SOCKET_ERROR); if (rc == SOCKET_ERROR) { goto close_socket; } rc = getsockname(socket_vector[1], &sa[1].addr, &cb); Assert(rc != SOCKET_ERROR); if (rc == SOCKET_ERROR) { goto close_socket; } rc = connect(socket_vector[0], &sa[1].addr, cb); Assert(rc != SOCKET_ERROR); if (rc == SOCKET_ERROR) { goto close_socket; } rc = connect(socket_vector[1], &sa[0].addr, cb); Assert(rc != SOCKET_ERROR); if (rc == SOCKET_ERROR) { goto close_socket; } } LogFlowFuncLeaveRC(VINF_SUCCESS); return VINF_SUCCESS; close_socket: if (listener != INVALID_SOCKET) closesocket(listener); if (socket_vector[0] != INVALID_SOCKET) closesocket(socket_vector[0]); if (socket_vector[1] != INVALID_SOCKET) closesocket(socket_vector[1]); LogFlowFuncLeaveRC(VERR_INTERNAL_ERROR); return VERR_INTERNAL_ERROR; }
/** @copydoc RTDBGMODVTDBG::pfnSegmentAdd */ static DECLCALLBACK(int) rtDbgModContainer_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName, uint32_t fFlags, PRTDBGSEGIDX piSeg) { PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv; /* * Input validation (the bits the caller cannot do). */ /* Overlapping segments are not yet supported. Will use flags to deal with it if it becomes necessary. */ RTUINTPTR uRvaLast = uRva + RT_MAX(cb, 1) - 1; RTUINTPTR uRvaLastMax = uRvaLast; RTDBGSEGIDX iSeg = pThis->cSegs; while (iSeg-- > 0) { RTUINTPTR uCurRva = pThis->paSegs[iSeg].off; RTUINTPTR uCurRvaLast = uCurRva + RT_MAX(pThis->paSegs[iSeg].cb, 1) - 1; if ( uRva <= uCurRvaLast && uRvaLast >= uCurRva && ( /* HACK ALERT! Allow empty segments to share space (bios/watcom, elf). */ (cb != 0 && pThis->paSegs[iSeg].cb != 0) || ( cb == 0 && uRva != uCurRva && uRva != uCurRvaLast) || ( pThis->paSegs[iSeg].cb == 0 && uCurRva != uRva && uCurRva != uRvaLast) ) ) AssertMsgFailedReturn(("uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\";\n" "uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\" iSeg=%#x\n", uRva, uRvaLast, cb, pszName, uCurRva, uCurRvaLast, pThis->paSegs[iSeg].cb, pThis->paSegs[iSeg].pszName, iSeg), VERR_DBG_SEGMENT_INDEX_CONFLICT); if (uRvaLastMax < uCurRvaLast) uRvaLastMax = uCurRvaLast; } /* Strict ordered segment addition at the moment. */ iSeg = pThis->cSegs; AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg == iSeg, ("iSeg=%#x *piSeg=%#x\n", iSeg, *piSeg), VERR_DBG_INVALID_SEGMENT_INDEX); /* * Add an entry to the segment table, extending it if necessary. */ if (!(iSeg % 8)) { void *pvSegs = RTMemRealloc(pThis->paSegs, sizeof(RTDBGMODCTNSEGMENT) * (iSeg + 8)); if (!pvSegs) return VERR_NO_MEMORY; pThis->paSegs = (PRTDBGMODCTNSEGMENT)pvSegs; } pThis->paSegs[iSeg].SymAddrTree = NULL; pThis->paSegs[iSeg].LineAddrTree = NULL; pThis->paSegs[iSeg].off = uRva; pThis->paSegs[iSeg].cb = cb; pThis->paSegs[iSeg].fFlags = fFlags; pThis->paSegs[iSeg].pszName = RTStrCacheEnterN(g_hDbgModStrCache, pszName, cchName); if (pThis->paSegs[iSeg].pszName) { if (piSeg) *piSeg = iSeg; pThis->cSegs++; pThis->cb = uRvaLastMax + 1; if (!pThis->cb) pThis->cb = RTUINTPTR_MAX; return VINF_SUCCESS; } return VERR_NO_MEMORY; }