/** * 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; }
/** * 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; }