RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...) { AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER); /* * Create the semaphore. * (Manual reset, not signaled, private event object.) */ HEV hev; int rc = DosCreateEventSem(NULL, &hev, 0, FALSE); if (!rc) { *phEventMultiSem = (RTSEMEVENTMULTI)(void *)hev; return VINF_SUCCESS; } return RTErrConvertFromOS2(rc); }
DECLHIDDEN(int) rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr) { if (fFlags & RTMEMHDR_FLAG_ANY_CTX) return VERR_NOT_SUPPORTED; void *pv = NULL; APIRET rc = KernVMAlloc(cb + sizeof(RTMEMHDR), VMDHA_FIXED, &pv, (void **)-1, NULL); if (RT_UNLIKELY(rc != NO_ERROR)) return RTErrConvertFromOS2(rc); PRTMEMHDR pHdr = (PRTMEMHDR)pv; pHdr->u32Magic = RTMEMHDR_MAGIC; pHdr->fFlags = fFlags; pHdr->cb = cb; pHdr->cbReq = cb; *ppHdr = pHdr; return VINF_SUCCESS; }
RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) { /* * Wait for condition. */ int rc = DosWaitEventSem(SEM2HND(hEventSem), cMillies == RT_INDEFINITE_WAIT ? SEM_INDEFINITE_WAIT : cMillies); switch (rc) { case NO_ERROR: return VINF_SUCCESS; case ERROR_SEM_TIMEOUT: case ERROR_TIMEOUT: return VERR_TIMEOUT; case ERROR_INTERRUPT: return VERR_INTERRUPTED; default: { AssertMsgFailed(("Wait on hEventSem %p failed, rc=%d\n", hEventSem, rc)); return RTErrConvertFromOS2(rc); } } }
RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...) { AssertReturn(!(fFlags & ~RTSEMMUTEX_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER); /* * Create the semaphore. */ HMTX hmtx; int rc = DosCreateMutexSem(NULL, &hmtx, 0, FALSE); if (!rc) { /** @todo implement lock validation of OS/2 mutex semaphores. */ *phMutexSem = (RTSEMMUTEX)(void *)hmtx; return VINF_SUCCESS; } return RTErrConvertFromOS2(rc); }
RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies) { /* * Lock mutex semaphore. */ int rc = DosRequestMutexSem(SEM2HND(hMutexSem), cMillies == RT_INDEFINITE_WAIT ? SEM_INDEFINITE_WAIT : cMillies); switch (rc) { case NO_ERROR: return VINF_SUCCESS; case ERROR_SEM_TIMEOUT: case ERROR_TIMEOUT: return VERR_TIMEOUT; case ERROR_INTERRUPT: return VERR_INTERRUPTED; case ERROR_SEM_OWNER_DIED: return VERR_SEM_OWNER_DIED; default: { AssertMsgFailed(("Wait on hMutexSem %p failed, rc=%d\n", hMutexSem, rc)); return RTErrConvertFromOS2(rc); } } }
DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess) { /* create the object. */ const ULONG cPages = cb >> PAGE_SHIFT; PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, aPages[cPages]), RTR0MEMOBJTYPE_LOCK, pv, cb); if (!pMemOs2) return VERR_NO_MEMORY; /* lock it. */ ULONG cPagesRet = cPages; int rc = KernVMLock(VMDHL_LONG | (fAccess & RTMEM_PROT_WRITE ? VMDHL_WRITE : 0), pv, cb, &pMemOs2->Lock, &pMemOs2->aPages[0], &cPagesRet); if (!rc) { rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet); pMemOs2->Core.u.Lock.R0Process = NIL_RTR0PROCESS; *ppMem = &pMemOs2->Core; return VINF_SUCCESS; } rtR0MemObjDelete(&pMemOs2->Core); return RTErrConvertFromOS2(rc); }
DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable) { NOREF(fExecutable); /* create the object. */ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_CONT, NULL, cb); if (!pMemOs2) return VERR_NO_MEMORY; /* do the allocation. */ ULONG ulPhys = ~0UL; int rc = KernVMAlloc(cb, VMDHA_FIXED | VMDHA_CONTIG, &pMemOs2->Core.pv, (PPVOID)&ulPhys, NULL); if (!rc) { Assert(ulPhys != ~0UL); pMemOs2->Core.u.Cont.Phys = ulPhys; *ppMem = &pMemOs2->Core; return VINF_SUCCESS; } rtR0MemObjDelete(&pMemOs2->Core); return RTErrConvertFromOS2(rc); }
/** * Daemonize the process for running in the background. * * This is supposed to do the same job as the BSD daemon() call. * * @returns 0 on success * * @param fNoChDir Pass false to change working directory to root. * @param fNoClose Pass false to redirect standard file streams to /dev/null. * @param fRespawn Restart the daemonised process after five seconds if it * terminates abnormally. * @param pcRespawn Where to store a count of how often we have respawned, * intended for avoiding error spamming. Optional. * * @todo Use RTProcDaemonize instead of this. * @todo Implement fRespawn on OS/2. * @todo Make the respawn interval configurable. But not until someone * actually needs that. */ VBGLR3DECL(int) VbglR3Daemonize(bool fNoChDir, bool fNoClose, bool fRespawn, unsigned *pcRespawn) { #if defined(RT_OS_OS2) PPIB pPib; PTIB pTib; DosGetInfoBlocks(&pTib, &pPib); AssertRelease(!fRespawn); /* Get the full path to the executable. */ char szExe[CCHMAXPATH]; APIRET rc = DosQueryModuleName(pPib->pib_hmte, sizeof(szExe), szExe); if (rc) return RTErrConvertFromOS2(rc); /* calc the length of the command line. */ char *pch = pPib->pib_pchcmd; size_t cch0 = strlen(pch); pch += cch0 + 1; size_t cch1 = strlen(pch); pch += cch1 + 1; char *pchArgs; if (cch1 && *pch) { do pch = strchr(pch, '\0') + 1; while (*pch); size_t cchTotal = pch - pPib->pib_pchcmd; pchArgs = (char *)alloca(cchTotal + sizeof("--daemonized\0\0")); memcpy(pchArgs, pPib->pib_pchcmd, cchTotal - 1); memcpy(pchArgs + cchTotal - 1, "--daemonized\0\0", sizeof("--daemonized\0\0")); } else { size_t cchTotal = pch - pPib->pib_pchcmd + 1; pchArgs = (char *)alloca(cchTotal + sizeof(" --daemonized ")); memcpy(pchArgs, pPib->pib_pchcmd, cch0 + 1); pch = pchArgs + cch0 + 1; memcpy(pch, " --daemonized ", sizeof(" --daemonized ") - 1); pch += sizeof(" --daemonized ") - 1; if (cch1) memcpy(pch, pPib->pib_pchcmd + cch0 + 1, cch1 + 2); else pch[0] = pch[1] = '\0'; } /* spawn a detach process */ char szObj[128]; RESULTCODES ResCodes = { 0, 0 }; szObj[0] = '\0'; rc = DosExecPgm(szObj, sizeof(szObj), EXEC_BACKGROUND, (PCSZ)pchArgs, NULL, &ResCodes, (PCSZ)szExe); if (rc) { /** @todo Change this to some standard log/print error?? */ /* VBoxServiceError("DosExecPgm failed with rc=%d and szObj='%s'\n", rc, szObj); */ return RTErrConvertFromOS2(rc); } DosExit(EXIT_PROCESS, 0); return VERR_GENERAL_FAILURE; #elif defined(RT_OS_WINDOWS) # error "PORTME" #else /* the unices */ /* * Fork the child process in a new session and quit the parent. * * - fork once and create a new session (setsid). This will detach us * from the controlling tty meaning that we won't receive the SIGHUP * (or any other signal) sent to that session. * - The SIGHUP signal is ignored because the session/parent may throw * us one before we get to the setsid. * - When the parent exit(0) we will become an orphan and re-parented to * the init process. * - Because of the Linux / System V semantics of assigning the controlling * tty automagically when a session leader first opens a tty, we will * fork() once more on Linux to get rid of the session leadership role. */ struct sigaction OldSigAct; struct sigaction SigAct; RT_ZERO(SigAct); SigAct.sa_handler = SIG_IGN; int rcSigAct = sigaction(SIGHUP, &SigAct, &OldSigAct); pid_t pid = fork(); if (pid == -1) return RTErrConvertFromErrno(errno); if (pid != 0) exit(0); /* * The orphaned child becomes is reparented to the init process. * We create a new session for it (setsid), point the standard * file descriptors to /dev/null, and change to the root directory. */ pid_t newpgid = setsid(); int SavedErrno = errno; if (rcSigAct != -1) sigaction(SIGHUP, &OldSigAct, NULL); if (newpgid == -1) return RTErrConvertFromErrno(SavedErrno); if (!fNoClose) { /* Open stdin(0), stdout(1) and stderr(2) as /dev/null. */ int fd = open("/dev/null", O_RDWR); if (fd == -1) /* paranoia */ { close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); fd = open("/dev/null", O_RDWR); } if (fd != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (fd > 2) close(fd); } } if (!fNoChDir) chdir("/"); /* * Change the umask - this is non-standard daemon() behavior. */ umask(027); # ifdef RT_OS_LINUX /* * And fork again to lose session leader status (non-standard daemon() * behaviour). */ pid = fork(); if (pid == -1) return RTErrConvertFromErrno(errno); if (pid != 0) exit(0); # endif /* RT_OS_LINUX */ if (fRespawn) { /* We implement re-spawning as a third fork(), with the parent process * monitoring the child and re-starting it after a delay if it exits * abnormally. */ unsigned cRespawn = 0; for (;;) { int iStatus, rcWait; if (pcRespawn != NULL) *pcRespawn = cRespawn; pid = fork(); if (pid == -1) return RTErrConvertFromErrno(errno); if (pid == 0) return VINF_SUCCESS; do rcWait = waitpid(pid, &iStatus, 0); while (rcWait == -1 && errno == EINTR); if (rcWait == -1) exit(1); if (WIFEXITED(iStatus) && WEXITSTATUS(iStatus) == 0) exit(0); sleep(5); ++cRespawn; } } return VINF_SUCCESS; #endif }
/** * Implementation of VbglR3Init and VbglR3InitUser */ static int vbglR3Init(const char *pszDeviceName) { uint32_t cInits = ASMAtomicIncU32(&g_cInits); Assert(cInits > 0); if (cInits > 1) { /* * This will fail if two (or more) threads race each other calling VbglR3Init. * However it will work fine for single threaded or otherwise serialized * processed calling us more than once. */ #ifdef RT_OS_WINDOWS if (g_hFile == INVALID_HANDLE_VALUE) #elif !defined (VBOX_VBGLR3_XFREE86) if (g_File == NIL_RTFILE) #else if (g_File == -1) #endif return VERR_INTERNAL_ERROR; return VINF_SUCCESS; } #if defined(RT_OS_WINDOWS) if (g_hFile != INVALID_HANDLE_VALUE) #elif !defined(VBOX_VBGLR3_XFREE86) if (g_File != NIL_RTFILE) #else if (g_File != -1) #endif return VERR_INTERNAL_ERROR; #if defined(RT_OS_WINDOWS) /* * Have to use CreateFile here as we want to specify FILE_FLAG_OVERLAPPED * and possible some other bits not available thru iprt/file.h. */ HANDLE hFile = CreateFile(pszDeviceName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (hFile == INVALID_HANDLE_VALUE) return VERR_OPEN_FAILED; g_hFile = hFile; #elif defined(RT_OS_OS2) /* * We might wish to compile this with Watcom, so stick to * the OS/2 APIs all the way. And in any case we have to use * DosDevIOCtl for the requests, why not use Dos* for everything. */ HFILE hf = NULLHANDLE; ULONG ulAction = 0; APIRET rc = DosOpen((PCSZ)pszDeviceName, &hf, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL); if (rc) return RTErrConvertFromOS2(rc); if (hf < 16) { HFILE ahfs[16]; unsigned i; for (i = 0; i < RT_ELEMENTS(ahfs); i++) { ahfs[i] = 0xffffffff; rc = DosDupHandle(hf, &ahfs[i]); if (rc) break; } if (i-- > 1) { ULONG fulState = 0; rc = DosQueryFHState(ahfs[i], &fulState); if (!rc) { fulState |= OPEN_FLAGS_NOINHERIT; fulState &= OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT; /* Turn off non-participating bits. */ rc = DosSetFHState(ahfs[i], fulState); } if (!rc) { rc = DosClose(hf); AssertMsg(!rc, ("%ld\n", rc)); hf = ahfs[i]; } else i++; while (i-- > 0) DosClose(ahfs[i]); } } g_File = (RTFILE)hf; #elif defined(VBOX_VBGLR3_XFREE86) int File = xf86open(pszDeviceName, XF86_O_RDWR); if (File == -1) return VERR_OPEN_FAILED; g_File = File; #else /* The default implementation. (linux, solaris, freebsd) */ RTFILE File; int rc = RTFileOpen(&File, pszDeviceName, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_FAILURE(rc)) return rc; g_File = File; #endif #ifndef VBOX_VBGLR3_XFREE86 /* * Create release logger */ PRTLOGGER pReleaseLogger; static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; int rc2 = RTLogCreate(&pReleaseLogger, 0, "all", "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), &s_apszGroups[0], RTLOGDEST_USER, NULL); /* This may legitimately fail if we are using the mini-runtime. */ if (RT_SUCCESS(rc2)) RTLogRelSetDefaultInstance(pReleaseLogger); #endif return VINF_SUCCESS; }
/** * Internal wrapper around various OS specific ioctl implementations. * * @returns VBox status code as returned by VBoxGuestCommonIOCtl, or * an failure returned by the OS specific ioctl APIs. * * @param iFunction The requested function. * @param pvData The input and output data buffer. * @param cbData The size of the buffer. * * @remark Exactly how the VBoxGuestCommonIOCtl is ferried back * here is OS specific. On BSD and Darwin we can use errno, * while on OS/2 we use the 2nd buffer of the IOCtl. */ int vbglR3DoIOCtl(unsigned iFunction, void *pvData, size_t cbData) { #if defined(RT_OS_WINDOWS) DWORD cbReturned = 0; if (!DeviceIoControl(g_hFile, iFunction, pvData, (DWORD)cbData, pvData, (DWORD)cbData, &cbReturned, NULL)) { /** @todo The passing of error codes needs to be tested and fixed (as does *all* the other hosts except for * OS/2). The idea is that the VBox status codes in ring-0 should be transferred without loss down to * ring-3. However, it's not vitally important right now (obviously, since the other guys has been * ignoring it for 1+ years now). On Linux and Solaris the transfer is done, but it is currently not * lossless, so still needs fixing. */ DWORD LastErr = GetLastError(); return RTErrConvertFromWin32(LastErr); } return VINF_SUCCESS; #elif defined(RT_OS_OS2) ULONG cbOS2Parm = cbData; int32_t vrc = VERR_INTERNAL_ERROR; ULONG cbOS2Data = sizeof(vrc); APIRET rc = DosDevIOCtl((uintptr_t)g_File, VBOXGUEST_IOCTL_CATEGORY, iFunction, pvData, cbData, &cbOS2Parm, &vrc, sizeof(vrc), &cbOS2Data); if (RT_LIKELY(!rc)) return vrc; return RTErrConvertFromOS2(rc); #elif defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) VBGLBIGREQ Hdr; Hdr.u32Magic = VBGLBIGREQ_MAGIC; Hdr.cbData = cbData; Hdr.pvDataR3 = pvData; # if HC_ARCH_BITS == 32 Hdr.u32Padding = 0; # endif /** @todo test status code passing! Check that the kernel doesn't do any * error checks using specific errno values, and just pass an VBox * error instead of an errno.h one. Alternatively, extend/redefine the * header with an error code return field (much better alternative * actually). */ #ifdef VBOX_VBGLR3_XFREE86 int rc = xf86ioctl(g_File, iFunction, &Hdr); #else int rc = ioctl(RTFileToNative(g_File), iFunction, &Hdr); #endif if (rc == -1) { rc = errno; return RTErrConvertFromErrno(rc); } return VINF_SUCCESS; #elif defined(RT_OS_LINUX) # ifdef VBOX_VBGLR3_XFREE86 int rc = xf86ioctl((int)g_File, iFunction, pvData); # else if (g_File == NIL_RTFILE) return VERR_INVALID_HANDLE; int rc = ioctl(RTFileToNative(g_File), iFunction, pvData); # endif if (RT_LIKELY(rc == 0)) return VINF_SUCCESS; /* Positive values are negated VBox error status codes. */ if (rc > 0) rc = -rc; else # ifdef VBOX_VBGLR3_XFREE86 rc = VERR_FILE_IO_ERROR; # else rc = RTErrConvertFromErrno(errno); # endif NOREF(cbData); return rc; #elif defined(VBOX_VBGLR3_XFREE86) /* PORTME - This is preferred over the RTFileIOCtl variant below, just be careful with the (int). */ /** @todo test status code passing! */ int rc = xf86ioctl(g_File, iFunction, pvData); if (rc == -1) return VERR_FILE_IO_ERROR; /* This is purely legacy stuff, it has to work and no more. */ return VINF_SUCCESS; #else /* Default implementation - PORTME: Do not use this without testings that passing errors works! */ /** @todo test status code passing! */ int rc2 = VERR_INTERNAL_ERROR; int rc = RTFileIoCtl(g_File, (int)iFunction, pvData, cbData, &rc2); if (RT_SUCCESS(rc)) rc = rc2; return rc; #endif }
int USBProxyServiceOs2::wait(RTMSINTERVAL aMillies) { int rc = DosWaitEventSem(mhev, aMillies); return RTErrConvertFromOS2(rc); }
/** * Implementation of VbglR3Init and VbglR3InitUser */ static int vbglR3Init(const char *pszDeviceName) { uint32_t cInits = ASMAtomicIncU32(&g_cInits); Assert(cInits > 0); if (cInits > 1) { /* * This will fail if two (or more) threads race each other calling VbglR3Init. * However it will work fine for single threaded or otherwise serialized * processed calling us more than once. */ #ifdef RT_OS_WINDOWS if (g_hFile == INVALID_HANDLE_VALUE) #elif !defined (VBOX_VBGLR3_XSERVER) if (g_File == NIL_RTFILE) #else if (g_File == -1) #endif return VERR_INTERNAL_ERROR; return VINF_SUCCESS; } #if defined(RT_OS_WINDOWS) if (g_hFile != INVALID_HANDLE_VALUE) #elif !defined(VBOX_VBGLR3_XSERVER) if (g_File != NIL_RTFILE) #else if (g_File != -1) #endif return VERR_INTERNAL_ERROR; #if defined(RT_OS_WINDOWS) /* * Have to use CreateFile here as we want to specify FILE_FLAG_OVERLAPPED * and possible some other bits not available thru iprt/file.h. */ HANDLE hFile = CreateFile(pszDeviceName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (hFile == INVALID_HANDLE_VALUE) return VERR_OPEN_FAILED; g_hFile = hFile; #elif defined(RT_OS_OS2) /* * We might wish to compile this with Watcom, so stick to * the OS/2 APIs all the way. And in any case we have to use * DosDevIOCtl for the requests, why not use Dos* for everything. */ HFILE hf = NULLHANDLE; ULONG ulAction = 0; APIRET rc = DosOpen((PCSZ)pszDeviceName, &hf, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL); if (rc) return RTErrConvertFromOS2(rc); if (hf < 16) { HFILE ahfs[16]; unsigned i; for (i = 0; i < RT_ELEMENTS(ahfs); i++) { ahfs[i] = 0xffffffff; rc = DosDupHandle(hf, &ahfs[i]); if (rc) break; } if (i-- > 1) { ULONG fulState = 0; rc = DosQueryFHState(ahfs[i], &fulState); if (!rc) { fulState |= OPEN_FLAGS_NOINHERIT; fulState &= OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT; /* Turn off non-participating bits. */ rc = DosSetFHState(ahfs[i], fulState); } if (!rc) { rc = DosClose(hf); AssertMsg(!rc, ("%ld\n", rc)); hf = ahfs[i]; } else i++; while (i-- > 0) DosClose(ahfs[i]); } } g_File = (RTFILE)hf; #elif defined(RT_OS_DARWIN) /* * Darwin is kind of special we need to engage the device via I/O first * before we open it via the BSD device node. */ mach_port_t MasterPort; kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort); if (kr != kIOReturnSuccess) return VERR_GENERAL_FAILURE; CFDictionaryRef ClassToMatch = IOServiceMatching("org_virtualbox_VBoxGuest"); if (!ClassToMatch) return VERR_GENERAL_FAILURE; io_service_t ServiceObject = IOServiceGetMatchingService(kIOMasterPortDefault, ClassToMatch); if (!ServiceObject) return VERR_NOT_FOUND; io_connect_t uConnection; kr = IOServiceOpen(ServiceObject, mach_task_self(), VBOXGUEST_DARWIN_IOSERVICE_COOKIE, &uConnection); IOObjectRelease(ServiceObject); if (kr != kIOReturnSuccess) return VERR_OPEN_FAILED; RTFILE hFile; int rc = RTFileOpen(&hFile, pszDeviceName, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_FAILURE(rc)) { IOServiceClose(uConnection); return rc; } g_File = hFile; g_uConnection = uConnection; #elif defined(VBOX_VBGLR3_XSERVER) int File = xf86open(pszDeviceName, XF86_O_RDWR); if (File == -1) return VERR_OPEN_FAILED; g_File = File; #else /* The default implementation. (linux, solaris, freebsd, haiku) */ RTFILE File; int rc = RTFileOpen(&File, pszDeviceName, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_FAILURE(rc)) return rc; g_File = File; #endif #ifndef VBOX_VBGLR3_XSERVER /* * Create release logger */ PRTLOGGER pReleaseLogger; static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; int rc2 = RTLogCreate(&pReleaseLogger, 0, "all", "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), &s_apszGroups[0], RTLOGDEST_USER, NULL); /* This may legitimately fail if we are using the mini-runtime. */ if (RT_SUCCESS(rc2)) RTLogRelSetDefaultInstance(pReleaseLogger); #endif return VINF_SUCCESS; }
DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process) { AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED); AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED); if (uAlignment > PAGE_SIZE) return VERR_NOT_SUPPORTED; int rc; void *pvR0; void *pvR3 = NULL; PRTR0MEMOBJOS2 pMemToMapOs2 = (PRTR0MEMOBJOS2)pMemToMap; switch (pMemToMapOs2->Core.enmType) { /* * These has kernel mappings. */ case RTR0MEMOBJTYPE_PAGE: case RTR0MEMOBJTYPE_LOW: case RTR0MEMOBJTYPE_CONT: pvR0 = pMemToMapOs2->Core.pv; break; case RTR0MEMOBJTYPE_PHYS: pvR0 = pMemToMapOs2->Core.pv; #if 0/* this is wrong. */ if (!pvR0) { /* no ring-0 mapping, so allocate a mapping in the process. */ AssertMsgReturn(fProt & RTMEM_PROT_WRITE, ("%#x\n", fProt), VERR_NOT_SUPPORTED); Assert(!pMemToMapOs2->Core.u.Phys.fAllocated); ULONG ulPhys = pMemToMapOs2->Core.u.Phys.PhysBase; rc = KernVMAlloc(pMemToMapOs2->Core.cb, VMDHA_PHYS | VMDHA_PROCESS, &pvR3, (PPVOID)&ulPhys, NULL); if (rc) return RTErrConvertFromOS2(rc); } break; #endif return VERR_NOT_SUPPORTED; case RTR0MEMOBJTYPE_PHYS_NC: AssertMsgFailed(("RTR0MEMOBJTYPE_PHYS_NC\n")); return VERR_INTERNAL_ERROR_5; break; case RTR0MEMOBJTYPE_LOCK: if (pMemToMapOs2->Core.u.Lock.R0Process != NIL_RTR0PROCESS) return VERR_NOT_SUPPORTED; /** @todo implement this... */ pvR0 = pMemToMapOs2->Core.pv; break; case RTR0MEMOBJTYPE_RES_VIRT: case RTR0MEMOBJTYPE_MAPPING: default: AssertMsgFailed(("enmType=%d\n", pMemToMapOs2->Core.enmType)); return VERR_INTERNAL_ERROR; } /* * Map the ring-0 memory into the current process. */ if (!pvR3) { Assert(pvR0); ULONG flFlags = 0; if (uAlignment == PAGE_SIZE) flFlags |= VMDHGP_4MB; if (fProt & RTMEM_PROT_WRITE) flFlags |= VMDHGP_WRITE; rc = RTR0Os2DHVMGlobalToProcess(flFlags, pvR0, pMemToMapOs2->Core.cb, &pvR3); if (rc) return RTErrConvertFromOS2(rc); } Assert(pvR3); /* * Create a mapping object for it. */ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_MAPPING, pvR3, pMemToMapOs2->Core.cb); if (pMemOs2) { Assert(pMemOs2->Core.pv == pvR3); pMemOs2->Core.u.Mapping.R0Process = R0Process; *ppMem = &pMemOs2->Core; return VINF_SUCCESS; } KernVMFree(pvR3); return VERR_NO_MEMORY; }
DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment, unsigned fProt, size_t offSub, size_t cbSub) { AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED); AssertMsgReturn(pvFixed == (void *)-1, ("%p\n", pvFixed), VERR_NOT_SUPPORTED); /* * Check that the specified alignment is supported. */ if (uAlignment > PAGE_SIZE) return VERR_NOT_SUPPORTED; /** @todo finish the implementation. */ int rc; void *pvR0 = NULL; PRTR0MEMOBJOS2 pMemToMapOs2 = (PRTR0MEMOBJOS2)pMemToMap; switch (pMemToMapOs2->Core.enmType) { /* * These has kernel mappings. */ case RTR0MEMOBJTYPE_PAGE: case RTR0MEMOBJTYPE_LOW: case RTR0MEMOBJTYPE_CONT: pvR0 = pMemToMapOs2->Core.pv; break; case RTR0MEMOBJTYPE_PHYS: pvR0 = pMemToMapOs2->Core.pv; if (!pvR0) { /* no ring-0 mapping, so allocate a mapping in the process. */ AssertMsgReturn(fProt & RTMEM_PROT_WRITE, ("%#x\n", fProt), VERR_NOT_SUPPORTED); Assert(!pMemToMapOs2->Core.u.Phys.fAllocated); ULONG ulPhys = pMemToMapOs2->Core.u.Phys.PhysBase; rc = KernVMAlloc(pMemToMapOs2->Core.cb, VMDHA_PHYS, &pvR0, (PPVOID)&ulPhys, NULL); if (rc) return RTErrConvertFromOS2(rc); pMemToMapOs2->Core.pv = pvR0; } break; case RTR0MEMOBJTYPE_PHYS_NC: AssertMsgFailed(("RTR0MEMOBJTYPE_PHYS_NC\n")); return VERR_INTERNAL_ERROR_3; break; case RTR0MEMOBJTYPE_LOCK: if (pMemToMapOs2->Core.u.Lock.R0Process != NIL_RTR0PROCESS) return VERR_NOT_SUPPORTED; /** @todo implement this... */ pvR0 = pMemToMapOs2->Core.pv; break; case RTR0MEMOBJTYPE_RES_VIRT: case RTR0MEMOBJTYPE_MAPPING: default: AssertMsgFailed(("enmType=%d\n", pMemToMapOs2->Core.enmType)); return VERR_INTERNAL_ERROR; } /* * Create a dummy mapping object for it. * * All mappings are read/write/execute in OS/2 and there isn't * any cache options, so sharing is ok. And the main memory object * isn't actually freed until all the mappings have been freed up * (reference counting). */ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_MAPPING, pvR0, pMemToMapOs2->Core.cb); if (pMemOs2) { pMemOs2->Core.u.Mapping.R0Process = NIL_RTR0PROCESS; *ppMem = &pMemOs2->Core; return VINF_SUCCESS; } return VERR_NO_MEMORY; }