int GuestFile::onFileNotify(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData) { AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER); AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER); LogFlowThisFuncEnter(); if (pSvcCbData->mParms < 3) return VERR_INVALID_PARAMETER; int vrc = VINF_SUCCESS; int idx = 1; /* Current parameter index. */ CALLBACKDATA_FILE_NOTIFY dataCb; /* pSvcCb->mpaParms[0] always contains the context ID. */ pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.uType); pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.rc); FileStatus_T fileStatus = FileStatus_Undefined; int guestRc = (int)dataCb.rc; /* uint32_t vs. int. */ LogFlowFunc(("uType=%RU32, guestRc=%Rrc\n", dataCb.uType, guestRc)); if (RT_FAILURE(guestRc)) { int rc2 = setFileStatus(FileStatus_Error, guestRc); AssertRC(rc2); rc2 = signalWaitEventInternal(pCbCtx, guestRc, NULL /* pPayload */); AssertRC(rc2); return VINF_SUCCESS; /* Report to the guest. */ } switch (dataCb.uType) { case GUEST_FILE_NOTIFYTYPE_ERROR: { int rc2 = setFileStatus(FileStatus_Error, guestRc); AssertRC(rc2); break; } case GUEST_FILE_NOTIFYTYPE_OPEN: { if (pSvcCbData->mParms == 4) { pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.open.uHandle); { AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); AssertMsg(mData.mID == VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID), ("File ID %RU32 does not match context ID %RU32\n", mData.mID, VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID))); /* Set the initial offset. On the guest the whole opening operation * would fail if an initial seek isn't possible. */ mData.mOffCurrent = mData.mOpenInfo.mInitialOffset; } /* Set the process status. */ int rc2 = setFileStatus(FileStatus_Open, guestRc); AssertRC(rc2); } else vrc = VERR_NOT_SUPPORTED; break; } case GUEST_FILE_NOTIFYTYPE_CLOSE: { int rc2 = setFileStatus(FileStatus_Closed, guestRc); AssertRC(rc2); break; } case GUEST_FILE_NOTIFYTYPE_READ: { if (pSvcCbData->mParms == 4) { pSvcCbData->mpaParms[idx++].getPointer(&dataCb.u.read.pvData, &dataCb.u.read.cbData); uint32_t cbRead = dataCb.u.read.cbData; AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); mData.mOffCurrent += cbRead; alock.release(); com::SafeArray<BYTE> data((size_t)cbRead); data.initFrom((BYTE*)dataCb.u.read.pvData, cbRead); fireGuestFileReadEvent(mEventSource, mSession, this, mData.mOffCurrent, cbRead, ComSafeArrayAsInParam(data)); } else vrc = VERR_NOT_SUPPORTED; break; } case GUEST_FILE_NOTIFYTYPE_WRITE: { if (pSvcCbData->mParms == 4) { pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.write.cbWritten); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); mData.mOffCurrent += dataCb.u.write.cbWritten; uint64_t uOffCurrent = mData.mOffCurrent; alock.release(); fireGuestFileWriteEvent(mEventSource, mSession, this, uOffCurrent, dataCb.u.write.cbWritten); } else vrc = VERR_NOT_SUPPORTED; break; } case GUEST_FILE_NOTIFYTYPE_SEEK: { if (pSvcCbData->mParms == 4) { pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.seek.uOffActual); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); mData.mOffCurrent = dataCb.u.seek.uOffActual; alock.release(); fireGuestFileOffsetChangedEvent(mEventSource, mSession, this, dataCb.u.seek.uOffActual, 0 /* Processed */); } else vrc = VERR_NOT_SUPPORTED; break; } case GUEST_FILE_NOTIFYTYPE_TELL: { if (pSvcCbData->mParms == 4) { pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.tell.uOffActual); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); mData.mOffCurrent = dataCb.u.tell.uOffActual; alock.release(); fireGuestFileOffsetChangedEvent(mEventSource, mSession, this, dataCb.u.tell.uOffActual, 0 /* Processed */); } else vrc = VERR_NOT_SUPPORTED; break; } default: vrc = VERR_NOT_SUPPORTED; break; } if (RT_SUCCESS(vrc)) { GuestWaitEventPayload payload(dataCb.uType, &dataCb, sizeof(dataCb)); int rc2 = signalWaitEventInternal(pCbCtx, guestRc, &payload); AssertRC(rc2); } LogFlowThisFunc(("uType=%RU32, guestRc=%Rrc\n", dataCb.uType, dataCb.rc)); LogFlowFuncLeaveRC(vrc); return vrc; }
int HostDnsServiceLinux::monitorWorker() { AutoNotify a; int rc = socketpair(AF_LOCAL, SOCK_DGRAM, 0, g_DnsMonitorStop); AssertMsgReturn(rc == 0, ("socketpair: failed (%d: %s)\n", errno, strerror(errno)), E_FAIL); FileDescriptor stopper0(g_DnsMonitorStop[0]); FileDescriptor stopper1(g_DnsMonitorStop[1]); pollfd polls[2]; RT_ZERO(polls); polls[0].fd = a.fileDescriptor(); polls[0].events = POLLIN; polls[1].fd = g_DnsMonitorStop[1]; polls[1].events = POLLIN; monitorThreadInitializationDone(); int wd[2]; wd[0] = wd[1] = -1; /* inotify inialization */ wd[0] = inotify_add_watch(a.fileDescriptor(), g_ResolvConfFullPath.c_str(), IN_CLOSE_WRITE|IN_DELETE_SELF); /** * If /etc/resolv.conf exists we want to listen for movements: because * # mv /etc/resolv.conf ... * won't arm IN_DELETE_SELF on wd[0] instead it will fire IN_MOVE_FROM on wd[1]. * * Because on some distributions /etc/resolv.conf is link, wd[0] can't detect deletion, * it's recognizible on directory level (wd[1]) only. */ wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(), wd[0] == -1 ? IN_MOVED_TO|IN_CREATE : IN_MOVED_FROM|IN_DELETE); struct InotifyEventWithName combo; while(true) { rc = poll(polls, 2, -1); if (rc == -1) continue; AssertMsgReturn( ((polls[0].revents & (POLLERR|POLLNVAL)) == 0) && ((polls[1].revents & (POLLERR|POLLNVAL)) == 0), ("Debug Me"), VERR_INTERNAL_ERROR); if (polls[1].revents & POLLIN) return VINF_SUCCESS; /* time to shutdown */ if (polls[0].revents & POLLIN) { RT_ZERO(combo); ssize_t r = read(polls[0].fd, static_cast<void *>(&combo), sizeof(combo)); NOREF(r); if (combo.e.wd == wd[0]) { if (combo.e.mask & IN_CLOSE_WRITE) { readResolvConf(); } else if (combo.e.mask & IN_DELETE_SELF) { inotify_rm_watch(a.fileDescriptor(), wd[0]); /* removes file watcher */ inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(), IN_MOVED_TO|IN_CREATE); /* alter folder watcher */ } else if (combo.e.mask & IN_IGNORED) { wd[0] = -1; /* we want receive any events on this watch */ } else { /** * It shouldn't happen, in release we will just ignore in debug * we will have to chance to look at into inotify_event */ AssertMsgFailed(("Debug Me!!!")); } } else if (combo.e.wd == wd[1]) { if ( combo.e.mask & IN_MOVED_FROM || combo.e.mask & IN_DELETE) { if (g_ResolvConf == combo.e.name) { /** * Our file has been moved so we should change watching mode. */ inotify_rm_watch(a.fileDescriptor(), wd[0]); wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(), IN_MOVED_TO|IN_CREATE); AssertMsg(wd[1] != -1, ("It shouldn't happen, further investigation is needed\n")); } } else { AssertMsg(combo.e.mask & (IN_MOVED_TO|IN_CREATE), ("%RX32 event isn't expected, we are waiting for IN_MOVED|IN_CREATE\n", combo.e.mask)); if (g_ResolvConf == combo.e.name) { AssertMsg(wd[0] == -1, ("We haven't removed file watcher first\n")); /* alter folder watcher*/ wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(), IN_MOVED_FROM|IN_DELETE); AssertMsg(wd[1] != -1, ("It shouldn't happen.\n")); wd[0] = inotify_add_watch(a.fileDescriptor(), g_ResolvConfFullPath.c_str(), IN_CLOSE_WRITE | IN_DELETE_SELF); AssertMsg(wd[0] != -1, ("Adding watcher to file (%s) has been failed!\n", g_ResolvConfFullPath.c_str())); /* Notify our listeners */ readResolvConf(); } } } else { /* It shouldn't happen */ AssertMsgFailed(("Shouldn't happen! Please debug me!")); } } } }
static DECLCALLBACK(int) drvscsiReqTransferEnqueue(VSCSILUN hVScsiLun, void *pvScsiLunUser, VSCSIIOREQ hVScsiIoReq) { int rc = VINF_SUCCESS; PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; if (pThis->pDrvBlockAsync) { /* async I/O path. */ VSCSIIOREQTXDIR enmTxDir; LogFlowFunc(("Enqueuing hVScsiIoReq=%#p\n", hVScsiIoReq)); enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq); switch (enmTxDir) { case VSCSIIOREQTXDIR_FLUSH: { rc = pThis->pDrvBlockAsync->pfnStartFlush(pThis->pDrvBlockAsync, hVScsiIoReq); if ( RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS && pThis->cErrors++ < MAX_LOG_REL_ERRORS) LogRel(("SCSI#%u: Flush returned rc=%Rrc\n", pThis->pDrvIns->iInstance, rc)); break; } case VSCSIIOREQTXDIR_UNMAP: { PCRTRANGE paRanges; unsigned cRanges; rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges); AssertRC(rc); pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; rc = pThis->pDrvBlockAsync->pfnStartDiscard(pThis->pDrvBlockAsync, paRanges, cRanges, hVScsiIoReq); if ( RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS && pThis->cErrors++ < MAX_LOG_REL_ERRORS) LogRel(("SCSI#%u: Discard returned rc=%Rrc\n", pThis->pDrvIns->iInstance, rc)); break; } case VSCSIIOREQTXDIR_READ: case VSCSIIOREQTXDIR_WRITE: { uint64_t uOffset = 0; size_t cbTransfer = 0; size_t cbSeg = 0; PCRTSGSEG paSeg = NULL; unsigned cSeg = 0; rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, &cSeg, &cbSeg, &paSeg); AssertRC(rc); if (enmTxDir == VSCSIIOREQTXDIR_READ) { pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1; rc = pThis->pDrvBlockAsync->pfnStartRead(pThis->pDrvBlockAsync, uOffset, paSeg, cSeg, cbTransfer, hVScsiIoReq); STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbTransfer); } else { pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; rc = pThis->pDrvBlockAsync->pfnStartWrite(pThis->pDrvBlockAsync, uOffset, paSeg, cSeg, cbTransfer, hVScsiIoReq); STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbTransfer); } if ( RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS && pThis->cErrors++ < MAX_LOG_REL_ERRORS) LogRel(("SCSI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n", pThis->pDrvIns->iInstance, enmTxDir == VSCSIIOREQTXDIR_READ ? "Read" : "Write", uOffset, cbTransfer, rc)); break; } default: AssertMsgFailed(("Invalid transfer direction %u\n", enmTxDir)); } if (rc == VINF_VD_ASYNC_IO_FINISHED) { if (enmTxDir == VSCSIIOREQTXDIR_READ) pThis->pLed->Actual.s.fReading = 0; else if (enmTxDir == VSCSIIOREQTXDIR_WRITE) pThis->pLed->Actual.s.fWriting = 0; else AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir)); VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS, false); rc = VINF_SUCCESS; } else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) rc = VINF_SUCCESS; else if (RT_FAILURE(rc)) { if (enmTxDir == VSCSIIOREQTXDIR_READ) pThis->pLed->Actual.s.fReading = 0; else if (enmTxDir == VSCSIIOREQTXDIR_WRITE) pThis->pLed->Actual.s.fWriting = 0; else AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir)); VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc)); rc = VINF_SUCCESS; } else AssertMsgFailed(("Invalid return code rc=%Rrc\n", rc)); } else { /* I/O thread. */ rc = RTReqQueueCallEx(pThis->hQueueRequests, NULL, 0, RTREQFLAGS_NO_WAIT, (PFNRT)drvscsiProcessRequestOne, 2, pThis, hVScsiIoReq); } return rc; }
static int tstRandAdv(RTRAND hRand) { /* * Test distribution. */ #if 1 /* unsigned 32-bit */ static const struct { uint32_t u32First; uint32_t u32Last; } s_aU32Tests[] = { { 0, UINT32_MAX }, { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, { 0, UINT32_MAX / 2 }, { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, { 0, TST_RAND_SAMPLE_RANGES - 1 }, { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU32Tests); iTest++) { uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; uint32_t const uFirst = s_aU32Tests[iTest].u32First; uint32_t const uLast = s_aU32Tests[iTest].u32Last; uint32_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); uint32_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; RTPrintf("tstRand: TESTING RTRandAdvU32Ex(,%#RX32, %#RX32) distribution... [div=%#RX32 range=%#RX32]\n", uFirst, uLast, uDivisor, uRange); for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) { uint32_t uRand = RTRandAdvU32Ex(hRand, uFirst, uLast); CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX32 %#RX32\n", uRand, uFirst)); CHECK_EXPR_MSG(uRand <= uLast, ("%#RX32 %#RX32\n", uRand, uLast)); uint32_t off = uRand - uFirst; acHits[off / uDivisor]++; } tstRandCheckDist(acHits, iTest); } #endif #if 1 /* unsigned 64-bit */ static const struct { uint64_t u64First; uint64_t u64Last; } s_aU64Tests[] = { { 0, UINT64_MAX }, { 0, UINT64_MAX / 2 + UINT64_MAX / 4 }, { 0, UINT64_MAX / 2 + UINT64_MAX / 8 }, { 0, UINT64_MAX / 2 + UINT64_MAX / 16 }, { 0, UINT64_MAX / 2 + UINT64_MAX / 64 }, { 0, UINT64_MAX / 2 }, { UINT64_MAX / 4, UINT64_MAX / 4 * 3 }, { 0, UINT32_MAX }, { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, { 0, UINT32_MAX / 2 }, { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, { 0, TST_RAND_SAMPLE_RANGES - 1 }, { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU64Tests); iTest++) { uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; uint64_t const uFirst = s_aU64Tests[iTest].u64First; uint64_t const uLast = s_aU64Tests[iTest].u64Last; uint64_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); uint64_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; RTPrintf("tstRand: TESTING RTRandAdvU64Ex(,%#RX64, %#RX64) distribution... [div=%#RX64 range=%#RX64]\n", uFirst, uLast, uDivisor, uRange); for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) { uint64_t uRand = RTRandAdvU64Ex(hRand, uFirst, uLast); CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX64 %#RX64\n", uRand, uFirst)); CHECK_EXPR_MSG(uRand <= uLast, ("%#RX64 %#RX64\n", uRand, uLast)); uint64_t off = uRand - uFirst; acHits[off / uDivisor]++; } tstRandCheckDist(acHits, iTest); } #endif #if 1 /* signed 32-bit */ static const struct { int32_t i32First; int32_t i32Last; } s_aS32Tests[] = { { -429496729, 429496729 }, { INT32_MIN, INT32_MAX }, { INT32_MIN, INT32_MAX / 2 }, { -0x20000000, INT32_MAX }, { -0x10000000, INT32_MAX }, { -0x08000000, INT32_MAX }, { -0x00800000, INT32_MAX }, { -0x00080000, INT32_MAX }, { -0x00008000, INT32_MAX }, { -0x00000800, INT32_MAX }, { 2, INT32_MAX / 2 }, { 4000000, INT32_MAX / 2 }, { -4000000, INT32_MAX / 2 }, { INT32_MIN / 2, INT32_MAX / 2 }, { INT32_MIN / 3, INT32_MAX / 2 }, { INT32_MIN / 3, INT32_MAX / 3 }, { INT32_MIN / 3, INT32_MAX / 4 }, { INT32_MIN / 4, INT32_MAX / 4 }, { INT32_MIN / 5, INT32_MAX / 5 }, { INT32_MIN / 6, INT32_MAX / 6 }, { INT32_MIN / 7, INT32_MAX / 6 }, { INT32_MIN / 7, INT32_MAX / 7 }, { INT32_MIN / 7, INT32_MAX / 8 }, { INT32_MIN / 8, INT32_MAX / 8 }, { INT32_MIN / 9, INT32_MAX / 9 }, { INT32_MIN / 9, INT32_MAX / 12 }, { INT32_MIN / 12, INT32_MAX / 12 }, { 0, TST_RAND_SAMPLE_RANGES - 1 }, { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 }, }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS32Tests); iTest++) { uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; int32_t const iFirst = s_aS32Tests[iTest].i32First; int32_t const iLast = s_aS32Tests[iTest].i32Last; uint32_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); uint32_t const uDivisor = (uRange ? uRange : UINT32_MAX) / TST_RAND_SAMPLE_RANGES + 1; RTPrintf("tstRand: TESTING RTRandAdvS32Ex(,%#RI32, %#RI32) distribution... [div=%#RX32 range=%#RX32]\n", iFirst, iLast, uDivisor, uRange); for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) { int32_t iRand = RTRandAdvS32Ex(hRand, iFirst, iLast); CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI32 %#RI32\n", iRand, iFirst)); CHECK_EXPR_MSG(iRand <= iLast, ("%#RI32 %#RI32\n", iRand, iLast)); uint32_t off = iRand - iFirst; acHits[off / uDivisor]++; } tstRandCheckDist(acHits, iTest); } #endif #if 1 /* signed 64-bit */ static const struct { int64_t i64First; int64_t i64Last; } s_aS64Tests[] = { { INT64_MIN, INT64_MAX }, { INT64_MIN, INT64_MAX / 2 }, { INT64_MIN / 2, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 4, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 8, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 16, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 + INT64_MAX / 64 }, { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 64 }, { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 8 }, { INT64_MIN / 2, INT64_MAX / 2 - INT64_MAX / 8 }, { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 4 }, { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 8 }, { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 - INT64_MAX / 8 }, { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 8 }, { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 16 }, { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 16 }, { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 32 }, { INT64_MIN / 2 - INT64_MIN / 64, INT64_MAX / 2 - INT64_MAX / 64 }, { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 }, { INT64_MIN / 4, INT64_MAX / 4 }, { INT64_MIN / 5, INT64_MAX / 5 }, { INT64_MIN / 6, INT64_MAX / 6 }, { INT64_MIN / 7, INT64_MAX / 7 }, { INT64_MIN / 8, INT64_MAX / 8 }, { INT32_MIN, INT32_MAX }, { INT32_MIN, INT32_MAX / 2 }, { -0x20000000, INT32_MAX }, { -0x10000000, INT32_MAX }, { -0x7f000000, INT32_MAX }, { -0x08000000, INT32_MAX }, { -0x00800000, INT32_MAX }, { -0x00080000, INT32_MAX }, { -0x00008000, INT32_MAX }, { 2, INT32_MAX / 2 }, { 4000000, INT32_MAX / 2 }, { -4000000, INT32_MAX / 2 }, { INT32_MIN / 2, INT32_MAX / 2 }, { 0, TST_RAND_SAMPLE_RANGES - 1 }, { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 } }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS64Tests); iTest++) { uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; int64_t const iFirst = s_aS64Tests[iTest].i64First; int64_t const iLast = s_aS64Tests[iTest].i64Last; uint64_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); uint64_t const uDivisor = (uRange ? uRange : UINT64_MAX) / TST_RAND_SAMPLE_RANGES + 1; RTPrintf("tstRand: TESTING RTRandAdvS64Ex(,%#RI64, %#RI64) distribution... [div=%#RX64 range=%#016RX64]\n", iFirst, iLast, uDivisor, uRange); for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) { int64_t iRand = RTRandAdvS64Ex(hRand, iFirst, iLast); CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI64 %#RI64\n", iRand, iFirst)); CHECK_EXPR_MSG(iRand <= iLast, ("%#RI64 %#RI64\n", iRand, iLast)); uint64_t off = iRand - iFirst; acHits[off / uDivisor]++; } tstRandCheckDist(acHits, iTest); } #endif /* * Test saving and restoring the state. */ RTPrintf("tstRand: TESTING RTRandAdvSave/RestoreSave\n"); char szState[256]; size_t cbState = sizeof(szState); int rc = RTRandAdvSaveState(hRand, szState, &cbState); if (rc != VERR_NOT_SUPPORTED) { CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("RTRandAdvSaveState(%p,,256) -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); uint32_t const u32A1 = RTRandAdvU32(hRand); uint32_t const u32B1 = RTRandAdvU32(hRand); RTPrintf("tstRand: state:\"%s\" A=%RX32 B=%RX32\n", szState, u32A1, u32B1); rc = RTRandAdvRestoreState(hRand, szState); CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("RTRandAdvRestoreState(%p,\"%s\") -> %Rrc (%d)\n", (uintptr_t)hRand, szState, rc, rc)); uint32_t const u32A2 = RTRandAdvU32(hRand); uint32_t const u32B2 = RTRandAdvU32(hRand); CHECK_EXPR_MSG(u32A1 == u32A2, ("u32A1=%RX32 u32A2=%RX32\n", u32A1, u32A2)); CHECK_EXPR_MSG(u32B1 == u32B2, ("u32B1=%RX32 u32B2=%RX32\n", u32B1, u32B2)); } else { szState[0] = '\0'; rc = RTRandAdvRestoreState(hRand, szState); CHECK_EXPR_MSG(rc == VERR_NOT_SUPPORTED, ("RTRandAdvRestoreState(%p,\"\") -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); } /* * Destroy it. */ rc = RTRandAdvDestroy(hRand); CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("RTRandAdvDestroy(%p) -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); return 0; }
DEFINE_THIS_FILE //:End Ignore //:>******************************************************************************************** //:> AfWnd methods. //:>******************************************************************************************** /*---------------------------------------------------------------------------------------------- Register this window class. This is a static method. @param pszName The window class name. @param grfwcs Window class style flags (CS_HREDRAW, CS_NOCLOSE, ...) @param ridCrs Resource ID for the window class cursor, or 0. @param ridMenu Resource ID for the window class menu, or 0. @param clrBack Background color for the window class. @param ridIcon Resource ID for the window class icon, or 0. @param ridIconSmall Resource ID for the window class small icon, or 0. ----------------------------------------------------------------------------------------------*/ void AfWnd::RegisterClass(Pcsz pszName, int grfwcs, int ridCrs, int ridMenu, int clrBack, int ridIcon, int ridIconSmall) { AssertPsz(pszName); Assert(!(ridCrs & 0xFFFF0000)); Assert(!(ridMenu & 0xFFFF0000)); Assert(clrBack == -1 || !(clrBack & 0xFFFF0000)); Assert(!(ridIcon & 0xFFFF0000)); Assert(!(ridIconSmall & 0xFFFF0000)); WNDCLASSEX wcx; HINSTANCE hinst = ModuleEntry::GetModuleHandle(); ClearItems(&wcx, 1); wcx.cbSize = isizeof(wcx); wcx.style = grfwcs; wcx.lpfnWndProc = &AfWnd::WndProc; wcx.cbClsExtra = 0; // REVIEW ShonK: For dialogs this needs to be DLGWINDOWEXTRA. Will we ever register // dialog classes? Probably not. wcx.cbWndExtra = 0; wcx.hInstance = hinst; // REVIEW ShonK: Determine whether to pass NULL or hinst in LoadIcon calls. wcx.hIcon = ridIcon ? ::LoadIcon(hinst, MAKEINTRESOURCE(ridIcon)) : NULL; wcx.hCursor = ridCrs ? ::LoadCursor(NULL, MAKEINTRESOURCE(ridCrs)) : NULL; // REVIEW ShonK: Do we not want to disallow a brush to be passed in clrBack? // hbrBackground in WNDCLASSEX allows a brush if it is not one a fixed number of // system colors. For context help we want COLOR_INFOBK which is not listed as // one of the valid colors. However, this along with the assert above, fails if // we try to pass a brush with COLOR_INFOBK, although this should be acceptable to // WNDCLASSEX. It ends up that we can pass COLOR_INFOBK to this method directly, and // it works OK. Will any color work using this approach, or should we allow a brush // to be consistent with WNDCLASSEX? // wcx.hbrBackground = (uint)clrBack < (uint)30 ? (HBRUSH)(clrBack + 1) : (HBRUSH)clrBack; wcx.hbrBackground = clrBack >= 0 ? (HBRUSH)(clrBack + 1) : NULL; wcx.lpszMenuName = MAKEINTRESOURCE(ridMenu); wcx.lpszClassName = pszName; wcx.hIconSm = ridIconSmall ? ::LoadIcon(hinst, MAKEINTRESOURCE(ridIconSmall)) : NULL; if (!::RegisterClassEx(&wcx)) { // we try to avoid this, but it can happen with opening/closing multiple projects and // multiple dialogs. DWORD dw = ::GetLastError(); if (dw == ERROR_CLASS_ALREADY_EXISTS) return; AssertMsg(false, "Registering window class failed."); ThrowHr(WarnHr(E_UNEXPECTED)); } }
/* Mini-toolbar constructor */ VBoxMiniToolBar::VBoxMiniToolBar(QWidget *pParent, Alignment alignment, bool fActive, bool fAutoHide) : UIToolBar(pParent) , m_pAutoHideAction(0) , m_pDisplayLabel(0) , m_pMinimizeAction(0) , m_pRestoreAction(0) , m_pCloseAction(0) , m_fActive(fActive) , m_fPolished(false) , m_fSeamless(false) , m_fAutoHide(fAutoHide) , m_fSlideToScreen(true) , m_fHideAfterSlide(false) , m_iAutoHideCounter(0) , m_iPositionX(0) , m_iPositionY(0) , m_pInsertPosition(0) , m_alignment(alignment) , m_fAnimated(true) , m_iScrollDelay(10) , m_iAutoScrollDelay(100) , m_iAutoHideTotalCounter(10) { /* Check parent widget presence: */ AssertMsg(parentWidget(), ("Parent widget must be set!\n")); /* Toolbar options: */ setIconSize(QSize(16, 16)); setVisible(false); /* Left margin of tool-bar: */ m_Margins << widgetForAction(addWidget(new QWidget(this))); /* Add pushpin: */ m_pAutoHideAction = new QAction(this); m_pAutoHideAction->setIcon(UIIconPool::iconSet(":/pin_16px.png")); m_pAutoHideAction->setToolTip(tr("Always show the toolbar")); m_pAutoHideAction->setCheckable(true); m_pAutoHideAction->setChecked(!m_fAutoHide); connect(m_pAutoHideAction, SIGNAL(toggled(bool)), this, SLOT(togglePushpin(bool))); addAction(m_pAutoHideAction); /* Left menu margin: */ m_Spacings << widgetForAction(addWidget(new QWidget(this))); /* Right menu margin: */ m_pInsertPosition = addWidget(new QWidget(this)); m_Spacings << widgetForAction(m_pInsertPosition); /* Left label margin: */ m_LabelMargins << widgetForAction(addWidget(new QWidget(this))); /* Insert a label for VM Name: */ m_pDisplayLabel = new QLabel(this); m_pDisplayLabel->setAlignment(Qt::AlignCenter); addWidget(m_pDisplayLabel); /* Right label margin: */ m_LabelMargins << widgetForAction(addWidget(new QWidget(this))); /* Minimize action: */ m_pMinimizeAction = new QAction(this); m_pMinimizeAction->setIcon(UIIconPool::iconSet(":/minimize_16px.png")); m_pMinimizeAction->setToolTip(tr("Minimize Window")); connect(m_pMinimizeAction, SIGNAL(triggered()), this, SIGNAL(minimizeAction())); addAction(m_pMinimizeAction); /* Exit action: */ m_pRestoreAction = new QAction(this); m_pRestoreAction->setIcon(UIIconPool::iconSet(":/restore_16px.png")); m_pRestoreAction->setToolTip(tr("Exit Full Screen or Seamless Mode")); connect(m_pRestoreAction, SIGNAL(triggered()), this, SIGNAL(exitAction())); addAction(m_pRestoreAction); /* Close action: */ m_pCloseAction = new QAction(this); m_pCloseAction->setIcon(UIIconPool::iconSet(":/close_16px.png")); m_pCloseAction->setToolTip(tr("Close VM")); connect(m_pCloseAction, SIGNAL(triggered()), this, SIGNAL(closeAction())); addAction(m_pCloseAction); /* Right margin of tool-bar: */ m_Margins << widgetForAction(addWidget(new QWidget(this))); /* Event-filter for parent widget to control resize: */ pParent->installEventFilter(this); /* Enable mouse-tracking for this & children allowing to get mouse-move events: */ setMouseTrackingEnabled(m_fAutoHide); }
/** * Allocates a block of memory from the specified heap. * * No parameter validation or adjustment is performed. * * @returns Pointer to the allocated block. * @returns NULL on failure. * * @param pHeapInt The heap. * @param cb Size of the memory block to allocate. * @param uAlignment The alignment specifications for the allocated block. */ static PRTHEAPSIMPLEBLOCK rtHeapSimpleAllocBlock(PRTHEAPSIMPLEINTERNAL pHeapInt, size_t cb, size_t uAlignment) { PRTHEAPSIMPLEBLOCK pRet = NULL; PRTHEAPSIMPLEFREE pFree; #ifdef RTHEAPSIMPLE_STRICT rtHeapSimpleAssertAll(pHeapInt); #endif /* * Search for a fitting block from the lower end of the heap. */ for (pFree = pHeapInt->pFreeHead; pFree; pFree = pFree->pNext) { uintptr_t offAlign; ASSERT_BLOCK_FREE(pHeapInt, pFree); /* * Match for size and alignment. */ if (pFree->cb < cb) continue; offAlign = (uintptr_t)(&pFree->Core + 1) & (uAlignment - 1); if (offAlign) { RTHEAPSIMPLEFREE Free; PRTHEAPSIMPLEBLOCK pPrev; offAlign = uAlignment - offAlign; if (pFree->cb - offAlign < cb) continue; /* * Make a stack copy of the free block header and adjust the pointer. */ Free = *pFree; pFree = (PRTHEAPSIMPLEFREE)((uintptr_t)pFree + offAlign); /* * Donate offAlign bytes to the node in front of us. * If we're the head node, we'll have to create a fake node. We'll * mark it USED for simplicity. * * (Should this policy of donating memory to the guy in front of us * cause big 'leaks', we could create a new free node if there is room * for that.) */ pPrev = Free.Core.pPrev; if (pPrev) { AssertMsg(!RTHEAPSIMPLEBLOCK_IS_FREE(pPrev), ("Impossible!\n")); pPrev->pNext = &pFree->Core; } else { pPrev = (PRTHEAPSIMPLEBLOCK)(pHeapInt + 1); Assert(pPrev == &pFree->Core); pPrev->pPrev = NULL; pPrev->pNext = &pFree->Core; pPrev->pHeap = pHeapInt; pPrev->fFlags = RTHEAPSIMPLEBLOCK_FLAGS_MAGIC; } pHeapInt->cbFree -= offAlign; /* * Recreate pFree in the new position and adjust the neighbors. */ *pFree = Free; /* the core */ if (pFree->Core.pNext) pFree->Core.pNext->pPrev = &pFree->Core; pFree->Core.pPrev = pPrev; /* the free part */ pFree->cb -= offAlign; if (pFree->pNext) pFree->pNext->pPrev = pFree; else pHeapInt->pFreeTail = pFree; if (pFree->pPrev) pFree->pPrev->pNext = pFree; else pHeapInt->pFreeHead = pFree; ASSERT_BLOCK_FREE(pHeapInt, pFree); ASSERT_BLOCK_USED(pHeapInt, pPrev); } /* * Split off a new FREE block? */ if (pFree->cb >= cb + RT_ALIGN_Z(sizeof(RTHEAPSIMPLEFREE), RTHEAPSIMPLE_ALIGNMENT)) { /* * Move the FREE block up to make room for the new USED block. */ PRTHEAPSIMPLEFREE pNew = (PRTHEAPSIMPLEFREE)((uintptr_t)&pFree->Core + cb + sizeof(RTHEAPSIMPLEBLOCK)); pNew->Core.pNext = pFree->Core.pNext; if (pFree->Core.pNext) pFree->Core.pNext->pPrev = &pNew->Core; pNew->Core.pPrev = &pFree->Core; pNew->Core.pHeap = pHeapInt; pNew->Core.fFlags = RTHEAPSIMPLEBLOCK_FLAGS_MAGIC | RTHEAPSIMPLEBLOCK_FLAGS_FREE; pNew->pNext = pFree->pNext; if (pNew->pNext) pNew->pNext->pPrev = pNew; else pHeapInt->pFreeTail = pNew; pNew->pPrev = pFree->pPrev; if (pNew->pPrev) pNew->pPrev->pNext = pNew; else pHeapInt->pFreeHead = pNew; pNew->cb = (pNew->Core.pNext ? (uintptr_t)pNew->Core.pNext : (uintptr_t)pHeapInt->pvEnd) \ - (uintptr_t)pNew - sizeof(RTHEAPSIMPLEBLOCK); ASSERT_BLOCK_FREE(pHeapInt, pNew); /* * Update the old FREE node making it a USED node. */ pFree->Core.fFlags &= ~RTHEAPSIMPLEBLOCK_FLAGS_FREE; pFree->Core.pNext = &pNew->Core; pHeapInt->cbFree -= pFree->cb; pHeapInt->cbFree += pNew->cb; pRet = &pFree->Core; ASSERT_BLOCK_USED(pHeapInt, pRet); } else { /* * Link it out of the free list. */ if (pFree->pNext) pFree->pNext->pPrev = pFree->pPrev; else pHeapInt->pFreeTail = pFree->pPrev; if (pFree->pPrev) pFree->pPrev->pNext = pFree->pNext; else pHeapInt->pFreeHead = pFree->pNext; /* * Convert it to a used block. */ pHeapInt->cbFree -= pFree->cb; pFree->Core.fFlags &= ~RTHEAPSIMPLEBLOCK_FLAGS_FREE; pRet = &pFree->Core; ASSERT_BLOCK_USED(pHeapInt, pRet); } break; } #ifdef RTHEAPSIMPLE_STRICT rtHeapSimpleAssertAll(pHeapInt); #endif return pRet; }
void CAI_PlaneSolver::GenerateSuggestionFromTrace( const AILocalMoveGoal_t &goal, const AIMoveTrace_t &moveTrace, float probeDist, float arcCenter, float arcSpan, int probeOffset ) { AI_MoveSuggestion_t suggestion; AI_MoveSuggType_t type; switch ( moveTrace.fStatus ) { case AIMR_BLOCKED_ENTITY: type = AIMST_AVOID_OBJECT; break; case AIMR_BLOCKED_WORLD: type = AIMST_AVOID_WORLD; break; case AIMR_BLOCKED_NPC: type = AIMST_AVOID_NPC; break; case AIMR_ILLEGAL: type = AIMST_AVOID_DANGER; break; default: type = AIMST_NO_KNOWLEDGE; AssertMsg( 0, "Unexpected mode status" ); break; } if ( goal.pMoveTarget != NULL && goal.pMoveTarget == moveTrace.pObstruction ) { suggestion.Set( type, 0, arcCenter, arcSpan, moveTrace.pObstruction ); m_Solver.AddRegulation( suggestion ); return; } float clearDist = probeDist - moveTrace.flDistObstructed; float pctBlocked = 1.0 - ( clearDist / probeDist ); float weight = CalculateRegulationWeight( moveTrace, pctBlocked ); if ( weight < 0.001 ) return; if ( pctBlocked < 0.5 ) { arcSpan *= pctBlocked * 2.0; } Vector vecToEnd = moveTrace.vEndPosition - GetLocalOrigin(); Vector crossProduct; bool favorLeft = false, favorRight = false; if ( moveTrace.fStatus == AIMR_BLOCKED_NPC ) { Vector vecToOther = moveTrace.pObstruction->GetLocalOrigin() - GetLocalOrigin(); CrossProduct(vecToEnd, vecToOther, crossProduct); favorLeft = ( crossProduct.z < 0 ); favorRight = ( crossProduct.z > 0 ); } else if ( moveTrace.vHitNormal != vec3_origin ) { CrossProduct(vecToEnd, moveTrace.vHitNormal, crossProduct); favorLeft = ( crossProduct.z > 0 ); favorRight = ( crossProduct.z < 0 ); } float thirdSpan = arcSpan / 3.0; float favoredWeight = weight * pctBlocked; suggestion.Set( type, weight, arcCenter, thirdSpan, moveTrace.pObstruction ); m_Solver.AddRegulation( suggestion ); suggestion.Set( type, ( favorRight ) ? favoredWeight : weight, arcCenter - thirdSpan, thirdSpan, moveTrace.pObstruction ); m_Solver.AddRegulation( suggestion ); suggestion.Set( type, ( favorLeft ) ? favoredWeight : weight, arcCenter + thirdSpan, thirdSpan, moveTrace.pObstruction ); m_Solver.AddRegulation( suggestion ); }
Console::teleporterTrgServeConnection(RTSOCKET Sock, void *pvUser) { TeleporterStateTrg *pState = (TeleporterStateTrg *)pvUser; pState->mhSocket = Sock; /* * Disable Nagle and say hello. */ int vrc = RTTcpSetSendCoalescing(pState->mhSocket, false /*fEnable*/); AssertRC(vrc); vrc = RTTcpWrite(Sock, g_szWelcome, sizeof(g_szWelcome) - 1); if (RT_FAILURE(vrc)) { LogRel(("Teleporter: Failed to write welcome message: %Rrc\n", vrc)); return VINF_SUCCESS; } /* * Password (includes '\n', see teleporterTrg). */ const char *pszPassword = pState->mstrPassword.c_str(); unsigned off = 0; while (pszPassword[off]) { char ch; vrc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); if ( RT_FAILURE(vrc) || pszPassword[off] != ch) { if (RT_FAILURE(vrc)) LogRel(("Teleporter: Password read failure (off=%u): %Rrc\n", off, vrc)); else LogRel(("Teleporter: Invalid password (off=%u)\n", off)); teleporterTcpWriteNACK(pState, VERR_AUTHENTICATION_FAILURE); return VINF_SUCCESS; } off++; } vrc = teleporterTcpWriteACK(pState); if (RT_FAILURE(vrc)) return VINF_SUCCESS; /* * Update the progress bar, with peer name if available. */ HRESULT hrc; RTNETADDR Addr; vrc = RTTcpGetPeerAddress(Sock, &Addr); if (RT_SUCCESS(vrc)) { LogRel(("Teleporter: Incoming VM from %RTnaddr!\n", &Addr)); hrc = pState->mptrProgress->SetNextOperation(BstrFmt(tr("Teleporting VM from %RTnaddr"), &Addr).raw(), 8); } else { LogRel(("Teleporter: Incoming VM!\n")); hrc = pState->mptrProgress->SetNextOperation(Bstr(tr("Teleporting VM")).raw(), 8); } AssertMsg(SUCCEEDED(hrc) || hrc == E_FAIL, ("%Rhrc\n", hrc)); /* * Stop the server and cancel the timeout timer. * * Note! After this point we must return VERR_TCP_SERVER_STOP, while prior * to it we must not return that value! */ RTTcpServerShutdown(pState->mhServer); RTTimerLRDestroy(*pState->mphTimerLR); *pState->mphTimerLR = NIL_RTTIMERLR; /* * Command processing loop. */ bool fDone = false; for (;;) { char szCmd[128]; vrc = teleporterTcpReadLine(pState, szCmd, sizeof(szCmd)); if (RT_FAILURE(vrc)) break; if (!strcmp(szCmd, "load")) { vrc = teleporterTcpWriteACK(pState); if (RT_FAILURE(vrc)) break; int vrc2 = VMR3AtErrorRegisterU(pState->mpUVM, Console::genericVMSetErrorCallback, &pState->mErrorText); AssertRC(vrc2); RTSocketRetain(pState->mhSocket); /* For concurrent access by I/O thread and EMT. */ pState->moffStream = 0; void *pvUser2 = static_cast<void *>(static_cast<TeleporterState *>(pState)); vrc = VMR3LoadFromStream(VMR3GetVM(pState->mpUVM), &g_teleporterTcpOps, pvUser2, teleporterProgressCallback, pvUser2); RTSocketRelease(pState->mhSocket); vrc2 = VMR3AtErrorDeregister(VMR3GetVM(pState->mpUVM), Console::genericVMSetErrorCallback, &pState->mErrorText); AssertRC(vrc2); if (RT_FAILURE(vrc)) { LogRel(("Teleporter: VMR3LoadFromStream -> %Rrc\n", vrc)); teleporterTcpWriteNACK(pState, vrc, pState->mErrorText.c_str()); break; } /* The EOS might not have been read, make sure it is. */ pState->mfStopReading = false; size_t cbRead; vrc = teleporterTcpOpRead(pvUser2, pState->moffStream, szCmd, 1, &cbRead); if (vrc != VERR_EOF) { LogRel(("Teleporter: Draining teleporterTcpOpRead -> %Rrc\n", vrc)); teleporterTcpWriteNACK(pState, vrc); break; } vrc = teleporterTcpWriteACK(pState); } else if (!strcmp(szCmd, "cancel")) { /* Don't ACK this. */ LogRel(("Teleporter: Received cancel command.\n")); vrc = VERR_SSM_CANCELLED; } else if (!strcmp(szCmd, "lock-media")) { hrc = pState->mpControl->LockMedia(); if (SUCCEEDED(hrc)) { pState->mfLockedMedia = true; vrc = teleporterTcpWriteACK(pState); } else { vrc = VERR_FILE_LOCK_FAILED; teleporterTcpWriteNACK(pState, vrc); } } else if ( !strcmp(szCmd, "hand-over-resume") || !strcmp(szCmd, "hand-over-paused")) { /* * Point of no return. * * Note! Since we cannot tell whether a VMR3Resume failure is * destructive for the source or not, we have little choice * but to ACK it first and take any failures locally. * * Ideally, we should try resume it first and then ACK (or * NACK) the request since this would reduce latency and * make it possible to recover from some VMR3Resume failures. */ if ( pState->mptrProgress->notifyPointOfNoReturn() && pState->mfLockedMedia) { vrc = teleporterTcpWriteACK(pState); if (RT_SUCCESS(vrc)) { if (!strcmp(szCmd, "hand-over-resume")) vrc = VMR3Resume(VMR3GetVM(pState->mpUVM)); else pState->mptrConsole->setMachineState(MachineState_Paused); fDone = true; break; } } else { vrc = pState->mfLockedMedia ? VERR_WRONG_ORDER : VERR_SSM_CANCELLED; teleporterTcpWriteNACK(pState, vrc); } } else { LogRel(("Teleporter: Unknown command '%s' (%.*Rhxs)\n", szCmd, strlen(szCmd), szCmd)); vrc = VERR_NOT_IMPLEMENTED; teleporterTcpWriteNACK(pState, vrc); } if (RT_FAILURE(vrc)) break; } if (RT_SUCCESS(vrc) && !fDone) vrc = VERR_WRONG_ORDER; if (RT_FAILURE(vrc)) teleporterTrgUnlockMedia(pState); pState->mRc = vrc; pState->mhSocket = NIL_RTSOCKET; LogFlowFunc(("returns mRc=%Rrc\n", vrc)); return VERR_TCP_SERVER_STOP; }
/** * Internal worker that create a darwin mbuf for a (scatter/)gather list. * * @returns Pointer to the mbuf. * @param pThis The instance. * @param pSG The (scatter/)gather list. */ static mbuf_t vboxNetFltDarwinMBufFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG) { /// @todo future? mbuf_how_t How = preemption enabled ? MBUF_DONTWAIT : MBUF_WAITOK; mbuf_how_t How = MBUF_WAITOK; /* * We need some way of getting back to our instance data when * the mbuf is freed, so use pvUserData for this. * -- this is not relevant anylonger! -- */ Assert(!pSG->pvUserData || pSG->pvUserData == pThis); Assert(!pSG->pvUserData2); pSG->pvUserData = pThis; /* * Allocate a packet and copy over the data. * * Using mbuf_attachcluster() here would've been nice but there are two * issues with it: (1) it's 10.5.x only, and (2) the documentation indicates * that it's not supposed to be used for really external buffers. The 2nd * point might be argued against considering that the only m_clattach user * is mallocs memory for the ext mbuf and not doing what's stated in the docs. * However, it's hard to tell if these m_clattach buffers actually makes it * to the NICs or not, and even if they did, the NIC would need the physical * addresses for the pages they contain and might end up copying the data * to a new mbuf anyway. * * So, in the end it's better to just do it the simple way that will work * 100%, even if it involves some extra work (alloc + copy) we really wished * to avoid. * * Note. We can't make use of the physical addresses on darwin because the * way the mbuf / cluster stuff works (see mbuf_data_to_physical and * mcl_to_paddr). */ mbuf_t pPkt = NULL; errno_t err = mbuf_allocpacket(How, pSG->cbTotal, NULL, &pPkt); if (!err) { /* Skip zero sized memory buffers (paranoia). */ mbuf_t pCur = pPkt; while (pCur && !mbuf_maxlen(pCur)) pCur = mbuf_next(pCur); Assert(pCur); /* Set the required packet header attributes. */ mbuf_pkthdr_setlen(pPkt, pSG->cbTotal); mbuf_pkthdr_setheader(pPkt, mbuf_data(pCur)); /* Special case the single buffer copy. */ if ( mbuf_next(pCur) && mbuf_maxlen(pCur) >= pSG->cbTotal) { mbuf_setlen(pCur, pSG->cbTotal); IntNetSgRead(pSG, mbuf_data(pCur)); } else { /* Multi buffer copying. */ size_t cbLeft = pSG->cbTotal; size_t offSrc = 0; while (cbLeft > 0 && pCur) { size_t cb = mbuf_maxlen(pCur); if (cb > cbLeft) cb = cbLeft; mbuf_setlen(pCur, cb); IntNetSgReadEx(pSG, offSrc, cb, mbuf_data(pCur)); /* advance */ offSrc += cb; cbLeft -= cb; pCur = mbuf_next(pCur); } Assert(cbLeft == 0); } if (!err) { /* * Tag the packet and return successfully. */ PVBOXNETFLTTAG pTagData; err = mbuf_tag_allocate(pPkt, g_idTag, 0 /* type */, sizeof(VBOXNETFLTTAG) /* tag len */, How, (void **)&pTagData); if (!err) { Assert(pSG->aSegs[0].cb >= sizeof(pTagData->EthHdr)); memcpy(&pTagData->EthHdr, pSG->aSegs[0].pv, sizeof(pTagData->EthHdr)); return pPkt; } /* bailout: */ AssertMsg(err == ENOMEM || err == EWOULDBLOCK, ("err=%d\n", err)); } mbuf_freem(pPkt); } else AssertMsg(err == ENOMEM || err == EWOULDBLOCK, ("err=%d\n", err)); pSG->pvUserData = NULL; return NULL; }
/** * Initializes a SG list from an mbuf. * * @returns Number of segments. * @param pThis The instance. * @param pMBuf The mbuf. * @param pSG The SG. * @param pvFrame The frame pointer, optional. * @param cSegs The number of segments allocated for the SG. * This should match the number in the mbuf exactly! * @param fSrc The source of the frame. */ DECLINLINE(void) vboxNetFltDarwinMBufToSG(PVBOXNETFLTINS pThis, mbuf_t pMBuf, void *pvFrame, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc) { NOREF(pThis); /* * Walk the chain and convert the buffers to segments. Works INTNETSG::cbTotal. */ unsigned iSeg = 0; IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, cSegs, 0 /*cSegsUsed*/); for (mbuf_t pCur = pMBuf; pCur; pCur = mbuf_next(pCur)) { size_t cbSeg = mbuf_len(pCur); if (cbSeg) { void *pvSeg = mbuf_data(pCur); /* deal with pvFrame */ if (!iSeg && pvFrame && pvFrame != pvSeg) { void *pvStart = mbuf_datastart(pMBuf); uintptr_t offSeg = (uintptr_t)pvSeg - (uintptr_t)pvStart; uintptr_t offSegEnd = offSeg + cbSeg; Assert(pvStart && pvSeg && offSeg < mbuf_maxlen(pMBuf) && offSegEnd <= mbuf_maxlen(pMBuf)); NOREF(offSegEnd); uintptr_t offFrame = (uintptr_t)pvFrame - (uintptr_t)pvStart; if (RT_LIKELY(offFrame < offSeg)) { pvSeg = pvFrame; cbSeg += offSeg - offFrame; } else AssertMsgFailed(("pvFrame=%p pvStart=%p pvSeg=%p offSeg=%p cbSeg=%#zx offSegEnd=%p offFrame=%p maxlen=%#zx\n", pvFrame, pvStart, pvSeg, offSeg, cbSeg, offSegEnd, offFrame, mbuf_maxlen(pMBuf))); pvFrame = NULL; } AssertBreak(iSeg < cSegs); pSG->cbTotal += cbSeg; pSG->aSegs[iSeg].cb = cbSeg; pSG->aSegs[iSeg].pv = pvSeg; pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS; iSeg++; } /* The pvFrame might be in a now empty buffer. */ else if ( !iSeg && pvFrame && (uintptr_t)pvFrame - (uintptr_t)mbuf_datastart(pMBuf) < mbuf_maxlen(pMBuf)) { cbSeg = (uintptr_t)mbuf_datastart(pMBuf) + mbuf_maxlen(pMBuf) - (uintptr_t)pvFrame; pSG->cbTotal += cbSeg; pSG->aSegs[iSeg].cb = cbSeg; pSG->aSegs[iSeg].pv = pvFrame; pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS; iSeg++; pvFrame = NULL; } } Assert(iSeg && iSeg <= cSegs); pSG->cSegsUsed = iSeg; #ifdef PADD_RUNT_FRAMES_FROM_HOST /* * Add a trailer if the frame is too small. * * Since we're getting to the packet before it is framed, it has not * yet been padded. The current solution is to add a segment pointing * to a buffer containing all zeros and pray that works for all frames... */ if (pSG->cbTotal < 60 && (fSrc & INTNETTRUNKDIR_HOST)) { AssertReturnVoid(iSeg < cSegs); static uint8_t const s_abZero[128] = {0}; pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS; pSG->aSegs[iSeg].pv = (void *)&s_abZero[0]; pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal; pSG->cbTotal = 60; pSG->cSegsUsed++; } #endif #ifdef VBOXNETFLT_DARWIN_TEST_SEG_SIZE /* * Redistribute the segments. */ if (pSG->cSegsUsed < pSG->cSegsAlloc) { /* copy the segments to the end. */ int iSrc = pSG->cSegsUsed; int iDst = pSG->cSegsAlloc; while (iSrc > 0) { iDst--; iSrc--; pSG->aSegs[iDst] = pSG->aSegs[iSrc]; } /* create small segments from the start. */ pSG->cSegsUsed = pSG->cSegsAlloc; iSrc = iDst; iDst = 0; while ( iDst < iSrc && iDst < pSG->cSegsAlloc) { pSG->aSegs[iDst].Phys = NIL_RTHCPHYS; pSG->aSegs[iDst].pv = pSG->aSegs[iSrc].pv; pSG->aSegs[iDst].cb = RT_MIN(pSG->aSegs[iSrc].cb, VBOXNETFLT_DARWIN_TEST_SEG_SIZE); if (pSG->aSegs[iDst].cb != pSG->aSegs[iSrc].cb) { pSG->aSegs[iSrc].cb -= pSG->aSegs[iDst].cb; pSG->aSegs[iSrc].pv = (uint8_t *)pSG->aSegs[iSrc].pv + pSG->aSegs[iDst].cb; } else if (++iSrc >= pSG->cSegsAlloc) { pSG->cSegsUsed = iDst + 1; break; } iDst++; } } #endif AssertMsg(!pvFrame, ("pvFrame=%p pMBuf=%p iSeg=%d\n", pvFrame, pMBuf, iSeg)); }
void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) { ifnet_t pIfNet = vboxNetFltDarwinRetainIfNet(pThis); if (pIfNet) { if (pThis->fDisablePromiscuous) { /* * Promiscuous mode should not be used (wireless), we just need to * make sure the interface is up. */ if (fActive) { u_int16_t fIf = ifnet_flags(pIfNet); if ((fIf & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) { ifnet_set_flags(pIfNet, IFF_UP, IFF_UP); ifnet_ioctl(pIfNet, 0, SIOCSIFFLAGS, NULL); } } } else { /* * This api is a bit weird, the best reference is the code. * * Also, we have a bit or race conditions wrt the maintenance of * host the interface promiscuity for vboxNetFltPortOsIsPromiscuous. */ unsigned const cPromiscBefore = VBOX_GET_PCOUNT(pIfNet); u_int16_t fIf; if (fActive) { Assert(!pThis->u.s.fSetPromiscuous); errno_t err = ENETDOWN; ASMAtomicWriteBool(&pThis->u.s.fNeedSetPromiscuous, true); /* * Try bring the interface up and running if it's down. */ fIf = ifnet_flags(pIfNet); if ((fIf & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) { err = ifnet_set_flags(pIfNet, IFF_UP, IFF_UP); errno_t err2 = ifnet_ioctl(pIfNet, 0, SIOCSIFFLAGS, NULL); if (!err) err = err2; fIf = ifnet_flags(pIfNet); } /* * Is it already up? If it isn't, leave it to the link event or * we'll upset if_pcount (as stated above, ifnet_set_promiscuous is weird). */ if ((fIf & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) { err = ifnet_set_promiscuous(pIfNet, 1); pThis->u.s.fSetPromiscuous = err == 0; if (!err) { ASMAtomicWriteBool(&pThis->u.s.fNeedSetPromiscuous, false); /* check if it actually worked, this stuff is not always behaving well. */ if (!(ifnet_flags(pIfNet) & IFF_PROMISC)) { err = ifnet_set_flags(pIfNet, IFF_PROMISC, IFF_PROMISC); if (!err) err = ifnet_ioctl(pIfNet, 0, SIOCSIFFLAGS, NULL); if (!err) Log(("vboxNetFlt: fixed IFF_PROMISC on %s (%d->%d)\n", pThis->szName, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet))); else Log(("VBoxNetFlt: failed to fix IFF_PROMISC on %s, err=%d (%d->%d)\n", pThis->szName, err, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet))); } } else Log(("VBoxNetFlt: ifnet_set_promiscuous -> err=%d grr! (%d->%d)\n", err, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet))); } else if (!err) Log(("VBoxNetFlt: Waiting for the link to come up... (%d->%d)\n", cPromiscBefore, VBOX_GET_PCOUNT(pIfNet))); if (err) LogRel(("VBoxNetFlt: Failed to put '%s' into promiscuous mode, err=%d (%d->%d)\n", pThis->szName, err, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet))); } else { ASMAtomicWriteBool(&pThis->u.s.fNeedSetPromiscuous, false); if (pThis->u.s.fSetPromiscuous) { errno_t err = ifnet_set_promiscuous(pIfNet, 0); AssertMsg(!err, ("%d\n", err)); NOREF(err); } pThis->u.s.fSetPromiscuous = false; fIf = ifnet_flags(pIfNet); Log(("VBoxNetFlt: fIf=%#x; %d->%d\n", fIf, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet))); } } vboxNetFltDarwinReleaseIfNet(pThis, pIfNet); } }
/** * Verifies a read request. * * @returns VBox status code. * @param pThis Disk integrity driver instance data. * @param paSeg Segment array of the containing the data buffers to verify. * @param cSeg Number of segments. * @param off Start offset. * @param cbWrite Number of bytes to verify. */ static int drvdiskintReadVerify(PDRVDISKINTEGRITY pThis, PCRTSGSEG paSeg, unsigned cSeg, uint64_t off, size_t cbRead) { int rc = VINF_SUCCESS; LogFlowFunc(("pThis=%#p paSeg=%#p cSeg=%u off=%llx cbRead=%u\n", pThis, paSeg, cSeg, off, cbRead)); Assert(off % 512 == 0); Assert(cbRead % 512 == 0); /* Compare read data */ size_t cbLeft = cbRead; RTFOFF offCurr = (RTFOFF)off; RTSGBUF SgBuf; RTSgBufInit(&SgBuf, paSeg, cSeg); while (cbLeft) { PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr); size_t cbRange = 0; bool fCmp = false; unsigned offSeg = 0; if (!pSeg) { /* Get next segment */ pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true); if (!pSeg) { /* No data in the tree for this read. Assume everything is ok. */ cbRange = cbLeft; } else if (offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key) cbRange = cbLeft; else cbRange = pSeg->Core.Key - offCurr; } else { fCmp = true; offSeg = offCurr - pSeg->Core.Key; cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr)); } if (fCmp) { RTSGSEG Seg; RTSGBUF SgBufCmp; size_t cbOff = 0; Seg.cbSeg = cbRange; Seg.pvSeg = pSeg->pbSeg + offSeg; RTSgBufInit(&SgBufCmp, &Seg, 1); if (RTSgBufCmpEx(&SgBuf, &SgBufCmp, cbRange, &cbOff, true)) { /* Corrupted disk, print I/O log entry of the last write which accessed this range. */ uint32_t cSector = (offSeg + cbOff) / 512; AssertMsg(cSector < pSeg->cIoLogEntries, ("Internal bug!\n")); RTMsgError("Corrupted disk at offset %llu (%u bytes in the current read buffer)!\n", offCurr + cbOff, cbOff); RTMsgError("Last write to this sector started at offset %llu with %u bytes (%u references to this log entry)\n", pSeg->apIoLog[cSector]->off, pSeg->apIoLog[cSector]->cbWrite, pSeg->apIoLog[cSector]->cRefs); RTAssertDebugBreak(); } } else RTSgBufAdvance(&SgBuf, cbRange); offCurr += cbRange; cbLeft -= cbRange; } return rc; }
/** * Record a successful write to the virtual disk. * * @returns VBox status code. * @param pThis Disk integrity driver instance data. * @param paSeg Segment array of the write to record. * @param cSeg Number of segments. * @param off Start offset. * @param cbWrite Number of bytes to record. */ static int drvdiskintWriteRecord(PDRVDISKINTEGRITY pThis, PCRTSGSEG paSeg, unsigned cSeg, uint64_t off, size_t cbWrite) { int rc = VINF_SUCCESS; LogFlowFunc(("pThis=%#p paSeg=%#p cSeg=%u off=%llx cbWrite=%u\n", pThis, paSeg, cSeg, off, cbWrite)); /* Update the segments */ size_t cbLeft = cbWrite; RTFOFF offCurr = (RTFOFF)off; RTSGBUF SgBuf; PIOLOGENT pIoLogEnt = (PIOLOGENT)RTMemAllocZ(sizeof(IOLOGENT)); if (!pIoLogEnt) return VERR_NO_MEMORY; pIoLogEnt->off = off; pIoLogEnt->cbWrite = cbWrite; pIoLogEnt->cRefs = 0; RTSgBufInit(&SgBuf, paSeg, cSeg); while (cbLeft) { PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr); size_t cbRange = 0; bool fSet = false; unsigned offSeg = 0; if (!pSeg) { /* Get next segment */ pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true); if ( !pSeg || offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key) cbRange = cbLeft; else cbRange = pSeg->Core.Key - offCurr; Assert(cbRange % 512 == 0); /* Create new segment */ pSeg = (PDRVDISKSEGMENT)RTMemAllocZ(RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbRange / 512])); if (pSeg) { pSeg->Core.Key = offCurr; pSeg->Core.KeyLast = offCurr + (RTFOFF)cbRange - 1; pSeg->cbSeg = cbRange; pSeg->pbSeg = (uint8_t *)RTMemAllocZ(cbRange); pSeg->cIoLogEntries = cbRange / 512; if (!pSeg->pbSeg) RTMemFree(pSeg); else { bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core); AssertMsg(fInserted, ("Bug!\n")); fSet = true; } } } else { fSet = true; offSeg = offCurr - pSeg->Core.Key; cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr)); } if (fSet) { AssertPtr(pSeg); size_t cbCopied = RTSgBufCopyToBuf(&SgBuf, pSeg->pbSeg + offSeg, cbRange); Assert(cbCopied == cbRange); /* Update the I/O log pointers */ Assert(offSeg % 512 == 0); Assert(cbRange % 512 == 0); while (offSeg < cbRange) { uint32_t uSector = offSeg / 512; PIOLOGENT pIoLogOld = NULL; AssertMsg(uSector < pSeg->cIoLogEntries, ("Internal bug!\n")); pIoLogOld = pSeg->apIoLog[uSector]; if (pIoLogOld) { pIoLogOld->cRefs--; if (!pIoLogOld->cRefs) RTMemFree(pIoLogOld); } pSeg->apIoLog[uSector] = pIoLogEnt; pIoLogEnt->cRefs++; offSeg += 512; } } else RTSgBufAdvance(&SgBuf, cbRange); offCurr += cbRange; cbLeft -= cbRange; } return rc; }
/** * Allocates a page from the page pool. * * @returns Pointer to allocated page(s). * @returns NULL on failure. * @param pPool Pointer to the page pool. * @thread The Emulation Thread. */ DECLINLINE(void *) mmR3PagePoolAlloc(PMMPAGEPOOL pPool) { VM_ASSERT_EMT(pPool->pVM); STAM_COUNTER_INC(&pPool->cAllocCalls); /* * Walk free list. */ if (pPool->pHeadFree) { PMMPAGESUBPOOL pSub = pPool->pHeadFree; /* decrement free count and unlink if no more free entries. */ if (!--pSub->cPagesFree) pPool->pHeadFree = pSub->pNextFree; #ifdef VBOX_WITH_STATISTICS pPool->cFreePages--; #endif /* find free spot in bitmap. */ #ifdef USE_INLINE_ASM_BIT_OPS const int iPage = ASMBitFirstClear(pSub->auBitmap, pSub->cPages); if (iPage >= 0) { Assert(!ASMBitTest(pSub->auBitmap, iPage)); ASMBitSet(pSub->auBitmap, iPage); return (uint8_t *)pSub->pvPages + PAGE_SIZE * iPage; } #else unsigned *pu = &pSub->auBitmap[0]; unsigned *puEnd = &pSub->auBitmap[pSub->cPages / (sizeof(pSub->auBitmap) * 8)]; while (pu < puEnd) { unsigned u; if ((u = *pu) != ~0U) { unsigned iBit = 0; unsigned uMask = 1; while (iBit < sizeof(pSub->auBitmap[0]) * 8) { if (!(u & uMask)) { *pu |= uMask; return (uint8_t *)pSub->pvPages + PAGE_SIZE * (iBit + ((uint8_t *)pu - (uint8_t *)&pSub->auBitmap[0]) * 8); } iBit++; uMask <<= 1; } STAM_COUNTER_INC(&pPool->cErrors); AssertMsgFailed(("how odd, expected to find a free bit in %#x, but didn't\n", u)); } /* next */ pu++; } #endif STAM_COUNTER_INC(&pPool->cErrors); #ifdef VBOX_WITH_STATISTICS pPool->cFreePages++; #endif AssertMsgFailed(("how strange, expected to find a free bit in %p, but didn't (%d pages supposed to be free!)\n", pSub, pSub->cPagesFree + 1)); } /* * Allocate new subpool. */ unsigned cPages = !pPool->fLow ? 128 : 32; PMMPAGESUBPOOL pSub; int rc = MMHyperAlloc(pPool->pVM, RT_OFFSETOF(MMPAGESUBPOOL, auBitmap[cPages / (sizeof(pSub->auBitmap[0]) * 8)]) + (sizeof(SUPPAGE) + sizeof(MMPPLOOKUPHCPHYS)) * cPages + sizeof(MMPPLOOKUPHCPTR), 0, MM_TAG_MM_PAGE, (void **)&pSub); if (RT_FAILURE(rc)) return NULL; PSUPPAGE paPhysPages = (PSUPPAGE)&pSub->auBitmap[cPages / (sizeof(pSub->auBitmap[0]) * 8)]; Assert((uintptr_t)paPhysPages >= (uintptr_t)&pSub->auBitmap[1]); if (!pPool->fLow) { rc = SUPR3PageAllocEx(cPages, 0 /* fFlags */, &pSub->pvPages, NULL, paPhysPages); if (RT_FAILURE(rc)) rc = VMSetError(pPool->pVM, rc, RT_SRC_POS, N_("Failed to lock host %zd bytes of memory (out of memory)"), (size_t)cPages << PAGE_SHIFT); } else rc = SUPR3LowAlloc(cPages, &pSub->pvPages, NULL, paPhysPages); if (RT_SUCCESS(rc)) { /* * Setup the sub structure and allocate the requested page. */ pSub->cPages = cPages; pSub->cPagesFree= cPages - 1; pSub->paPhysPages = paPhysPages; memset(pSub->auBitmap, 0, cPages / 8); /* allocate first page. */ pSub->auBitmap[0] |= 1; /* link into free chain. */ pSub->pNextFree = pPool->pHeadFree; pPool->pHeadFree= pSub; /* link into main chain. */ pSub->pNext = pPool->pHead; pPool->pHead = pSub; /* update pool statistics. */ pPool->cSubPools++; pPool->cPages += cPages; #ifdef VBOX_WITH_STATISTICS pPool->cFreePages += cPages - 1; #endif /* * Initialize the physical pages with backpointer to subpool. */ unsigned i = cPages; while (i-- > 0) { AssertMsg(paPhysPages[i].Phys && !(paPhysPages[i].Phys & PAGE_OFFSET_MASK), ("i=%d Phys=%d\n", i, paPhysPages[i].Phys)); paPhysPages[i].uReserved = (RTHCUINTPTR)pSub; } /* * Initialize the physical lookup record with backpointers to the physical pages. */ PMMPPLOOKUPHCPHYS paLookupPhys = (PMMPPLOOKUPHCPHYS)&paPhysPages[cPages]; i = cPages; while (i-- > 0) { paLookupPhys[i].pPhysPage = &paPhysPages[i]; paLookupPhys[i].Core.Key = paPhysPages[i].Phys; RTAvlHCPhysInsert(&pPool->pLookupPhys, &paLookupPhys[i].Core); } /* * And the one record for virtual memory lookup. */ PMMPPLOOKUPHCPTR pLookupVirt = (PMMPPLOOKUPHCPTR)&paLookupPhys[cPages]; pLookupVirt->pSubPool = pSub; pLookupVirt->Core.Key = pSub->pvPages; RTAvlPVInsert(&pPool->pLookupVirt, &pLookupVirt->Core); /* return allocated page (first). */ return pSub->pvPages; } MMHyperFree(pPool->pVM, pSub); STAM_COUNTER_INC(&pPool->cErrors); if (pPool->fLow) VMSetError(pPool->pVM, rc, RT_SRC_POS, N_("Failed to expand page pool for memory below 4GB. Current size: %d pages"), pPool->cPages); AssertMsgFailed(("Failed to expand pool%s. rc=%Rrc poolsize=%d\n", pPool->fLow ? " (<4GB)" : "", rc, pPool->cPages)); return NULL; }
/** * Allocates physical contiguous memory (below 4GB). * The allocation is page aligned and the content is undefined. * * @returns Pointer to the memory block. This is page aligned. * @param pPhys Where to store the physical address. * @param cb The allocation size in bytes. This is always * rounded up to PAGE_SIZE. */ RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb) { int cOrder; unsigned cPages; struct page *paPages; /* * validate input. */ Assert(VALID_PTR(pPhys)); Assert(cb > 0); /* * Allocate page pointer array. */ cb = RT_ALIGN_Z(cb, PAGE_SIZE); cPages = cb >> PAGE_SHIFT; cOrder = CalcPowerOf2Order(cPages); #if (defined(RT_ARCH_AMD64) || defined(CONFIG_X86_PAE)) && defined(GFP_DMA32) /* ZONE_DMA32: 0-4GB */ paPages = alloc_pages(GFP_DMA32 | __GFP_NOWARN, cOrder); if (!paPages) #endif #ifdef RT_ARCH_AMD64 /* ZONE_DMA; 0-16MB */ paPages = alloc_pages(GFP_DMA | __GFP_NOWARN, cOrder); #else /* ZONE_NORMAL: 0-896MB */ paPages = alloc_pages(GFP_USER | __GFP_NOWARN, cOrder); #endif if (paPages) { /* * Reserve the pages and mark them executable. */ unsigned iPage; for (iPage = 0; iPage < cPages; iPage++) { Assert(!PageHighMem(&paPages[iPage])); if (iPage + 1 < cPages) { AssertMsg( (uintptr_t)phys_to_virt(page_to_phys(&paPages[iPage])) + PAGE_SIZE == (uintptr_t)phys_to_virt(page_to_phys(&paPages[iPage + 1])) && page_to_phys(&paPages[iPage]) + PAGE_SIZE == page_to_phys(&paPages[iPage + 1]), ("iPage=%i cPages=%u [0]=%#llx,%p [1]=%#llx,%p\n", iPage, cPages, (long long)page_to_phys(&paPages[iPage]), phys_to_virt(page_to_phys(&paPages[iPage])), (long long)page_to_phys(&paPages[iPage + 1]), phys_to_virt(page_to_phys(&paPages[iPage + 1])) )); } SetPageReserved(&paPages[iPage]); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 20) /** @todo find the exact kernel where change_page_attr was introduced. */ MY_SET_PAGES_EXEC(&paPages[iPage], 1); #endif } *pPhys = page_to_phys(paPages); return phys_to_virt(page_to_phys(paPages)); } return NULL; }
bool UIMachineViewScale::event(QEvent *pEvent) { switch (pEvent->type()) { case VBoxDefs::ResizeEventType: { /* Some situations require framebuffer resize events to be ignored at all, * leaving machine-window, machine-view and framebuffer sizes preserved: */ if (uisession()->isGuestResizeIgnored()) return true; /* We are starting to perform machine-view resize, * we should temporary ignore other if they are trying to be: */ bool fWasMachineWindowResizeIgnored = isMachineWindowResizeIgnored(); setMachineWindowResizeIgnored(true); /* Get guest resize-event: */ UIResizeEvent *pResizeEvent = static_cast<UIResizeEvent*>(pEvent); /* Perform framebuffer resize: */ frameBuffer()->setScaledSize(size()); frameBuffer()->resizeEvent(pResizeEvent); /* Store the new size to prevent unwanted resize hints being sent back: */ storeConsoleSize(pResizeEvent->width(), pResizeEvent->height()); /* Let our toplevel widget calculate its sizeHint properly: */ QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest); #ifdef Q_WS_MAC machineLogic()->updateDockIconSize(screenId(), pResizeEvent->width(), pResizeEvent->height()); #endif /* Q_WS_MAC */ /* Report to the VM thread that we finished resizing: */ session().GetConsole().GetDisplay().ResizeCompleted(screenId()); /* We are finishing to perform machine-view resize: */ setMachineWindowResizeIgnored(fWasMachineWindowResizeIgnored); /* We also recalculate the desktop geometry if this is determined * automatically. In fact, we only need this on the first resize, * but it is done every time to keep the code simpler. */ calculateDesktopGeometry(); /* Emit a signal about guest was resized: */ emit resizeHintDone(); pEvent->accept(); return true; } case VBoxDefs::RepaintEventType: { UIRepaintEvent *pPaintEvent = static_cast<UIRepaintEvent*>(pEvent); QSize scaledSize = frameBuffer()->scaledSize(); double xRatio = (double)scaledSize.width() / frameBuffer()->width(); double yRatio = (double)scaledSize.height() / frameBuffer()->height(); AssertMsg(contentsX() == 0, ("This can't be, else notify Dsen!\n")); AssertMsg(contentsY() == 0, ("This can't be, else notify Dsen!\n")); /* Make sure we update always a bigger rectangle than requested to * catch all rounding errors. (use 1 time the ratio factor and * round down on top/left, but round up for the width/height) */ viewport()->update((int)(pPaintEvent->x() * xRatio) - ((int)xRatio) - 1, (int)(pPaintEvent->y() * yRatio) - ((int)yRatio) - 1, (int)(pPaintEvent->width() * xRatio) + ((int)xRatio + 2) * 2, (int)(pPaintEvent->height() * yRatio) + ((int)yRatio + 2) * 2); pEvent->accept(); return true; } default: break; } return UIMachineView::event(pEvent); }
void UIFrameBufferSDL::resizeEvent(UIResizeEvent *pEvent) { /* Check whether the guest resolution has not been changed. */ bool fSameResolutionRequested = (width() == pEvent->width() && height() == pEvent->height()); /* Check if the guest VRAM can be used as the source bitmap. */ bool bFallback = false; Uint32 Rmask = 0; Uint32 Gmask = 0; Uint32 Bmask = 0; if (pEvent->pixelFormat() == FramebufferPixelFormat_FOURCC_RGB) { switch (pEvent->bitsPerPixel()) { case 32: Rmask = 0x00FF0000; Gmask = 0x0000FF00; Bmask = 0x000000FF; break; case 24: Rmask = 0x00FF0000; Gmask = 0x0000FF00; Bmask = 0x000000FF; break; case 16: Rmask = 0xF800; Gmask = 0x07E0; Bmask = 0x001F; break; default: /* Unsupported format leads to the indirect buffer */ bFallback = true; break; } } else { /* Unsupported format leads to the indirect buffer */ bFallback = true; } m_width = pEvent->width(); m_height = pEvent->height(); /* Recreate the source surface. */ if (m_pSurfVRAM) { SDL_FreeSurface(m_pSurfVRAM); m_pSurfVRAM = NULL; } if (!bFallback) { /* It is OK to create the source surface from the guest VRAM. */ m_pSurfVRAM = SDL_CreateRGBSurfaceFrom(pEvent->VRAM(), pEvent->width(), pEvent->height(), pEvent->bitsPerPixel(), pEvent->bytesPerLine(), Rmask, Gmask, Bmask, 0); LogFlowFunc(("Created VRAM surface %p\n", m_pSurfVRAM)); if (m_pSurfVRAM == NULL) { bFallback = true; } } if (fSameResolutionRequested) { LogFlowFunc(("the same resolution requested, skipping the resize.\n")); return; } /* close SDL so we can init it again */ if (m_pScreen) { X11ScreenSaverSettingsSave(); SDL_QuitSubSystem(SDL_INIT_VIDEO); X11ScreenSaverSettingsRestore(); m_pScreen = NULL; } /* * initialize the SDL library, use its super hack to integrate it with our client window */ static char sdlHack[64]; LogFlowFunc(("Using client window 0x%08lX to initialize SDL\n", m_pMachineView->viewport()->winId())); /* Note: SDL_WINDOWID must be decimal (not hex) to work on Win32 */ sprintf(sdlHack, "SDL_WINDOWID=%lu", m_pMachineView->viewport()->winId()); putenv(sdlHack); X11ScreenSaverSettingsSave(); int rc = SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); X11ScreenSaverSettingsRestore(); AssertMsg(rc == 0, ("SDL initialization failed: %s\n", SDL_GetError())); NOREF(rc); #ifdef Q_WS_X11 /* undo signal redirections from SDL, it'd steal keyboard events from us! */ signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); #endif LogFlowFunc(("Setting SDL video mode to %d x %d\n", m_width, m_height)); /* Pixel format is RGB in any case */ m_uPixelFormat = FramebufferPixelFormat_FOURCC_RGB; m_pScreen = SDL_SetVideoMode(m_width, m_height, 0, SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL); AssertMsg(m_pScreen, ("SDL video mode could not be set!\n")); }
/** * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug. * * @returns VBox status code. * @param pThis The event semaphore. * @param fFlags See RTSemEventMultiWaitEx. * @param uTimeout See RTSemEventMultiWaitEx. * @param pSrcPos The source code position of the wait. */ static int rtR0SemEventMultiDarwinWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos) { /* * Validate input. */ AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); if (uTimeout != 0 || (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)) RT_ASSERT_PREEMPTIBLE(); rtR0SemEventMultiDarwinRetain(pThis); lck_spin_lock(pThis->pSpinlock); /* * Is the event already signalled or do we have to wait? */ int rc; uint32_t const fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen); if (fOrgStateAndGen & RTSEMEVENTMULTIDARWIN_STATE_MASK) rc = VINF_SUCCESS; else { /* * We have to wait. So, we'll need to convert the timeout and figure * out if it's indefinite or not. */ uint64_t uNsAbsTimeout = 1; if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE)) { if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000) ? uTimeout * UINT32_C(1000000) : UINT64_MAX; if (uTimeout == UINT64_MAX) fFlags |= RTSEMWAIT_FLAGS_INDEFINITE; else { uint64_t u64Now; if (fFlags & RTSEMWAIT_FLAGS_RELATIVE) { if (uTimeout != 0) { u64Now = RTTimeSystemNanoTS(); uNsAbsTimeout = u64Now + uTimeout; if (uNsAbsTimeout < u64Now) /* overflow */ fFlags |= RTSEMWAIT_FLAGS_INDEFINITE; } } else { uNsAbsTimeout = uTimeout; u64Now = RTTimeSystemNanoTS(); uTimeout = u64Now < uTimeout ? uTimeout - u64Now : 0; } } } if ( !(fFlags & RTSEMWAIT_FLAGS_INDEFINITE) && uTimeout == 0) { /* * Poll call, we already checked the condition above so no need to * wait for anything. */ rc = VERR_TIMEOUT; } else { for (;;) { /* * Do the actual waiting. */ ASMAtomicWriteBool(&pThis->fHaveBlockedThreads, true); wait_interrupt_t fInterruptible = fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE ? THREAD_ABORTSAFE : THREAD_UNINT; wait_result_t rcWait; if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE) rcWait = lck_spin_sleep(pThis->pSpinlock, LCK_SLEEP_DEFAULT, (event_t)pThis, fInterruptible); else { uint64_t u64AbsTime; nanoseconds_to_absolutetime(uNsAbsTimeout, &u64AbsTime); rcWait = lck_spin_sleep_deadline(pThis->pSpinlock, LCK_SLEEP_DEFAULT, (event_t)pThis, fInterruptible, u64AbsTime); } /* * Deal with the wait result. */ if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC)) { switch (rcWait) { case THREAD_AWAKENED: if (RT_LIKELY(ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)) rc = VINF_SUCCESS; else if (fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE) rc = VERR_INTERRUPTED; else continue; /* Seen this happen after fork/exec/something. */ break; case THREAD_TIMED_OUT: Assert(!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE)); rc = VERR_TIMEOUT; break; case THREAD_INTERRUPTED: Assert(fInterruptible != THREAD_UNINT); rc = VERR_INTERRUPTED; break; case THREAD_RESTART: AssertMsg(pThis->u32Magic == ~RTSEMEVENTMULTI_MAGIC, ("%#x\n", pThis->u32Magic)); rc = VERR_SEM_DESTROYED; break; default: AssertMsgFailed(("rcWait=%d\n", rcWait)); rc = VERR_INTERNAL_ERROR_3; break; } } else rc = VERR_SEM_DESTROYED; break; } } } lck_spin_unlock(pThis->pSpinlock); rtR0SemEventMultiDarwinRelease(pThis); return rc; }
void CAI_ScriptConditions::EvaluationThink() { if ( m_fDisabled == true ) return; int iActorsDone = 0; for ( int i = 0; i < m_ElementList.Count(); ) { CAI_ScriptConditionsElement *pConditionElement = &m_ElementList[i]; if ( pConditionElement == NULL ) { i++; continue; } CBaseEntity *pActor = pConditionElement->GetActor(); CBaseEntity *pActivator = this; #ifdef HL2_EPISODIC if ( pActor && HasSpawnFlags( SF_ACTOR_AS_ACTIVATOR ) ) { pActivator = pActor; } #endif AssertMsg( !m_fDisabled, ("Violated invariant between CAI_ScriptConditions disabled state and think func setting") ); if ( m_Actor != NULL_STRING && !pActor ) { if ( m_ElementList.Count() == 1 ) { DevMsg( "Warning: Active AI script conditions associated with an non-existant or destroyed NPC\n" ); m_NoValidActors.FireOutput( this, this, 0 ); } iActorsDone++; m_ElementList.Remove( i ); continue; } i++; if( m_flMinTimeout > 0 && pConditionElement->GetTimeOut()->Expired() ) { ScrCondDbgMsg( ( "%s firing output OnConditionsTimeout (%f seconds)\n", STRING( GetEntityName() ), pConditionElement->GetTimeOut()->GetInterval() ) ); iActorsDone++; m_OnConditionsTimeout.FireOutput( pActivator, this ); continue; } bool result = true; const int nEvaluators = sizeof( gm_Evaluators ) / sizeof( gm_Evaluators[0] ); EvalArgs_t args = { pActor, GetPlayer(), m_hTarget.Get() }; for ( int i = 0; i < nEvaluators; ++i ) { if ( !(this->*gm_Evaluators[i].pfnEvaluator)( args ) ) { pConditionElement->GetTimer()->Reset(); result = false; ScrCondDbgMsg( ( "%s failed on: %s\n", GetDebugName(), gm_Evaluators[ i ].pszName ) ); break; } } if ( result ) { ScrCondDbgMsg( ( "%s waiting... %f\n", GetDebugName(), pConditionElement->GetTimer()->GetRemaining() ) ); } if ( result && pConditionElement->GetTimer()->Expired() ) { ScrCondDbgMsg( ( "%s firing output OnConditionsSatisfied\n", GetDebugName() ) ); // Default behavior for now, provide worldcraft option later. iActorsDone++; m_OnConditionsSatisfied.FireOutput( pActivator, this ); } } //All done! if ( iActorsDone == m_ElementList.Count() ) { Disable(); m_ElementList.Purge(); } SetThinkTime(); }
int main() { RTR3InitExeNoArguments(0); RTPrintf("tstRand: TESTING...\n"); /* * Do some smoke tests first? */ /** @todo RTRand smoke testing. */ #if 1 /* * Test distribution. */ #if 1 /* unsigned 32-bit */ static const struct { uint32_t u32First; uint32_t u32Last; } s_aU32Tests[] = { { 0, UINT32_MAX }, { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, { 0, UINT32_MAX / 2 }, { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, { 0, TST_RAND_SAMPLE_RANGES - 1 }, { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU32Tests); iTest++) { uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; uint32_t const uFirst = s_aU32Tests[iTest].u32First; uint32_t const uLast = s_aU32Tests[iTest].u32Last; uint32_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); uint32_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; RTPrintf("tstRand: TESTING RTRandU32Ex(%#RX32, %#RX32) distribution... [div=%#RX32 range=%#RX32]\n", uFirst, uLast, uDivisor, uRange); for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) { uint32_t uRand = RTRandU32Ex(uFirst, uLast); CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX32 %#RX32\n", uRand, uFirst)); CHECK_EXPR_MSG(uRand <= uLast, ("%#RX32 %#RX32\n", uRand, uLast)); uint32_t off = uRand - uFirst; acHits[off / uDivisor]++; } tstRandCheckDist(acHits, iTest); } #endif #if 1 /* unsigned 64-bit */ static const struct { uint64_t u64First; uint64_t u64Last; } s_aU64Tests[] = { { 0, UINT64_MAX }, { 0, UINT64_MAX / 2 + UINT64_MAX / 4 }, { 0, UINT64_MAX / 2 + UINT64_MAX / 8 }, { 0, UINT64_MAX / 2 + UINT64_MAX / 16 }, { 0, UINT64_MAX / 2 + UINT64_MAX / 64 }, { 0, UINT64_MAX / 2 }, { UINT64_MAX / 4, UINT64_MAX / 4 * 3 }, { 0, UINT32_MAX }, { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, { 0, UINT32_MAX / 2 }, { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, { 0, TST_RAND_SAMPLE_RANGES - 1 }, { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU64Tests); iTest++) { uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; uint64_t const uFirst = s_aU64Tests[iTest].u64First; uint64_t const uLast = s_aU64Tests[iTest].u64Last; uint64_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); uint64_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; RTPrintf("tstRand: TESTING RTRandU64Ex(%#RX64, %#RX64) distribution... [div=%#RX64 range=%#RX64]\n", uFirst, uLast, uDivisor, uRange); for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) { uint64_t uRand = RTRandU64Ex(uFirst, uLast); CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX64 %#RX64\n", uRand, uFirst)); CHECK_EXPR_MSG(uRand <= uLast, ("%#RX64 %#RX64\n", uRand, uLast)); uint64_t off = uRand - uFirst; acHits[off / uDivisor]++; } tstRandCheckDist(acHits, iTest); } #endif #if 1 /* signed 32-bit */ static const struct { int32_t i32First; int32_t i32Last; } s_aS32Tests[] = { { -429496729, 429496729 }, { INT32_MIN, INT32_MAX }, { INT32_MIN, INT32_MAX / 2 }, { -0x20000000, INT32_MAX }, { -0x10000000, INT32_MAX }, { -0x08000000, INT32_MAX }, { -0x00800000, INT32_MAX }, { -0x00080000, INT32_MAX }, { -0x00008000, INT32_MAX }, { -0x00000800, INT32_MAX }, { 2, INT32_MAX / 2 }, { 4000000, INT32_MAX / 2 }, { -4000000, INT32_MAX / 2 }, { INT32_MIN / 2, INT32_MAX / 2 }, { INT32_MIN / 3, INT32_MAX / 2 }, { INT32_MIN / 3, INT32_MAX / 3 }, { INT32_MIN / 3, INT32_MAX / 4 }, { INT32_MIN / 4, INT32_MAX / 4 }, { INT32_MIN / 5, INT32_MAX / 5 }, { INT32_MIN / 6, INT32_MAX / 6 }, { INT32_MIN / 7, INT32_MAX / 6 }, { INT32_MIN / 7, INT32_MAX / 7 }, { INT32_MIN / 7, INT32_MAX / 8 }, { INT32_MIN / 8, INT32_MAX / 8 }, { INT32_MIN / 9, INT32_MAX / 9 }, { INT32_MIN / 9, INT32_MAX / 12 }, { INT32_MIN / 12, INT32_MAX / 12 }, { 0, TST_RAND_SAMPLE_RANGES - 1 }, { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 }, }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS32Tests); iTest++) { uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; int32_t const iFirst = s_aS32Tests[iTest].i32First; int32_t const iLast = s_aS32Tests[iTest].i32Last; uint32_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); uint32_t const uDivisor = (uRange ? uRange : UINT32_MAX) / TST_RAND_SAMPLE_RANGES + 1; RTPrintf("tstRand: TESTING RTRandS32Ex(%#RI32, %#RI32) distribution... [div=%#RX32 range=%#RX32]\n", iFirst, iLast, uDivisor, uRange); for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) { int32_t iRand = RTRandS32Ex(iFirst, iLast); CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI32 %#RI32\n", iRand, iFirst)); CHECK_EXPR_MSG(iRand <= iLast, ("%#RI32 %#RI32\n", iRand, iLast)); uint32_t off = iRand - iFirst; acHits[off / uDivisor]++; } tstRandCheckDist(acHits, iTest); } #endif #if 1 /* signed 64-bit */ static const struct { int64_t i64First; int64_t i64Last; } s_aS64Tests[] = { { INT64_MIN, INT64_MAX }, { INT64_MIN, INT64_MAX / 2 }, { INT64_MIN / 2, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 4, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 8, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 16, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 }, { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 + INT64_MAX / 64 }, { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 64 }, { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 8 }, { INT64_MIN / 2, INT64_MAX / 2 - INT64_MAX / 8 }, { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 4 }, { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 8 }, { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 - INT64_MAX / 8 }, { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 8 }, { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 16 }, { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 16 }, { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 32 }, { INT64_MIN / 2 - INT64_MIN / 64, INT64_MAX / 2 - INT64_MAX / 64 }, { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 }, { INT64_MIN / 4, INT64_MAX / 4 }, { INT64_MIN / 5, INT64_MAX / 5 }, { INT64_MIN / 6, INT64_MAX / 6 }, { INT64_MIN / 7, INT64_MAX / 7 }, { INT64_MIN / 8, INT64_MAX / 8 }, { INT32_MIN, INT32_MAX }, { INT32_MIN, INT32_MAX / 2 }, { -0x20000000, INT32_MAX }, { -0x10000000, INT32_MAX }, { -0x7f000000, INT32_MAX }, { -0x08000000, INT32_MAX }, { -0x00800000, INT32_MAX }, { -0x00080000, INT32_MAX }, { -0x00008000, INT32_MAX }, { 2, INT32_MAX / 2 }, { 4000000, INT32_MAX / 2 }, { -4000000, INT32_MAX / 2 }, { INT32_MIN / 2, INT32_MAX / 2 }, { 0, TST_RAND_SAMPLE_RANGES - 1 }, { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 } }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS64Tests); iTest++) { uint32_t acHits[TST_RAND_SAMPLE_RANGES] = {0}; int64_t const iFirst = s_aS64Tests[iTest].i64First; int64_t const iLast = s_aS64Tests[iTest].i64Last; uint64_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); uint64_t const uDivisor = (uRange ? uRange : UINT64_MAX) / TST_RAND_SAMPLE_RANGES + 1; RTPrintf("tstRand: TESTING RTRandS64Ex(%#RI64, %#RI64) distribution... [div=%#RX64 range=%#016RX64]\n", iFirst, iLast, uDivisor, uRange); for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) { int64_t iRand = RTRandS64Ex(iFirst, iLast); CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI64 %#RI64\n", iRand, iFirst)); CHECK_EXPR_MSG(iRand <= iLast, ("%#RI64 %#RI64\n", iRand, iLast)); uint64_t off = iRand - iFirst; acHits[off / uDivisor]++; } tstRandCheckDist(acHits, iTest); } #endif #endif /* Testing RTRand */ #if 1 /* * Test the various random generators. */ RTPrintf("tstRand: TESTING RTRandAdvCreateParkerMiller\n"); RTRAND hRand; int rc = RTRandAdvCreateParkMiller(&hRand); CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); if (RT_SUCCESS(rc)) if (tstRandAdv(hRand)) return 1; #endif /* Testing RTRandAdv */ /* * Summary. */ if (!g_cErrors) RTPrintf("tstRand: SUCCESS\n"); else RTPrintf("tstRand: FAILED - %d errors\n", g_cErrors); return !!g_cErrors; }
JavascriptSymbolObject* JavascriptSymbolObject::FromVar(Js::Var aValue) { AssertMsg(Is(aValue), "Ensure var is actually a 'JavascriptSymbolObject'"); return static_cast<JavascriptSymbolObject *>(RecyclableObject::FromVar(aValue)); }
RT_C_DECLS_END /** * Exits the trap, called when exiting a trap handler. * * Will reset the trap if it's not a guest trap or the trap * is already handled. Will process resume guest FFs. * * @returns rc, can be adjusted if its VINF_SUCCESS or something really bad * happened. * @param pVM Pointer to the VM. * @param pVCpu Pointer to the VMCPU. * @param rc The VBox status code to return. * @param pRegFrame Pointer to the register frame for the trap. * * @remarks This must not be used for hypervisor traps, only guest traps. */ static int trpmGCExitTrap(PVM pVM, PVMCPU pVCpu, int rc, PCPUMCTXCORE pRegFrame) { uint32_t uOldActiveVector = pVCpu->trpm.s.uActiveVector; NOREF(uOldActiveVector); /* Reset trap? */ if ( rc != VINF_EM_RAW_GUEST_TRAP && rc != VINF_EM_RAW_RING_SWITCH_INT) pVCpu->trpm.s.uActiveVector = UINT32_MAX; #ifdef VBOX_HIGH_RES_TIMERS_HACK /* * We should poll the timers occasionally. * We must *NOT* do this too frequently as it adds a significant overhead * and it'll kill us if the trap load is high. (See @bugref{1354}.) * (The heuristic is not very intelligent, we should really check trap * frequency etc. here, but alas, we lack any such information atm.) */ static unsigned s_iTimerPoll = 0; if (rc == VINF_SUCCESS) { if (!(++s_iTimerPoll & 0xf)) { TMTimerPollVoid(pVM, pVCpu); Log2(("TMTimerPoll at %08RX32 - VM_FF_TM_VIRTUAL_SYNC=%d VM_FF_TM_VIRTUAL_SYNC=%d\n", pRegFrame->eip, VM_FF_ISPENDING(pVM, VM_FF_TM_VIRTUAL_SYNC), VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_TIMER))); } } else s_iTimerPoll = 0; #endif /* Clear pending inhibit interrupt state if required. (necessary for dispatching interrupts later on) */ if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)) { Log2(("VM_FF_INHIBIT_INTERRUPTS at %08RX32 successor %RGv\n", pRegFrame->eip, EMGetInhibitInterruptsPC(pVCpu))); if (pRegFrame->eip != EMGetInhibitInterruptsPC(pVCpu)) { /** @note we intentionally don't clear VM_FF_INHIBIT_INTERRUPTS here if the eip is the same as the inhibited instr address. * Before we are able to execute this instruction in raw mode (iret to guest code) an external interrupt might * force a world switch again. Possibly allowing a guest interrupt to be dispatched in the process. This could * break the guest. Sounds very unlikely, but such timing sensitive problem are not as rare as you might think. */ VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS); } } /* * Pending resume-guest-FF? * Or pending (A)PIC interrupt? Windows XP will crash if we delay APIC interrupts. */ if ( rc == VINF_SUCCESS && ( VM_FF_ISPENDING(pVM, VM_FF_TM_VIRTUAL_SYNC | VM_FF_REQUEST | VM_FF_PGM_NO_MEMORY | VM_FF_PDM_DMA) || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_TIMER | VMCPU_FF_TO_R3 | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_REQUEST | VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_PDM_CRITSECT | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_SELM_SYNC_TSS ) ) ) { /* The out of memory condition naturally outranks the others. */ if (RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))) rc = VINF_EM_NO_MEMORY; /* Pending Ring-3 action. */ else if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_TO_R3 | VMCPU_FF_PDM_CRITSECT)) { VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3); rc = VINF_EM_RAW_TO_R3; } /* Pending timer action. */ else if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_TIMER)) rc = VINF_EM_RAW_TIMER_PENDING; /* The Virtual Sync clock has stopped. */ else if (VM_FF_ISPENDING(pVM, VM_FF_TM_VIRTUAL_SYNC)) rc = VINF_EM_RAW_TO_R3; /* DMA work pending? */ else if (VM_FF_ISPENDING(pVM, VM_FF_PDM_DMA)) rc = VINF_EM_RAW_TO_R3; /* Pending request packets might contain actions that need immediate attention, such as pending hardware interrupts. */ else if ( VM_FF_ISPENDING(pVM, VM_FF_REQUEST) || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_REQUEST)) rc = VINF_EM_PENDING_REQUEST; /* Pending GDT/LDT/TSS sync. */ else if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_SELM_SYNC_TSS)) rc = VINF_SELM_SYNC_GDT; /* Pending interrupt: dispatch it. */ else if ( VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC) && !VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS) && PATMAreInterruptsEnabledByCtxCore(pVM, pRegFrame) ) { uint8_t u8Interrupt; rc = PDMGetInterrupt(pVCpu, &u8Interrupt); Log(("trpmGCExitTrap: u8Interrupt=%d (%#x) rc=%Rrc\n", u8Interrupt, u8Interrupt, rc)); AssertFatalMsgRC(rc, ("PDMGetInterrupt failed with %Rrc\n", rc)); rc = TRPMForwardTrap(pVCpu, pRegFrame, (uint32_t)u8Interrupt, 0, TRPM_TRAP_NO_ERRORCODE, TRPM_HARDWARE_INT, uOldActiveVector); /* can't return if successful */ Assert(rc != VINF_SUCCESS); /* Stop the profile counter that was started in TRPMGCHandlersA.asm */ Assert(uOldActiveVector <= 16); STAM_PROFILE_ADV_STOP(&pVM->trpm.s.aStatGCTraps[uOldActiveVector], a); /* Assert the trap and go to the recompiler to dispatch it. */ TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT); STAM_PROFILE_ADV_START(&pVM->trpm.s.aStatGCTraps[uOldActiveVector], a); rc = VINF_EM_RAW_INTERRUPT_PENDING; } /* * Try sync CR3? */ else if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL)) { #if 1 PGMRZDynMapReleaseAutoSet(pVCpu); PGMRZDynMapStartAutoSet(pVCpu); rc = PGMSyncCR3(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR3(pVCpu), CPUMGetGuestCR4(pVCpu), VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3)); #else rc = VINF_PGM_SYNC_CR3; #endif } } AssertMsg( rc != VINF_SUCCESS || ( pRegFrame->eflags.Bits.u1IF && ( pRegFrame->eflags.Bits.u2IOPL < (unsigned)(pRegFrame->ss.Sel & X86_SEL_RPL) || pRegFrame->eflags.Bits.u1VM)) , ("rc=%Rrc\neflags=%RX32 ss=%RTsel IOPL=%d\n", rc, pRegFrame->eflags.u32, pRegFrame->ss.Sel, pRegFrame->eflags.Bits.u2IOPL)); PGMRZDynMapReleaseAutoSet(pVCpu); return rc; }
DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType) { /* * Convert the priority type to scheduling policies. * (This is really just guess work.) */ bool fSetExtended = false; thread_extended_policy Extended = { true }; bool fSetTimeContstraint = false; thread_time_constraint_policy TimeConstraint = { 0, 0, 0, true }; thread_precedence_policy Precedence = { 0 }; switch (enmType) { case RTTHREADTYPE_INFREQUENT_POLLER: Precedence.importance = 1; break; case RTTHREADTYPE_EMULATION: Precedence.importance = 30; break; case RTTHREADTYPE_DEFAULT: Precedence.importance = 31; break; case RTTHREADTYPE_MSG_PUMP: Precedence.importance = 34; break; case RTTHREADTYPE_IO: Precedence.importance = 98; break; case RTTHREADTYPE_TIMER: Precedence.importance = 0x7fffffff; fSetExtended = true; Extended.timeshare = FALSE; fSetTimeContstraint = true; TimeConstraint.period = 0; /* not really true for a real timer thread, but we've really no idea. */ TimeConstraint.computation = rtDarwinAbsTimeFromNano(100000); /* 100 us*/ TimeConstraint.constraint = rtDarwinAbsTimeFromNano(500000); /* 500 us */ TimeConstraint.preemptible = FALSE; break; default: AssertMsgFailed(("enmType=%d\n", enmType)); return VERR_INVALID_PARAMETER; } RT_ASSERT_INTS_ON(); /* * Do the actual modification. */ kern_return_t kr = thread_policy_set((thread_t)pThread->Core.Key, THREAD_PRECEDENCE_POLICY, (thread_policy_t)&Precedence, THREAD_PRECEDENCE_POLICY_COUNT); AssertMsg(kr == KERN_SUCCESS, ("%rc\n", kr)); NOREF(kr); if (fSetExtended) { kr = thread_policy_set((thread_t)pThread->Core.Key, THREAD_EXTENDED_POLICY, (thread_policy_t)&Extended, THREAD_EXTENDED_POLICY_COUNT); AssertMsg(kr == KERN_SUCCESS, ("%rc\n", kr)); } if (fSetTimeContstraint) { kr = thread_policy_set((thread_t)pThread->Core.Key, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&TimeConstraint, THREAD_TIME_CONSTRAINT_POLICY_COUNT); AssertMsg(kr == KERN_SUCCESS, ("%rc\n", kr)); } return VINF_SUCCESS; /* ignore any errors for now */ }
void InitDeferredRTs( bool bInitial ) { if ( !bInitial ) materials->ReEnableRenderTargetAllocation_IRealizeIfICallThisAllTexturesWillBeUnloadedAndLoadTimeWillSufferHorribly(); // HAHAHAHA. No. int screen_w, screen_h; int dummy = 128; materials->GetBackBufferDimensions( screen_w, screen_h ); const ImageFormat fmt_gbuffer0 = #if DEFCFG_LIGHTCTRL_PACKING IMAGE_FORMAT_RGBA8888; #else IMAGE_FORMAT_RGB888; #endif #if !DEFCFG_LIGHTCTRL_PACKING const ImageFormat fmt_gbuffer2 = IMAGE_FORMAT_RGBA8888; #endif #if DEFCFG_DEFERRED_SHADING == 1 const ImageFormat fmt_gbuffer2 = IMAGE_FORMAT_RGBA8888; const ImageFormat fmt_gbuffer3 = IMAGE_FORMAT_RGB888; #endif const ImageFormat fmt_gbuffer1 = IMAGE_FORMAT_R32F; const ImageFormat fmt_lightAccum = #if DEFCFG_LIGHTACCUM_COMPRESSED IMAGE_FORMAT_RGBA8888; #else IMAGE_FORMAT_RGBA16161616F; #endif const ImageFormat fmt_volumAccum = IMAGE_FORMAT_RGB888; const ImageFormat fmt_projVGUI = IMAGE_FORMAT_RGB888; const bool bShadowUseColor = #ifdef SHADOWMAPPING_USE_COLOR true; #else false; #endif const ImageFormat fmt_depth = GetDeferredManager()->GetShadowDepthFormat(); const ImageFormat fmt_depthColor = bShadowUseColor ? IMAGE_FORMAT_R32F : g_pMaterialSystemHardwareConfig->GetNullTextureFormat(); const ImageFormat fmt_radAlbedo = IMAGE_FORMAT_RGB888; const ImageFormat fmt_radNormal = IMAGE_FORMAT_RGB888; const ImageFormat fmt_radBuffer = IMAGE_FORMAT_RGB888; if ( fmt_depth == IMAGE_FORMAT_D16_SHADOW ) g_flDepthScalar = pow( 2.0, 16 ); else if ( fmt_depth == IMAGE_FORMAT_D24X8_SHADOW ) g_flDepthScalar = pow( 2.0, 24 ); AssertMsg( fmt_depth == IMAGE_FORMAT_D16_SHADOW || fmt_depth == IMAGE_FORMAT_D24X8_SHADOW, "Unexpected depth format" ); unsigned int gbufferFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_RENDERTARGET | TEXTUREFLAGS_POINTSAMPLE; unsigned int lightAccumFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_RENDERTARGET | TEXTUREFLAGS_POINTSAMPLE; unsigned int volumAccumFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_RENDERTARGET; unsigned int depthFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_RENDERTARGET; unsigned int shadowColorFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_RENDERTARGET | TEXTUREFLAGS_POINTSAMPLE; unsigned int projVGUIFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_RENDERTARGET; unsigned int radAlbedoNormalFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_RENDERTARGET | TEXTUREFLAGS_POINTSAMPLE; unsigned int radBufferFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_RENDERTARGET; unsigned int radNormalFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_RENDERTARGET | TEXTUREFLAGS_POINTSAMPLE; materials->BeginRenderTargetAllocation(); shadowData_general_t generalShadowData; if ( bInitial ) { g_tex_Normals.Init( materials->CreateNamedRenderTargetTextureEx2( DEFRTNAME_GBUFFER0, dummy, dummy, RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP, fmt_gbuffer0, #if DEFCFG_DEFERRED_SHADING == 1 MATERIAL_RT_DEPTH_NONE, #else MATERIAL_RT_DEPTH_SHARED, #endif gbufferFlags, 0 ) ); g_tex_Depth.Init( materials->CreateNamedRenderTargetTextureEx2( DEFRTNAME_GBUFFER1, dummy, dummy, RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP, fmt_gbuffer1, MATERIAL_RT_DEPTH_NONE, gbufferFlags, 0 ) ); #if ( DEFCFG_LIGHTCTRL_PACKING == 0 ) g_tex_LightCtrl.Init( materials->CreateNamedRenderTargetTextureEx2( DEFRTNAME_GBUFFER2, dummy, dummy, RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP, fmt_gbuffer2, MATERIAL_RT_DEPTH_NONE, gbufferFlags, 0 ) ); #elif DEFCFG_DEFERRED_SHADING == 1 g_tex_Albedo.Init( materials->CreateNamedRenderTargetTextureEx2( DEFRTNAME_GBUFFER2, dummy, dummy, RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP, fmt_gbuffer2, MATERIAL_RT_DEPTH_SHARED, gbufferFlags, 0 ) ); g_tex_Specular.Init( materials->CreateNamedRenderTargetTextureEx2( DEFRTNAME_GBUFFER3, dummy, dummy, RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP, fmt_gbuffer3, MATERIAL_RT_DEPTH_NONE, gbufferFlags, 0 ) ); #endif g_tex_Lightaccum.Init( materials->CreateNamedRenderTargetTextureEx2( DEFRTNAME_LIGHTACCUM, dummy, dummy, RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP, fmt_lightAccum, MATERIAL_RT_DEPTH_NONE, lightAccumFlags, 0 ) ); for ( int i = 0; i < 2; i++ ) g_tex_VolumetricsBuffer[ i ].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_VOLUMACCUM, i ), dummy, dummy, RT_SIZE_HDR, fmt_volumAccum, MATERIAL_RT_DEPTH_NONE, volumAccumFlags, 0 ) ); g_tex_VolumePrepass.Init( materials->CreateNamedRenderTargetTextureEx2( DEFRTNAME_VOLUMPREPASS, dummy, dummy, RT_SIZE_HDR, fmt_gbuffer1, MATERIAL_RT_DEPTH_NONE, gbufferFlags, 0 ) ); for ( int i = 0; i < MAX_SHADOW_ORTHO; i++ ) { #if CSM_USE_COMPOSITED_TARGET int iResolution_x = CSM_COMP_RES_X; int iResolution_y = CSM_COMP_RES_Y; #else const cascade_t &c = GetCascadeInfo( i ); int iResolution_x = c.iResolution; int iResolution_y = c.iResolution; #endif g_tex_ShadowDepth_Ortho[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWDEPTH_ORTHO, i ), iResolution_x, iResolution_y, RT_SIZE_NO_CHANGE, fmt_depth, MATERIAL_RT_DEPTH_NONE, depthFlags, 0 ) ); g_tex_ShadowColor_Ortho[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWCOLOR_ORTHO, i ), iResolution_x, iResolution_y, RT_SIZE_NO_CHANGE, fmt_depthColor, MATERIAL_RT_DEPTH_NONE, shadowColorFlags, 0 ) ); #if DEFCFG_ENABLE_RADIOSITY g_tex_ShadowRad_Albedo_Ortho[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWRAD_ALBEDO_ORTHO, i ), iResolution_x, iResolution_y, RT_SIZE_NO_CHANGE, fmt_radAlbedo, MATERIAL_RT_DEPTH_NONE, radAlbedoNormalFlags, 0 ) ); g_tex_ShadowRad_Normal_Ortho[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWRAD_NORMAL_ORTHO, i ), iResolution_x, iResolution_y, RT_SIZE_NO_CHANGE, fmt_radNormal, MATERIAL_RT_DEPTH_NONE, radAlbedoNormalFlags, 0 ) ); #endif Assert( iResolution_y == g_tex_ShadowDepth_Ortho[i]->GetActualHeight() ); Assert( iResolution_y == g_tex_ShadowColor_Ortho[i]->GetActualHeight() ); Assert( iResolution_x == g_tex_ShadowDepth_Ortho[i]->GetActualWidth() ); Assert( iResolution_x == g_tex_ShadowColor_Ortho[i]->GetActualWidth() ); } for ( int i = 0; i < NUM_PROJECTABLE_VGUI; i++ ) { g_tex_ProjectableVGUI[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_PROJECTABLE_VGUI, i ), PROJECTABLE_VGUI_RES, PROJECTABLE_VGUI_RES, RT_SIZE_NO_CHANGE, fmt_projVGUI, MATERIAL_RT_DEPTH_NONE, projVGUIFlags, 0 ) ); } #if DEFCFG_ENABLE_RADIOSITY for ( int i = 0; i < 2; i++ ) { g_tex_RadiosityBuffer[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_RADIOSITY_BUFFER, i ), RADIOSITY_BUFFER_RES_X, RADIOSITY_BUFFER_RES_Y, RT_SIZE_NO_CHANGE, fmt_radBuffer, MATERIAL_RT_DEPTH_NONE, radBufferFlags, 0 ) ); g_tex_RadiosityNormal[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_RADIOSITY_NORMAL, i ), RADIOSITY_BUFFER_RES_X, RADIOSITY_BUFFER_RES_Y, RT_SIZE_NO_CHANGE, fmt_radNormal, MATERIAL_RT_DEPTH_NONE, radNormalFlags, 0 ) ); } #endif } for ( int i = 0; i < MAX_SHADOW_PROJ; i++ ) { int res = GetShadowResolution_Spot(); generalShadowData.iPROJ_Res = res; bool bFirst = i == 0; if ( !bShadowUseColor || bFirst ) g_tex_ShadowDepth_Proj[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWDEPTH_PROJ, i ), res, res, RT_SIZE_NO_CHANGE, fmt_depth, MATERIAL_RT_DEPTH_NONE, depthFlags, 0 ) ); else g_tex_ShadowDepth_Proj[i].Init( g_tex_ShadowDepth_Proj[0] ); if ( bShadowUseColor || bFirst ) g_tex_ShadowColor_Proj[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWCOLOR_PROJ, i ), res, res, RT_SIZE_NO_CHANGE, fmt_depthColor, MATERIAL_RT_DEPTH_NONE, shadowColorFlags, 0 ) ); else g_tex_ShadowColor_Proj[i].Init( g_tex_ShadowColor_Proj[0] ); Assert( res == g_tex_ShadowDepth_Proj[i]->GetActualHeight() ); Assert( res == g_tex_ShadowColor_Proj[i]->GetActualHeight() ); Assert( res == g_tex_ShadowDepth_Proj[i]->GetActualWidth() ); Assert( res == g_tex_ShadowColor_Proj[i]->GetActualWidth() ); #if DEFCFG_ADAPTIVE_SHADOWMAP_LOD res = GetShadowResolution_Spot_LOD1(); generalShadowData.iPROJ_Res_LOD1 = res; if ( !bShadowUseColor || bFirst ) g_tex_ShadowDepth_Proj_LOD1[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWDEPTH_PROJ_LOD1, i ), res, res, RT_SIZE_NO_CHANGE, fmt_depth, MATERIAL_RT_DEPTH_NONE, depthFlags, 0 ) ); else g_tex_ShadowDepth_Proj_LOD1[i].Init( g_tex_ShadowDepth_Proj_LOD1[0] ); if ( bShadowUseColor || bFirst ) g_tex_ShadowColor_Proj_LOD1[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWCOLOR_PROJ_LOD1, i ), res, res, RT_SIZE_NO_CHANGE, fmt_depthColor, MATERIAL_RT_DEPTH_NONE, shadowColorFlags, 0 ) ); else g_tex_ShadowColor_Proj_LOD1[i].Init( g_tex_ShadowColor_Proj_LOD1[0] ); Assert( res == g_tex_ShadowDepth_Proj_LOD1[i]->GetActualHeight() ); Assert( res == g_tex_ShadowColor_Proj_LOD1[i]->GetActualHeight() ); Assert( res == g_tex_ShadowDepth_Proj_LOD1[i]->GetActualWidth() ); Assert( res == g_tex_ShadowColor_Proj_LOD1[i]->GetActualWidth() ); res = GetShadowResolution_Spot_LOD2(); generalShadowData.iPROJ_Res_LOD2 = res; if ( !bShadowUseColor || bFirst ) g_tex_ShadowDepth_Proj_LOD2[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWDEPTH_PROJ_LOD2, i ), res, res, RT_SIZE_NO_CHANGE, fmt_depth, MATERIAL_RT_DEPTH_NONE, depthFlags, 0 ) ); else g_tex_ShadowDepth_Proj_LOD2[i].Init( g_tex_ShadowDepth_Proj_LOD2[0] ); if ( bShadowUseColor || bFirst ) g_tex_ShadowColor_Proj_LOD2[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWCOLOR_PROJ_LOD2, i ), res, res, RT_SIZE_NO_CHANGE, fmt_depthColor, MATERIAL_RT_DEPTH_NONE, shadowColorFlags, 0 ) ); else g_tex_ShadowColor_Proj_LOD2[i].Init( g_tex_ShadowColor_Proj_LOD2[0] ); Assert( res == g_tex_ShadowDepth_Proj_LOD2[i]->GetActualHeight() ); Assert( res == g_tex_ShadowColor_Proj_LOD2[i]->GetActualHeight() ); Assert( res == g_tex_ShadowDepth_Proj_LOD2[i]->GetActualWidth() ); Assert( res == g_tex_ShadowColor_Proj_LOD2[i]->GetActualWidth() ); #endif } for ( int i = 0; i < MAX_SHADOW_DP; i++ ) { int res_x = GetShadowResolution_Point(); int res_y = res_x * 2; generalShadowData.iDPSM_Res_x = res_x; generalShadowData.iDPSM_Res_y = res_y; bool bFirst = i == 0; if ( !bShadowUseColor || bFirst ) g_tex_ShadowDepth_DP[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWDEPTH_DP, i ), res_x, res_y, RT_SIZE_NO_CHANGE, fmt_depth, MATERIAL_RT_DEPTH_NONE, depthFlags, 0 ) ); else g_tex_ShadowDepth_DP[i].Init( g_tex_ShadowDepth_DP[0] ); if ( bShadowUseColor || bFirst ) g_tex_ShadowColor_DP[i].Init( materials->CreateNamedRenderTargetTextureEx2( VarArgs( "%s%02i", DEFRTNAME_SHADOWCOLOR_DP, i ), res_x, res_y, RT_SIZE_NO_CHANGE, fmt_depthColor, MATERIAL_RT_DEPTH_NONE, shadowColorFlags, 0 ) ); else g_tex_ShadowColor_DP[i].Init( g_tex_ShadowColor_DP[0] ); Assert( res_y == g_tex_ShadowDepth_DP[i]->GetActualHeight() ); Assert( res_y == g_tex_ShadowColor_DP[i]->GetActualHeight() ); Assert( res_x == g_tex_ShadowDepth_DP[i]->GetActualWidth() ); Assert( res_x == g_tex_ShadowColor_DP[i]->GetActualWidth() ); } materials->EndRenderTargetAllocation(); GetDeferredExt()->CommitTexture_General( g_tex_Normals, g_tex_Depth, #if ( DEFCFG_LIGHTCTRL_PACKING == 0 ) g_tex_LightCtrl, #elif DEFCFG_DEFERRED_SHADING == 1 g_tex_Albedo, g_tex_Specular, #endif g_tex_Lightaccum ); for ( int i = 0; i < MAX_SHADOW_ORTHO; i++ ) GetDeferredExt()->CommitTexture_CascadedDepth( i, bShadowUseColor ? g_tex_ShadowColor_Ortho[i] : g_tex_ShadowDepth_Ortho[i] ); for ( int i = 0; i < MAX_SHADOW_DP; i++ ) GetDeferredExt()->CommitTexture_DualParaboloidDepth( i, bShadowUseColor ? g_tex_ShadowColor_DP[i] : g_tex_ShadowDepth_DP[i] ); for ( int i = 0; i < MAX_SHADOW_PROJ; i++ ) GetDeferredExt()->CommitTexture_ProjectedDepth( i, bShadowUseColor ? g_tex_ShadowColor_Proj[i] : g_tex_ShadowDepth_Proj[i] ); GetDeferredExt()->CommitTexture_VolumePrePass( g_tex_VolumePrepass ); GetDeferredExt()->CommitShadowData_General( generalShadowData ); #if DEFCFG_ENABLE_RADIOSITY AssertMsg( MAX_SHADOW_ORTHO == 1, "You gotta fix the commit func now.." ); GetDeferredExt()->CommitTexture_ShadowRadOutput_Ortho( g_tex_ShadowRad_Albedo_Ortho[0], g_tex_ShadowRad_Normal_Ortho[0] ); GetDeferredExt()->CommitTexture_Radiosity( g_tex_RadiosityBuffer[0], g_tex_RadiosityBuffer[1], g_tex_RadiosityNormal[0], g_tex_RadiosityNormal[1] ); #endif }
///---------------------------------------------------------------------------- /// /// ConfigFlagsTable::SetAsBoolean /// /// Set the value of a boolean flag. If the flag is a parent flag, all children flag // will be set accordingly. /// ///---------------------------------------------------------------------------- void ConfigFlagsTable::SetAsBoolean(Flag flag, Boolean value) { AssertMsg(this->GetFlagType(flag) == FlagBoolean, "flag not a boolean type"); Boolean* settingAsBoolean = this->GetAsBoolean(flag); Assert(settingAsBoolean != nullptr); Output::VerboseNote(_u("FLAG %s = %d\n"), FlagNames[(int) flag], value); *settingAsBoolean = value; // check if parent flag if (this->IsParentFlag(flag)) { // parent flag, will iterate through all child flags Flag childFlag = GetNextChildFlag(flag, /* no currentChildFlag */ InvalidFlag); while (childFlag != InvalidFlag) { Boolean childDefaultValue = GetDefaultValueAsBoolean(childFlag); // if the parent flag is TRUE, the children flag values are based on their default values // if the parent flag is FALSE, the children flag values are FALSE (always - as disabled) Boolean childValue = value == TRUE ? childDefaultValue : FALSE; Output::VerboseNote(_u("FLAG %s = %d - setting child flag %s = %d\n"), FlagNames[(int) flag], value, FlagNames[(int) childFlag], childValue); this->SetAsBoolean(childFlag, childValue); // get next child flag childFlag = GetNextChildFlag(flag, /* currentChildFlag */ childFlag); } } #ifdef ENABLE_DEBUG_CONFIG_OPTIONS // in case the flag is marked as 'callback' - to call the method #define FLAG(type, name, description, defaultValue, parentName, hasCallback) FLAGCALLBACK##hasCallback(type, name) #define FLAGCALLBACKFALSE(type, name) #define FLAGCALLBACKTRUE(type, name) FLAGDOCALLBACK##type(name) // define an overload for each FlagTypes - type // * all defaults we don't care about - should assert #define FLAGDOCALLBACKNumberRange(name) Assert(false); #define FLAGDOCALLBACKPhases(name) Assert(false); #define FLAGDOCALLBACKString(name) Assert(false); #define FLAGDOCALLBACKNumber(name) Assert(false); #define FLAGDOCALLBACKNumberSet(name) Assert(false); #define FLAGDOCALLBACKNumberPairSet(name) Assert(false); #define FLAGDOCALLBACKNumberTrioSet(name) Assert(false); // * and those we do care about #define FLAGDOCALLBACKBoolean(name) if( flag == name##Flag ) this->FlagSetCallback_##name(value); #include "ConfigFlagsList.h" #undef FLAGDOCALLBACKBoolean #undef FLAGDOCALLBACKNumberRange #undef FLAGDOCALLBACKNumberPairSet #undef FLAGDOCALLBACKNumberTrioSet #undef FLAGDOCALLBACKNumberSet #undef FLAGDOCALLBACKNumber #undef FLAGDOCALLBACKString #undef FLAGDOCALLBACKPhases #undef FLAGCALLBACKTRUE #undef FLAGCALLBACKFALSE #undef FLAG #endif }
INT32 DoMessageBox( UINT8 ubStyle, INT16 *zString, UINT32 uiExitScreen, UINT16 usFlags, MSGBOX_CALLBACK ReturnCallback, SGPRect *pCenteringRect ) { VSURFACE_DESC vs_desc; UINT16 usTextBoxWidth; UINT16 usTextBoxHeight; SGPRect aRect; UINT32 uiDestPitchBYTES, uiSrcPitchBYTES; UINT8 *pDestBuf, *pSrcBuf; INT16 sButtonX, sButtonY, sBlankSpace; UINT8 ubMercBoxBackground = BASIC_MERC_POPUP_BACKGROUND, ubMercBoxBorder = BASIC_MERC_POPUP_BORDER; UINT8 ubFontColor, ubFontShadowColor; UINT16 usCursor; INT32 iId = -1; GetMousePos( &pOldMousePosition ); //this variable can be unset if ur in a non gamescreen and DONT want the msg box to use the save buffer gfDontOverRideSaveBuffer = TRUE; SetCurrentCursorFromDatabase( CURSOR_NORMAL ); if( gMsgBox.BackRegion.uiFlags & MSYS_REGION_EXISTS ) { return( 0 ); } // Based on style.... switch( ubStyle ) { //default case MSG_BOX_BASIC_STYLE: ubMercBoxBackground = DIALOG_MERC_POPUP_BACKGROUND; ubMercBoxBorder = DIALOG_MERC_POPUP_BORDER; // Add button images gMsgBox.iButtonImages = LoadButtonImage( "INTERFACE\\popupbuttons.sti", -1,0,-1,1,-1 ); ubFontColor = FONT_MCOLOR_WHITE; ubFontShadowColor = DEFAULT_SHADOW; usCursor = CURSOR_NORMAL; break; case MSG_BOX_RED_ON_WHITE: ubMercBoxBackground = WHITE_MERC_POPUP_BACKGROUND; ubMercBoxBorder = RED_MERC_POPUP_BORDER; // Add button images gMsgBox.iButtonImages = LoadButtonImage( "INTERFACE\\msgboxRedButtons.sti", -1,0,-1,1,-1 ); ubFontColor = 2; ubFontShadowColor = NO_SHADOW; usCursor = CURSOR_LAPTOP_SCREEN; break; case MSG_BOX_BLUE_ON_GREY: ubMercBoxBackground = GREY_MERC_POPUP_BACKGROUND; ubMercBoxBorder = BLUE_MERC_POPUP_BORDER; // Add button images gMsgBox.iButtonImages = LoadButtonImage( "INTERFACE\\msgboxGreyButtons.sti", -1,0,-1,1,-1 ); ubFontColor = 2; ubFontShadowColor = FONT_MCOLOR_WHITE; usCursor = CURSOR_LAPTOP_SCREEN; break; case MSG_BOX_IMP_STYLE: ubMercBoxBackground = IMP_POPUP_BACKGROUND; ubMercBoxBorder = DIALOG_MERC_POPUP_BORDER; // Add button images gMsgBox.iButtonImages = LoadButtonImage( "INTERFACE\\msgboxGreyButtons.sti", -1,0,-1,1,-1 ); ubFontColor = 2; ubFontShadowColor = FONT_MCOLOR_WHITE; usCursor = CURSOR_LAPTOP_SCREEN; break; case MSG_BOX_BASIC_SMALL_BUTTONS: ubMercBoxBackground = DIALOG_MERC_POPUP_BACKGROUND; ubMercBoxBorder = DIALOG_MERC_POPUP_BORDER; // Add button images gMsgBox.iButtonImages = LoadButtonImage( "INTERFACE\\popupbuttons.sti", -1,2,-1,3,-1 ); ubFontColor = FONT_MCOLOR_WHITE; ubFontShadowColor = DEFAULT_SHADOW; usCursor = CURSOR_NORMAL; break; case MSG_BOX_LAPTOP_DEFAULT: ubMercBoxBackground = LAPTOP_POPUP_BACKGROUND; ubMercBoxBorder = LAPTOP_POP_BORDER; // Add button images gMsgBox.iButtonImages = LoadButtonImage( "INTERFACE\\popupbuttons.sti", -1,0,-1,1,-1 ); ubFontColor = FONT_MCOLOR_WHITE; ubFontShadowColor = DEFAULT_SHADOW; usCursor = CURSOR_LAPTOP_SCREEN; break; default: ubMercBoxBackground = BASIC_MERC_POPUP_BACKGROUND; ubMercBoxBorder = BASIC_MERC_POPUP_BORDER; // Add button images gMsgBox.iButtonImages = LoadButtonImage( "INTERFACE\\msgboxbuttons.sti", -1,0,-1,1,-1 ); ubFontColor = FONT_MCOLOR_WHITE; ubFontShadowColor = DEFAULT_SHADOW; usCursor = CURSOR_NORMAL; break; } if ( usFlags & MSG_BOX_FLAG_USE_CENTERING_RECT && pCenteringRect != NULL ) { aRect.iTop = pCenteringRect->iTop; aRect.iLeft = pCenteringRect->iLeft; aRect.iBottom = pCenteringRect->iBottom; aRect.iRight = pCenteringRect->iRight; } else { // Use default! aRect.iTop = 0; aRect.iLeft = 0; aRect.iBottom = 480; aRect.iRight = 640; } // Set some values! gMsgBox.usFlags = usFlags; gMsgBox.uiExitScreen = uiExitScreen; gMsgBox.ExitCallback = ReturnCallback; gMsgBox.fRenderBox = TRUE; gMsgBox.bHandled = 0; // Init message box gMsgBox.iBoxId = PrepareMercPopupBox( iId, ubMercBoxBackground, ubMercBoxBorder, zString, MSGBOX_DEFAULT_WIDTH, 40, 10, 30, &usTextBoxWidth, &usTextBoxHeight ); if( gMsgBox.iBoxId == -1 ) { #ifdef JA2BETAVERSION AssertMsg( 0, "Failed in DoMessageBox(). Probable reason is because the string was too large to fit in max message box size." ); #endif return 0; } // Save height,width gMsgBox.usWidth = usTextBoxWidth; gMsgBox.usHeight = usTextBoxHeight; // Determine position ( centered in rect ) gMsgBox.sX = (INT16)( ( ( ( aRect.iRight - aRect.iLeft ) - usTextBoxWidth ) / 2 ) + aRect.iLeft ); gMsgBox.sY = (INT16)( ( ( ( aRect.iBottom - aRect.iTop ) - usTextBoxHeight ) / 2 ) + aRect.iTop ); if ( guiCurrentScreen == GAME_SCREEN ) { gfStartedFromGameScreen = TRUE; } if ( (fInMapMode == TRUE ) ) { // fMapExitDueToMessageBox = TRUE; gfStartedFromMapScreen = TRUE; fMapPanelDirty = TRUE; } // Set pending screen SetPendingNewScreen( MSG_BOX_SCREEN); // Init save buffer vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE; vs_desc.usWidth = usTextBoxWidth; vs_desc.usHeight = usTextBoxHeight; vs_desc.ubBitDepth = 16; if( AddVideoSurface( &vs_desc, &gMsgBox.uiSaveBuffer) == FALSE ) { return( - 1 ); } //Save what we have under here... pDestBuf = LockVideoSurface( gMsgBox.uiSaveBuffer, &uiDestPitchBYTES); pSrcBuf = LockVideoSurface( FRAME_BUFFER, &uiSrcPitchBYTES); Blt16BPPTo16BPP((UINT16 *)pDestBuf, uiDestPitchBYTES, (UINT16 *)pSrcBuf, uiSrcPitchBYTES, 0 , 0, gMsgBox.sX , gMsgBox.sY, usTextBoxWidth, usTextBoxHeight ); UnLockVideoSurface( gMsgBox.uiSaveBuffer ); UnLockVideoSurface( FRAME_BUFFER ); // Create top-level mouse region MSYS_DefineRegion( &(gMsgBox.BackRegion), 0, 0, 640, 480, MSYS_PRIORITY_HIGHEST, usCursor, MSYS_NO_CALLBACK, MsgBoxClickCallback ); if( gGameSettings.fOptions[ TOPTION_DONT_MOVE_MOUSE ] == FALSE ) { if( usFlags & MSG_BOX_FLAG_OK ) { SimulateMouseMovement( ( gMsgBox.sX + ( usTextBoxWidth / 2 ) + 27 ), ( gMsgBox.sY + ( usTextBoxHeight - 10 ) ) ); } else { SimulateMouseMovement( gMsgBox.sX + usTextBoxWidth / 2 , gMsgBox.sY + usTextBoxHeight - 4 ); } } // Add region MSYS_AddRegion(&(gMsgBox.BackRegion) ); // findout if cursor locked, if so, store old params and store, restore when done if( IsCursorRestricted() ) { fCursorLockedToArea = TRUE; GetRestrictedClipCursor( &MessageBoxRestrictedCursorRegion ); FreeMouseCursor( ); } // Create four numbered buttons if ( usFlags & MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS ) { // This is exclusive of any other buttons... no ok, no cancel, no nothing sBlankSpace = usTextBoxWidth - MSGBOX_SMALL_BUTTON_WIDTH * 4 - MSGBOX_SMALL_BUTTON_X_SEP * 3; sButtonX = sBlankSpace / 2; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiButton[0] = CreateIconAndTextButton( gMsgBox.iButtonImages, L"1", FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NumberedMsgBoxCallback ); MSYS_SetBtnUserData( gMsgBox.uiButton[0], 0, 1); SetButtonCursor(gMsgBox.uiButton[0], usCursor); sButtonX += MSGBOX_SMALL_BUTTON_WIDTH + MSGBOX_SMALL_BUTTON_X_SEP; gMsgBox.uiButton[1] = CreateIconAndTextButton( gMsgBox.iButtonImages, L"2", FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NumberedMsgBoxCallback ); MSYS_SetBtnUserData( gMsgBox.uiButton[1], 0, 2); SetButtonCursor(gMsgBox.uiButton[1], usCursor); sButtonX += MSGBOX_SMALL_BUTTON_WIDTH + MSGBOX_SMALL_BUTTON_X_SEP; gMsgBox.uiButton[2] = CreateIconAndTextButton( gMsgBox.iButtonImages, L"3", FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NumberedMsgBoxCallback ); MSYS_SetBtnUserData( gMsgBox.uiButton[2], 0, 3); SetButtonCursor(gMsgBox.uiButton[2], usCursor); sButtonX += MSGBOX_SMALL_BUTTON_WIDTH + MSGBOX_SMALL_BUTTON_X_SEP; gMsgBox.uiButton[3] = CreateIconAndTextButton( gMsgBox.iButtonImages, L"4", FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NumberedMsgBoxCallback ); MSYS_SetBtnUserData( gMsgBox.uiButton[3], 0, 4); SetButtonCursor(gMsgBox.uiButton[3], usCursor); ForceButtonUnDirty( gMsgBox.uiButton[3] ); ForceButtonUnDirty( gMsgBox.uiButton[2] ); ForceButtonUnDirty( gMsgBox.uiButton[1] ); ForceButtonUnDirty( gMsgBox.uiButton[0] ); } else { // Create text button if ( usFlags & MSG_BOX_FLAG_OK ) { // sButtonX = ( usTextBoxWidth - MSGBOX_BUTTON_WIDTH ) / 2; sButtonX = ( usTextBoxWidth - GetMSgBoxButtonWidth( gMsgBox.iButtonImages ) ) / 2; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiOKButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_OK ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)OKMsgBoxCallback ); SetButtonCursor(gMsgBox.uiOKButton, usCursor); ForceButtonUnDirty( gMsgBox.uiOKButton ); } // Create text button if ( usFlags & MSG_BOX_FLAG_CANCEL ) { sButtonX = ( usTextBoxWidth - GetMSgBoxButtonWidth( gMsgBox.iButtonImages ) ) / 2; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiOKButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_CANCEL ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)OKMsgBoxCallback ); SetButtonCursor(gMsgBox.uiOKButton, usCursor); ForceButtonUnDirty( gMsgBox.uiOKButton ); } if ( usFlags & MSG_BOX_FLAG_YESNO ) { sButtonX = ( usTextBoxWidth - ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ) / 2; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiYESButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_YES ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)YESMsgBoxCallback ); SetButtonCursor(gMsgBox.uiYESButton, usCursor); ForceButtonUnDirty( gMsgBox.uiYESButton ); gMsgBox.uiNOButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_NO ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NOMsgBoxCallback ); SetButtonCursor(gMsgBox.uiNOButton, usCursor); ForceButtonUnDirty( gMsgBox.uiNOButton ); } if ( usFlags & MSG_BOX_FLAG_CONTINUESTOP ) { sButtonX = ( usTextBoxWidth - ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ) / 2; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiYESButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pUpdatePanelButtons[ 0 ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)YESMsgBoxCallback ); SetButtonCursor(gMsgBox.uiYESButton, usCursor); ForceButtonUnDirty( gMsgBox.uiYESButton ); gMsgBox.uiNOButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pUpdatePanelButtons[ 1 ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NOMsgBoxCallback ); SetButtonCursor(gMsgBox.uiNOButton, usCursor); ForceButtonUnDirty( gMsgBox.uiNOButton ); } if ( usFlags & MSG_BOX_FLAG_OKCONTRACT ) { sButtonX = ( usTextBoxWidth - ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ) / 2; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiYESButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_OK ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)OKMsgBoxCallback ); SetButtonCursor(gMsgBox.uiYESButton, usCursor); ForceButtonUnDirty( gMsgBox.uiYESButton ); gMsgBox.uiNOButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_REHIRE ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)ContractMsgBoxCallback ); SetButtonCursor(gMsgBox.uiNOButton, usCursor); ForceButtonUnDirty( gMsgBox.uiNOButton ); } if ( usFlags & MSG_BOX_FLAG_YESNOCONTRACT ) { sButtonX = ( usTextBoxWidth - ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ) / 3; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiYESButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_YES ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)YESMsgBoxCallback ); SetButtonCursor(gMsgBox.uiYESButton, usCursor); ForceButtonUnDirty( gMsgBox.uiYESButton ); gMsgBox.uiNOButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_NO ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NOMsgBoxCallback ); SetButtonCursor(gMsgBox.uiNOButton, usCursor); ForceButtonUnDirty( gMsgBox.uiNOButton ); gMsgBox.uiOKButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_REHIRE ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + 2 * ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)ContractMsgBoxCallback ); SetButtonCursor(gMsgBox.uiOKButton, usCursor); ForceButtonUnDirty( gMsgBox.uiOKButton ); } if ( usFlags & MSG_BOX_FLAG_GENERICCONTRACT ) { sButtonX = ( usTextBoxWidth - ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ) / 3; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiYESButton = CreateIconAndTextButton( gMsgBox.iButtonImages, gzUserDefinedButton1, FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)YESMsgBoxCallback ); SetButtonCursor(gMsgBox.uiYESButton, usCursor); ForceButtonUnDirty( gMsgBox.uiYESButton ); gMsgBox.uiNOButton = CreateIconAndTextButton( gMsgBox.iButtonImages, gzUserDefinedButton2, FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NOMsgBoxCallback ); SetButtonCursor(gMsgBox.uiNOButton, usCursor); ForceButtonUnDirty( gMsgBox.uiNOButton ); gMsgBox.uiOKButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_REHIRE ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + 2 * ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)ContractMsgBoxCallback ); SetButtonCursor(gMsgBox.uiOKButton, usCursor); ForceButtonUnDirty( gMsgBox.uiOKButton ); } if ( usFlags & MSG_BOX_FLAG_GENERIC ) { sButtonX = ( usTextBoxWidth - ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ) / 2; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiYESButton = CreateIconAndTextButton( gMsgBox.iButtonImages, gzUserDefinedButton1, FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)YESMsgBoxCallback ); SetButtonCursor(gMsgBox.uiYESButton, usCursor); ForceButtonUnDirty( gMsgBox.uiYESButton ); gMsgBox.uiNOButton = CreateIconAndTextButton( gMsgBox.iButtonImages, gzUserDefinedButton2, FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NOMsgBoxCallback ); SetButtonCursor(gMsgBox.uiNOButton, usCursor); ForceButtonUnDirty( gMsgBox.uiNOButton ); } if ( usFlags & MSG_BOX_FLAG_YESNOLIE ) { sButtonX = ( usTextBoxWidth - ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ) / 3; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiYESButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_YES ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)YESMsgBoxCallback ); SetButtonCursor(gMsgBox.uiYESButton, usCursor); ForceButtonUnDirty( gMsgBox.uiYESButton ); gMsgBox.uiNOButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_NO ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NOMsgBoxCallback ); SetButtonCursor(gMsgBox.uiNOButton, usCursor); ForceButtonUnDirty( gMsgBox.uiNOButton ); gMsgBox.uiOKButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_LIE ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + 2 * ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)LieMsgBoxCallback ); SetButtonCursor(gMsgBox.uiOKButton, usCursor); ForceButtonUnDirty( gMsgBox.uiOKButton ); } if ( usFlags & MSG_BOX_FLAG_OKSKIP ) { sButtonX = ( usTextBoxWidth - ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ) / 2; sButtonY = usTextBoxHeight - MSGBOX_BUTTON_HEIGHT - 10; gMsgBox.uiYESButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_OK ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)YESMsgBoxCallback ); SetButtonCursor(gMsgBox.uiYESButton, usCursor); ForceButtonUnDirty( gMsgBox.uiYESButton ); gMsgBox.uiNOButton = CreateIconAndTextButton( gMsgBox.iButtonImages, pMessageStrings[ MSG_SKIP ], FONT12ARIAL, ubFontColor, ubFontShadowColor, ubFontColor, ubFontShadowColor, TEXT_CJUSTIFIED, (INT16)(gMsgBox.sX + sButtonX + ( MSGBOX_BUTTON_WIDTH + MSGBOX_BUTTON_X_SEP ) ), (INT16)(gMsgBox.sY + sButtonY ), BUTTON_TOGGLE ,MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)NOMsgBoxCallback ); SetButtonCursor(gMsgBox.uiNOButton, usCursor); ForceButtonUnDirty( gMsgBox.uiNOButton ); } } InterruptTime(); PauseGame(); LockPauseState( 1 ); // Pause timers as well.... PauseTime( TRUE ); // Save mouse restriction region... GetRestrictedClipCursor( &gOldCursorLimitRectangle ); FreeMouseCursor( ); gfNewMessageBox = TRUE; gfInMsgBox = TRUE; return( iId ); }
/** * Explodes a time spec (UTC). * * @returns pTime. * @param pTime Where to store the exploded time. * @param pTimeSpec The time spec to exploded. */ RTDECL(PRTTIME) RTTimeExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec) { int64_t i64Div; int32_t i32Div; int32_t i32Rem; unsigned iYear; const uint16_t *paiDayOfYear; int iMonth; AssertMsg(VALID_PTR(pTime), ("%p\n", pTime)); AssertMsg(VALID_PTR(pTimeSpec), ("%p\n", pTime)); /* * The simple stuff first. */ pTime->fFlags = RTTIME_FLAGS_TYPE_UTC; i64Div = pTimeSpec->i64NanosecondsRelativeToUnixEpoch; i32Rem = (int32_t)(i64Div % 1000000000); i64Div /= 1000000000; if (i32Rem < 0) { i32Rem += 1000000000; i64Div--; } pTime->u32Nanosecond = i32Rem; /* second */ i32Rem = (int32_t)(i64Div % 60); i64Div /= 60; if (i32Rem < 0) { i32Rem += 60; i64Div--; } pTime->u8Second = i32Rem; /* minute */ i32Div = (int32_t)i64Div; /* 60,000,000,000 > 33bit, so 31bit suffices. */ i32Rem = i32Div % 60; i32Div /= 60; if (i32Rem < 0) { i32Rem += 60; i32Div--; } pTime->u8Minute = i32Rem; /* hour */ i32Rem = i32Div % 24; i32Div /= 24; /* days relative to 1970-01-01 */ if (i32Rem < 0) { i32Rem += 24; i32Div--; } pTime->u8Hour = i32Rem; /* weekday - 1970-01-01 was a Thursday (3) */ pTime->u8WeekDay = ((int)(i32Div % 7) + 3 + 7) % 7; /* * We've now got a number of days relative to 1970-01-01. * To get the correct year number we have to mess with leap years. Fortunately, * the representation we've got only supports a few hundred years, so we can * generate a table and perform a simple two way search from the modulus 365 derived. */ iYear = OFF_YEAR_IDX_EPOCH + i32Div / 365; while (g_aoffYear[iYear + 1] <= i32Div) iYear++; while (g_aoffYear[iYear] > i32Div) iYear--; pTime->i32Year = iYear + OFF_YEAR_IDX_0_YEAR; i32Div -= g_aoffYear[iYear]; pTime->u16YearDay = i32Div + 1; /* * Figuring out the month is done in a manner similar to the year, only here we * ensure that the index is matching or too small. */ if (rtTimeIsLeapYear(pTime->i32Year)) { pTime->fFlags |= RTTIME_FLAGS_LEAP_YEAR; paiDayOfYear = &g_aiDayOfYearLeap[0]; } else { pTime->fFlags |= RTTIME_FLAGS_COMMON_YEAR; paiDayOfYear = &g_aiDayOfYear[0]; } iMonth = i32Div / 32; i32Div++; while (paiDayOfYear[iMonth + 1] <= i32Div) iMonth++; pTime->u8Month = iMonth + 1; i32Div -= paiDayOfYear[iMonth]; pTime->u8MonthDay = i32Div + 1; /* This is for UTC timespecs, so, no offset. */ pTime->offUTC = 0; return pTime; }
JavascriptMapIterator* JavascriptMapIterator::FromVar(Var aValue) { AssertMsg(Is(aValue), "Ensure var is actually a 'JavascriptMapIterator'"); return static_cast<JavascriptMapIterator *>(RecyclableObject::FromVar(aValue)); }
Js::Var JSONParser::Walk(Js::JavascriptString* name, Js::PropertyId id, Js::Var holder, uint32 index) { AssertMsg(reviver, "JSON post parse walk with null reviver"); Js::Var value; Js::Var values[3]; Js::Arguments args(0, values); Js::RecyclableObject *undefined = scriptContext->GetLibrary()->GetUndefined(); if (Js::DynamicObject::IsAnyArray(holder)) { // when called from an array the key is NULL and the keyId is the index. value = Js::JavascriptArray::FromAnyArray(holder)->DirectGetItem(id); name = scriptContext->GetIntegerString(id); } else { AssertMsg(Js::JavascriptOperators::GetTypeId(holder) == Js::TypeIds_Object || Js::JavascriptOperators::GetTypeId(holder) == Js::TypeIds_Arguments, "The holder argument in a JSON::Walk function must be an object or an array"); if (id == Constants::NoProperty) { if (!Js::RecyclableObject::FromVar(holder)->GetItem(holder, index, &value, scriptContext)) { value = undefined; } } else { if (!Js::RecyclableObject::FromVar(holder)->GetProperty(holder, id, &value, NULL, scriptContext)) { value = undefined; } } } // this is a post order walk. Visit the children before calling walk on this object if (Js::DynamicObject::IsAnyArray(value)) { Js::JavascriptArray* arrayVal = Js::JavascriptArray::FromAnyArray(value); // REVIEW: How do we guarantee that JSON objects are not native arrays? Assert(!Js::JavascriptNativeIntArray::Is(arrayVal) && !Js::JavascriptNativeFloatArray::Is(arrayVal)); uint length = arrayVal->GetLength(); if (!arrayVal->IsCrossSiteObject()) { for(uint k = 0; k < length; k++) { Js::Var newElement = Walk(0, k, value); if(Js::JavascriptOperators::IsUndefinedObject(newElement, undefined)) { arrayVal->DirectDeleteItemAt<Js::Var>(k); } else { arrayVal->DirectSetItemAt(k, newElement); } } } else { for(uint k = 0; k < length; k++) { Js::Var newElement = Walk(0, k, value); if(Js::JavascriptOperators::IsUndefinedObject(newElement, undefined)) { arrayVal->DirectDeleteItemAt<Js::Var>(k); } else { arrayVal->SetItem(k, newElement, Js::PropertyOperation_None); } } } } else { Js::TypeId typeId = Js::JavascriptOperators::GetTypeId(value); if (typeId == Js::TypeIds_Object || typeId == Js::TypeIds_Arguments) { Js::Var enumeratorVar; // normally we should have a JSON object here and the enumerator should be always be successful. However, the objects can be // modified by user code. It is better to skip a damaged object. ES5 spec doesn't specify an error here. if(Js::RecyclableObject::FromVar(value)->GetEnumerator(FALSE, &enumeratorVar, scriptContext)) { Js::JavascriptEnumerator* enumerator = static_cast<Js::JavascriptEnumerator*>(enumeratorVar); Js::Var propertyNameVar; Js::PropertyId idMember; while(enumerator->MoveNext()) { propertyNameVar = enumerator->GetCurrentIndex(); //NOTE: If testing key value call enumerator->GetCurrentValue() to confirm value is correct; AssertMsg(!Js::JavascriptOperators::IsUndefinedObject(propertyNameVar, undefined) && Js::JavascriptString::Is(propertyNameVar) , "bad enumeration on a JSON Object"); if (enumerator->GetCurrentPropertyId(&idMember)) { Js::Var newElement = Walk(Js::JavascriptString::FromVar(propertyNameVar), idMember, value); if (Js::JavascriptOperators::IsUndefinedObject(newElement, undefined)) { Js::JavascriptOperators::DeleteProperty(Js::RecyclableObject::FromVar(value), idMember); } else { Js::JavascriptOperators::SetProperty(value, Js::RecyclableObject::FromVar(value), idMember, newElement, scriptContext); } } // For the numeric cases the enumerator is set to a NullEnumerator (see class in ForInObjectEnumerator.h) // Numerals do not have property Ids so we need to set and delete items else { uint32 propertyIndex = enumerator->GetCurrentItemIndex(); AssertMsg(Js::JavascriptArray::InvalidIndex != propertyIndex, "Not a numeric type"); Js::Var newElement = Walk(Js::JavascriptString::FromVar(propertyNameVar), idMember, value, propertyIndex); if (Js::JavascriptOperators::IsUndefinedObject(newElement, undefined)) { Js::JavascriptOperators::DeleteItem(Js::RecyclableObject::FromVar(value), propertyIndex); } else { Js::JavascriptOperators::SetItem(value, Js::RecyclableObject::FromVar(value), propertyIndex, newElement, scriptContext); } } } } } } // apply reviver on this node now args.Info.Count = 3; args.Values[0] = holder; args.Values[1] = name; args.Values[2] = value; value = Js::JavascriptFunction::CallFunction<true>(reviver, reviver->GetEntryPoint(), args); return value; }