/* Sends the given event to the UI thread. Assumes aEventID never goes out * of scope (static strings are ideal). */ nsresult nsNotifyAddrListener::SendEventToUI(const char *aEventID) { nsresult rv; if (!aEventID) return NS_ERROR_NULL_POINTER; nsCOMPtr<nsIEventQueue> eq; rv = NS_GetMainEventQ(getter_AddRefs(eq)); if (NS_FAILED(rv)) return rv; ChangeEvent *event = new ChangeEvent(aEventID); if (!event) return NS_ERROR_OUT_OF_MEMORY; // AddRef this because it is being placed in the PLEvent; it'll be Released // when DestroyInterfaceEvent is called NS_ADDREF_THIS(); PL_InitEvent(event, this, HandleInterfaceEvent, DestroyInterfaceEvent); if (NS_FAILED(rv = eq->PostEvent(event))) { NS_ERROR("failed to post event to UI EventQueue"); PL_DestroyEvent(event); } return rv; }
/* static */ int NativeEventQueue::init() { Assert(sMainQueue == NULL); Assert(RTThreadIsMain(RTThreadSelf())); try { sMainQueue = new NativeEventQueue(); AssertPtr(sMainQueue); #ifdef VBOX_WITH_XPCOM /* Check that it actually is the main event queue, i.e. that we're called on the right thread. */ nsCOMPtr<nsIEventQueue> q; nsresult rv = NS_GetMainEventQ(getter_AddRefs(q)); AssertComRCReturn(rv, VERR_INVALID_POINTER); Assert(q == sMainQueue->mEventQ); /* Check that it's a native queue. */ PRBool fIsNative = PR_FALSE; rv = sMainQueue->mEventQ->IsQueueNative(&fIsNative); Assert(NS_SUCCEEDED(rv) && fIsNative); #endif // VBOX_WITH_XPCOM } catch (std::bad_alloc &ba) { NOREF(ba); return VERR_NO_MEMORY; } return VINF_SUCCESS; }
~nsUrlClassifierCallbackWrapper() { nsCOMPtr<nsIEventQueue> mainEventQ; NS_GetMainEventQ(getter_AddRefs(mainEventQ)); if (mainEventQ) { NS_ProxyRelease(mainEventQ, mInner); } else { NS_WARNING("unable to get main event queue"); } }
int main(int argc, char **argv) { if (test_common_init(&argc, &argv) != 0) return -1; if (argc < 2) { printf("usage: %s <url>\n", argv[0]); return -1; } #if defined(PR_LOGGING) gTestLog = PR_NewLogModule("Test"); #endif nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull); if (NS_FAILED(rv)) return -1; { // Create the Event Queue for this thread... rv = NS_GetMainEventQ(&gEventQ); if (NS_FAILED(rv)) return -1; nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), nsDependentCString(argv[1])); if (NS_FAILED(rv)) return -1; nsCOMPtr<nsIChannel> chan; rv = NS_NewChannel(getter_AddRefs(chan), uri); if (NS_FAILED(rv)) return -1; nsCOMPtr<nsIStreamLoaderObserver> observer = new MyStreamLoaderObserver(); if (!observer) return -1; nsCOMPtr<nsIStreamLoader> loader; rv = NS_NewStreamLoader(getter_AddRefs(loader), chan, observer, nsnull); if (NS_FAILED(rv)) return -1; // Enter the message pump to allow the URL load to proceed. while (gKeepRunning) { PLEvent *e; gEventQ->WaitForEvent(&e); gEventQ->HandleEvent(e); } } // this scopes the nsCOMPtrs // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM NS_ShutdownXPCOM(nsnull); return rv; }
bool VirtualBoxBridge::initXPCOM() { nsresult rc; /* * This is the standard XPCOM init procedure. * What we do is just follow the required steps to get an instance * of our main interface, which is IVirtualBox. * * Note that we scope all nsCOMPtr variables in order to have all XPCOM * objects automatically released before we call NS_ShutdownXPCOM at the * end. This is an XPCOM requirement. */ rc = NS_InitXPCOM2(getter_AddRefs(nsCOM_serviceManager), nsnull, nsnull); if (NS_FAILED(rc)) { std::cerr << "Error: XPCOM could not be initialized! rc=0x" << std::hex << rc << std::dec << std::endl; return false; } /* * Make sure the main event queue is created. This event queue is * responsible for dispatching incoming XPCOM IPC messages. The main * thread should run this event queue's loop during lengthy non-XPCOM * operations to ensure messages from the VirtualBox server and other * XPCOM IPC clients are processed. This use case doesn't perform such * operations so it doesn't run the event loop. */ rc = NS_GetMainEventQ(getter_AddRefs(nsCOM_eventQ)); if (NS_FAILED(rc)) { std::cerr << "Error: could not get main event queue! rc=0x" << std::hex << rc << std::dec << std::endl; return false; } /* * Now XPCOM is ready and we can start to do real work. * All interfaces will be retrieved from the XPCOM component manager. * We use the XPCOM provided smart pointer nsCOMPtr for all objects * because that's very convenient and removes the need deal with * reference counting and freeing. */ rc = NS_GetComponentManager(getter_AddRefs(nsCOM_manager)); if (NS_FAILED(rc)) { std::cerr << "Error: could not get component manager! rc=0x" << std::hex << rc << std::dec << std::endl; return false; } return true; }
/* static */ int EventQueue::init() { Assert(sMainQueue == NULL); Assert(RTThreadIsMain(RTThreadSelf())); sMainQueue = new EventQueue(); #ifdef VBOX_WITH_XPCOM /* Check that it actually is the main event queue, i.e. that we're called on the right thread. */ nsCOMPtr<nsIEventQueue> q; nsresult rv = NS_GetMainEventQ(getter_AddRefs(q)); Assert(NS_SUCCEEDED(rv)); Assert(q == sMainQueue->mEventQ); /* Check that it's a native queue. */ PRBool fIsNative = PR_FALSE; rv = sMainQueue->mEventQ->IsQueueNative(&fIsNative); Assert(NS_SUCCEEDED(rv) && fIsNative); #endif // VBOX_WITH_XPCOM return VINF_SUCCESS; }
int main(int argc, char *argv[]) { /* * Check that PRUnichar is equal in size to what compiler composes L"" * strings from; otherwise NS_LITERAL_STRING macros won't work correctly * and we will get a meaningless SIGSEGV. This, of course, must be checked * at compile time in xpcom/string/nsTDependentString.h, but XPCOM lacks * compile-time assert macros and I'm not going to add them now. */ if (sizeof(PRUnichar) != sizeof(wchar_t)) { printf("Error: sizeof(PRUnichar) {%lu} != sizeof(wchar_t) {%lu}!\n" "Probably, you forgot the -fshort-wchar compiler option.\n", (unsigned long) sizeof(PRUnichar), (unsigned long) sizeof(wchar_t)); return -1; } nsresult rc; /* * This is the standard XPCOM init procedure. * What we do is just follow the required steps to get an instance * of our main interface, which is IVirtualBox. */ #if defined(XPCOM_GLUE) XPCOMGlueStartup(nsnull); #endif /* * Note that we scope all nsCOMPtr variables in order to have all XPCOM * objects automatically released before we call NS_ShutdownXPCOM at the * end. This is an XPCOM requirement. */ { nsCOMPtr<nsIServiceManager> serviceManager; rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), nsnull, nsnull); if (NS_FAILED(rc)) { printf("Error: XPCOM could not be initialized! rc=0x%x\n", rc); return -1; } #if 0 /* * Register our components. This step is only necessary if this executable * implements XPCOM components itself which is not the case for this * simple example. */ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager); if (!registrar) { printf("Error: could not query nsIComponentRegistrar interface!\n"); return -1; } registrar->AutoRegister(nsnull); #endif /* * Make sure the main event queue is created. This event queue is * responsible for dispatching incoming XPCOM IPC messages. The main * thread should run this event queue's loop during lengthy non-XPCOM * operations to ensure messages from the VirtualBox server and other * XPCOM IPC clients are processed. This use case doesn't perform such * operations so it doesn't run the event loop. */ nsCOMPtr<nsIEventQueue> eventQ; rc = NS_GetMainEventQ(getter_AddRefs (eventQ)); if (NS_FAILED(rc)) { printf("Error: could not get main event queue! rc=%08X\n", rc); return -1; } /* * Now XPCOM is ready and we can start to do real work. * IVirtualBox is the root interface of VirtualBox and will be * retrieved from the XPCOM component manager. We use the * XPCOM provided smart pointer nsCOMPtr for all objects because * that's very convenient and removes the need deal with reference * counting and freeing. */ nsCOMPtr<nsIComponentManager> manager; rc = NS_GetComponentManager (getter_AddRefs (manager)); if (NS_FAILED(rc)) { printf("Error: could not get component manager! rc=%08X\n", rc); return -1; } nsCOMPtr<IVirtualBox> virtualBox; rc = manager->CreateInstanceByContractID (NS_VIRTUALBOX_CONTRACTID, nsnull, NS_GET_IID(IVirtualBox), getter_AddRefs(virtualBox)); if (NS_FAILED(rc)) { printf("Error, could not instantiate VirtualBox object! rc=0x%x\n", rc); return -1; } printf("VirtualBox object created\n"); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// listVMs(virtualBox); createVM(virtualBox); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /* this is enough to free the IVirtualBox instance -- smart pointers rule! */ virtualBox = nsnull; /* * Process events that might have queued up in the XPCOM event * queue. If we don't process them, the server might hang. */ eventQ->ProcessPendingEvents(); } /* * Perform the standard XPCOM shutdown procedure. */ NS_ShutdownXPCOM(nsnull); #if defined(XPCOM_GLUE) XPCOMGlueShutdown(); #endif printf("Done!\n"); return 0; }
HRESULT Shutdown() { HRESULT rc = S_OK; #if !defined(VBOX_WITH_XPCOM) /* EventQueue::uninit reference counting fun. */ RTTHREAD hSelf = RTThreadSelf(); if ( hSelf == gCOMMainThread && hSelf != NIL_RTTHREAD) { if (-- gCOMMainInitCount == 0) { EventQueue::uninit(); ASMAtomicWriteHandle(&gCOMMainThread, NIL_RTTHREAD); } } CoUninitialize(); #else /* !defined (VBOX_WITH_XPCOM) */ nsCOMPtr<nsIEventQueue> eventQ; rc = NS_GetMainEventQ(getter_AddRefs(eventQ)); if (NS_SUCCEEDED(rc) || rc == NS_ERROR_NOT_AVAILABLE) { /* NS_ERROR_NOT_AVAILABLE seems to mean that * nsIEventQueue::StopAcceptingEvents() has been called (see * nsEventQueueService.cpp). We hope that this error code always means * just that in this case and assume that we're on the main thread * (it's a kind of unexpected behavior if a non-main thread ever calls * StopAcceptingEvents() on the main event queue). */ PRBool isOnMainThread = PR_FALSE; if (NS_SUCCEEDED(rc)) { rc = eventQ->IsOnCurrentThread(&isOnMainThread); eventQ = nsnull; /* early release before shutdown */ } else { isOnMainThread = PR_TRUE; rc = NS_OK; } if (NS_SUCCEEDED(rc) && isOnMainThread) { /* only the main thread needs to uninitialize XPCOM and only if * init counter drops to zero */ if (--gXPCOMInitCount == 0) { EventQueue::uninit(); rc = NS_ShutdownXPCOM(nsnull); /* This is a thread initialized XPCOM and set gIsXPCOMInitialized to * true. Reset it back to false. */ bool wasInited = ASMAtomicXchgBool(&gIsXPCOMInitialized, false); Assert(wasInited == true); NOREF(wasInited); # if defined (XPCOM_GLUE) XPCOMGlueShutdown(); # endif } } } #endif /* !defined(VBOX_WITH_XPCOM) */ AssertComRC(rc); return rc; }
/** * Initializes the COM runtime. * * This method must be called on each thread of the client application that * wants to access COM facilities. The initialization must be performed before * calling any other COM method or attempting to instantiate COM objects. * * On platforms using XPCOM, this method uses the following scheme to search for * XPCOM runtime: * * 1. If the VBOX_APP_HOME environment variable is set, the path it specifies * is used to search XPCOM libraries and components. If this method fails to * initialize XPCOM runtime using this path, it will immediately return a * failure and will NOT check for other paths as described below. * * 2. If VBOX_APP_HOME is not set, this methods tries the following paths in the * given order: * * a) Compiled-in application data directory (as returned by * RTPathAppPrivateArch()) * b) "/usr/lib/virtualbox" (Linux only) * c) "/opt/VirtualBox" (Linux only) * * The first path for which the initialization succeeds will be used. * * On MS COM platforms, the COM runtime is provided by the system and does not * need to be searched for. * * Once the COM subsystem is no longer necessary on a given thread, Shutdown() * must be called to free resources allocated for it. Note that a thread may * call Initialize() several times but for each of tese calls there must be a * corresponding Shutdown() call. * * @return S_OK on success and a COM result code in case of failure. */ HRESULT Initialize(bool fGui) { HRESULT rc = E_FAIL; #if !defined(VBOX_WITH_XPCOM) /* * We initialize COM in GUI thread in STA, to be compliant with QT and * OLE requirments (for example to allow D&D), while other threads * initialized in regular MTA. To allow fast proxyless access from * GUI thread to COM objects, we explicitly provide our COM objects * with free threaded marshaller. * !!!!! Please think twice before touching this code !!!!! */ DWORD flags = fGui ? COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY : COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE | COINIT_SPEED_OVER_MEMORY; rc = CoInitializeEx(NULL, flags); /* the overall result must be either S_OK or S_FALSE (S_FALSE means * "already initialized using the same apartment model") */ AssertMsg(rc == S_OK || rc == S_FALSE, ("rc=%08X\n", rc)); /* To be flow compatible with the XPCOM case, we return here if this isn't * the main thread or if it isn't its first initialization call. * Note! CoInitializeEx and CoUninitialize does it's own reference * counting, so this exercise is entirely for the EventQueue init. */ bool fRc; RTTHREAD hSelf = RTThreadSelf(); if (hSelf != NIL_RTTHREAD) ASMAtomicCmpXchgHandle(&gCOMMainThread, hSelf, NIL_RTTHREAD, fRc); else fRc = false; if (fGui) Assert(RTThreadIsMain(hSelf)); if (!fRc) { if ( gCOMMainThread == hSelf && SUCCEEDED(rc)) gCOMMainInitCount++; AssertComRC(rc); return rc; } Assert(RTThreadIsMain(hSelf)); /* this is the first main thread initialization */ Assert(gCOMMainInitCount == 0); if (SUCCEEDED(rc)) gCOMMainInitCount = 1; #else /* !defined (VBOX_WITH_XPCOM) */ /* Unused here */ NOREF(fGui); if (ASMAtomicXchgBool(&gIsXPCOMInitialized, true) == true) { /* XPCOM is already initialized on the main thread, no special * initialization is necessary on additional threads. Just increase * the init counter if it's a main thread again (to correctly support * nested calls to Initialize()/Shutdown() for compatibility with * Win32). */ nsCOMPtr<nsIEventQueue> eventQ; rc = NS_GetMainEventQ(getter_AddRefs(eventQ)); if (NS_SUCCEEDED(rc)) { PRBool isOnMainThread = PR_FALSE; rc = eventQ->IsOnCurrentThread(&isOnMainThread); if (NS_SUCCEEDED(rc) && isOnMainThread) ++gXPCOMInitCount; } AssertComRC(rc); return rc; } Assert(RTThreadIsMain(RTThreadSelf())); /* this is the first initialization */ gXPCOMInitCount = 1; bool const fInitEventQueues = true; /* prepare paths for registry files */ char szCompReg[RTPATH_MAX]; char szXptiDat[RTPATH_MAX]; int vrc = GetVBoxUserHomeDirectory(szCompReg, sizeof(szCompReg)); AssertRCReturn(vrc, NS_ERROR_FAILURE); strcpy(szXptiDat, szCompReg); vrc = RTPathAppend(szCompReg, sizeof(szCompReg), "compreg.dat"); AssertRCReturn(vrc, NS_ERROR_FAILURE); vrc = RTPathAppend(szXptiDat, sizeof(szXptiDat), "xpti.dat"); AssertRCReturn(vrc, NS_ERROR_FAILURE); LogFlowFunc(("component registry : \"%s\"\n", szCompReg)); LogFlowFunc(("XPTI data file : \"%s\"\n", szXptiDat)); #if defined (XPCOM_GLUE) XPCOMGlueStartup(nsnull); #endif static const char *kAppPathsToProbe[] = { NULL, /* 0: will use VBOX_APP_HOME */ NULL, /* 1: will try RTPathAppPrivateArch() */ #ifdef RT_OS_LINUX "/usr/lib/virtualbox", "/opt/VirtualBox", #elif RT_OS_SOLARIS "/opt/VirtualBox/amd64", "/opt/VirtualBox/i386", #elif RT_OS_DARWIN "/Application/VirtualBox.app/Contents/MacOS", #endif }; /* Find out the directory where VirtualBox binaries are located */ for (size_t i = 0; i < RT_ELEMENTS(kAppPathsToProbe); ++ i) { char szAppHomeDir[RTPATH_MAX]; if (i == 0) { /* Use VBOX_APP_HOME if present */ vrc = RTEnvGetEx(RTENV_DEFAULT, "VBOX_APP_HOME", szAppHomeDir, sizeof(szAppHomeDir), NULL); if (vrc == VERR_ENV_VAR_NOT_FOUND) continue; AssertRC(vrc); } else if (i == 1) { /* Use RTPathAppPrivateArch() first */ vrc = RTPathAppPrivateArch(szAppHomeDir, sizeof(szAppHomeDir)); AssertRC(vrc); } else { /* Iterate over all other paths */ szAppHomeDir[RTPATH_MAX - 1] = '\0'; strncpy(szAppHomeDir, kAppPathsToProbe[i], RTPATH_MAX - 1); vrc = VINF_SUCCESS; } if (RT_FAILURE(vrc)) { rc = NS_ERROR_FAILURE; continue; } char szCompDir[RTPATH_MAX]; vrc = RTPathAppend(strcpy(szCompDir, szAppHomeDir), sizeof(szCompDir), "components"); if (RT_FAILURE(vrc)) { rc = NS_ERROR_FAILURE; continue; } LogFlowFunc(("component directory : \"%s\"\n", szCompDir)); nsCOMPtr<DirectoryServiceProvider> dsProv; dsProv = new DirectoryServiceProvider(); if (dsProv) rc = dsProv->init(szCompReg, szXptiDat, szCompDir, szAppHomeDir); else rc = NS_ERROR_OUT_OF_MEMORY; if (NS_FAILED(rc)) break; /* Setup the application path for NS_InitXPCOM2. Note that we properly * answer the NS_XPCOM_CURRENT_PROCESS_DIR query in our directory * service provider but it seems to be activated after the directory * service is used for the first time (see the source NS_InitXPCOM2). So * use the same value here to be on the safe side. */ nsCOMPtr <nsIFile> appDir; { char *appDirCP = NULL; vrc = RTStrUtf8ToCurrentCP(&appDirCP, szAppHomeDir); if (RT_SUCCESS(vrc)) { nsCOMPtr<nsILocalFile> file; rc = NS_NewNativeLocalFile(nsEmbedCString(appDirCP), PR_FALSE, getter_AddRefs(file)); if (NS_SUCCEEDED(rc)) appDir = do_QueryInterface(file, &rc); RTStrFree(appDirCP); } else rc = NS_ERROR_FAILURE; } if (NS_FAILED(rc)) break; /* Set VBOX_XPCOM_HOME to the same app path to make XPCOM sources that * still use it instead of the directory service happy */ vrc = RTEnvSetEx(RTENV_DEFAULT, "VBOX_XPCOM_HOME", szAppHomeDir); AssertRC(vrc); /* Finally, initialize XPCOM */ { nsCOMPtr<nsIServiceManager> serviceManager; rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), appDir, dsProv); if (NS_SUCCEEDED(rc)) { nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager, &rc); if (NS_SUCCEEDED(rc)) { rc = registrar->AutoRegister(nsnull); if (NS_SUCCEEDED(rc)) { /* We succeeded, stop probing paths */ LogFlowFunc(("Succeeded.\n")); break; } } } } /* clean up before the new try */ rc = NS_ShutdownXPCOM(nsnull); if (i == 0) { /* We failed with VBOX_APP_HOME, don't probe other paths */ break; } } #endif /* !defined (VBOX_WITH_XPCOM) */ // for both COM and XPCOM, we only get here if this is the main thread; // only then initialize the autolock system (AutoLock.cpp) Assert(RTThreadIsMain(RTThreadSelf())); util::InitAutoLockSystem(); AssertComRC(rc); /* * Init the main event queue (ASSUMES it cannot fail). */ if (SUCCEEDED(rc)) EventQueue::init(); return rc; }
/** entry point */ int main(int argc, char *argv[]) { const char *uuid = NULL; int c; int listHostModes = 0; int quit = 0; const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "startvm", required_argument, NULL, 's' }, { "fixedres", required_argument, NULL, 'f' }, { "listhostmodes", no_argument, NULL, 'l' }, { "scale", no_argument, NULL, 'c' } }; printf("VirtualBox DirectFB GUI built %s %s\n" "(C) 2004-" VBOX_C_YEAR " " VBOX_VENDOR "\n" "(C) 2004-2005 secunet Security Networks AG\n", __DATE__, __TIME__); for (;;) { c = getopt_long(argc, argv, "s:", options, NULL); if (c == -1) break; switch (c) { case 'h': { showusage(); exit(0); break; } case 's': { // UUID as string, parse it RTUUID buuid; if (!RT_SUCCESS(RTUuidFromStr((PRTUUID)&buuid, optarg))) { printf("Error, invalid UUID format given!\n"); showusage(); exit(-1); } uuid = optarg; break; } case 'f': { if (sscanf(optarg, "%ux%ux%u", &fixedVideoMode.width, &fixedVideoMode.height, &fixedVideoMode.bpp) != 3) { printf("Error, invalid resolution argument!\n"); showusage(); exit(-1); } useFixedVideoMode = 1; break; } case 'l': { listHostModes = 1; break; } case 'c': { scaleGuest = 1; break; } default: break; } } // check if we got a UUID if (!uuid) { printf("Error, no UUID given!\n"); showusage(); exit(-1); } /** * XPCOM setup */ nsresult rc; /* * Note that we scope all nsCOMPtr variables in order to have all XPCOM * objects automatically released before we call NS_ShutdownXPCOM at the * end. This is an XPCOM requirement. */ { nsCOMPtr<nsIServiceManager> serviceManager; rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), nsnull, nsnull); if (NS_FAILED(rc)) { printf("Error: XPCOM could not be initialized! rc=0x%x\n", rc); exit(-1); } // register our component nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager); if (!registrar) { printf("Error: could not query nsIComponentRegistrar interface!\n"); exit(-1); } registrar->AutoRegister(nsnull); /* * Make sure the main event queue is created. This event queue is * responsible for dispatching incoming XPCOM IPC messages. The main * thread should run this event queue's loop during lengthy non-XPCOM * operations to ensure messages from the VirtualBox server and other * XPCOM IPC clients are processed. This use case doesn't perform such * operations so it doesn't run the event loop. */ nsCOMPtr<nsIEventQueue> eventQ; rc = NS_GetMainEventQ(getter_AddRefs (eventQ)); if (NS_FAILED(rc)) { printf("Error: could not get main event queue! rc=%08X\n", rc); return -1; } /* * Now XPCOM is ready and we can start to do real work. * IVirtualBox is the root interface of VirtualBox and will be * retrieved from the XPCOM component manager. We use the * XPCOM provided smart pointer nsCOMPtr for all objects because * that's very convenient and removes the need deal with reference * counting and freeing. */ nsCOMPtr<nsIComponentManager> manager; rc = NS_GetComponentManager (getter_AddRefs (manager)); if (NS_FAILED(rc)) { printf("Error: could not get component manager! rc=%08X\n", rc); exit(-1); } nsCOMPtr<IVirtualBox> virtualBox; rc = manager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID, nsnull, NS_GET_IID(IVirtualBox), getter_AddRefs(virtualBox)); if (NS_FAILED(rc)) { printf("Error, could not instantiate object! rc=0x%x\n", rc); exit(-1); } nsCOMPtr<ISession> session; rc = manager->CreateInstance(CLSID_Session, nsnull, NS_GET_IID(ISession), getter_AddRefs(session)); if (NS_FAILED(rc)) { printf("Error: could not instantiate Session object! rc = %08X\n", rc); exit(-1); } // open session for this VM rc = virtualBox->OpenSession(session, NS_ConvertUTF8toUTF16(uuid).get()); if (NS_FAILED(rc)) { printf("Error: given machine not found!\n"); exit(-1); } nsCOMPtr<IMachine> machine; session->GetMachine(getter_AddRefs(machine)); if (!machine) { printf("Error: given machine not found!\n"); exit(-1); } nsCOMPtr<IConsole> console; session->GetConsole(getter_AddRefs(console)); if (!console) { printf("Error: cannot get console!\n"); exit(-1); } nsCOMPtr<IDisplay> display; console->GetDisplay(getter_AddRefs(display)); if (!display) { printf("Error: could not get display object!\n"); exit(-1); } nsCOMPtr<IKeyboard> keyboard; nsCOMPtr<IMouse> mouse; VBoxDirectFB *frameBuffer = NULL; /** * Init DirectFB */ IDirectFB *dfb = NULL; IDirectFBSurface *surface = NULL; IDirectFBInputDevice *dfbKeyboard = NULL; IDirectFBInputDevice *dfbMouse = NULL; IDirectFBEventBuffer *dfbEventBuffer = NULL; DFBSurfaceDescription dsc; int screen_width, screen_height; DFBCHECK(DirectFBInit(&argc, &argv)); DFBCHECK(DirectFBCreate(&dfb)); DFBCHECK(dfb->SetCooperativeLevel(dfb, DFSCL_FULLSCREEN)); // populate our structure of supported video modes DFBCHECK(dfb->EnumVideoModes(dfb, enumVideoModesHandler, NULL)); if (listHostModes) { printf("*****************************************************\n"); printf("Number of available host video modes: %u\n", numVideoModes); for (uint32_t i = 0; i < numVideoModes; i++) { printf("Mode %u: xres = %u, yres = %u, bpp = %u\n", i, videoModes[i].width, videoModes[i].height, videoModes[i].bpp); } printf("Note: display modes with bpp < have been filtered out\n"); printf("*****************************************************\n"); goto Leave; } if (useFixedVideoMode) { int32_t bestVideoMode = getBestVideoMode(fixedVideoMode.width, fixedVideoMode.height, fixedVideoMode.bpp); // validate the fixed mode if ((bestVideoMode == -1) || ((fixedVideoMode.width != videoModes[bestVideoMode].width) || (fixedVideoMode.height != videoModes[bestVideoMode].height) || (fixedVideoMode.bpp != videoModes[bestVideoMode].bpp))) { printf("Error: the specified fixed video mode is not available!\n"); exit(-1); } } else { initialVideoMode = getBestVideoMode(640, 480, 16); if (initialVideoMode == -1) { printf("Error: initial video mode 640x480x16 is not available!\n"); exit(-1); } } dsc.flags = DSDESC_CAPS; dsc.caps = DSCAPS_PRIMARY; DFBCHECK(dfb->CreateSurface(dfb, &dsc, &surface)); DFBCHECK(surface->Clear(surface, 0, 0, 0, 0)); DFBCHECK(surface->GetSize(surface, &screen_width, &screen_height)); DFBCHECK(dfb->GetInputDevice(dfb, DIDID_KEYBOARD, &dfbKeyboard)); DFBCHECK(dfbKeyboard->CreateEventBuffer(dfbKeyboard, &dfbEventBuffer)); DFBCHECK(dfb->GetInputDevice(dfb, DIDID_MOUSE, &dfbMouse)); DFBCHECK(dfbMouse->AttachEventBuffer(dfbMouse, dfbEventBuffer)); if (useFixedVideoMode) { printf("Information: setting video mode to %ux%ux%u\n", fixedVideoMode.width, fixedVideoMode.height, fixedVideoMode.bpp); DFBCHECK(dfb->SetVideoMode(dfb, fixedVideoMode.width, fixedVideoMode.height, fixedVideoMode.bpp)); } else { printf("Information: starting with default video mode %ux%ux%u\n", videoModes[initialVideoMode].width, videoModes[initialVideoMode].height, videoModes[initialVideoMode].bpp); DFBCHECK(dfb->SetVideoMode(dfb, videoModes[initialVideoMode].width, videoModes[initialVideoMode].height, videoModes[initialVideoMode].bpp)); } // register our framebuffer frameBuffer = new VBoxDirectFB(dfb, surface); display->SetFramebuffer(0, frameBuffer); /** * Start the VM execution thread */ console->PowerUp(NULL); console->GetKeyboard(getter_AddRefs(keyboard)); console->GetMouse(getter_AddRefs(mouse)); /** * Main event loop */ #define MAX_KEYEVENTS 10 PRInt32 keyEvents[MAX_KEYEVENTS]; int numKeyEvents; while (!quit) { DFBInputEvent event; numKeyEvents = 0; DFBCHECK(dfbEventBuffer->WaitForEvent(dfbEventBuffer)); while (dfbEventBuffer->GetEvent(dfbEventBuffer, DFB_EVENT(&event)) == DFB_OK) { int mouseXDelta = 0; int mouseYDelta = 0; int mouseZDelta = 0; switch (event.type) { #define QUEUEEXT() keyEvents[numKeyEvents++] = 0xe0 #define QUEUEKEY(scan) keyEvents[numKeyEvents++] = scan | (event.type == DIET_KEYRELEASE ? 0x80 : 0x00) #define QUEUEKEYRAW(scan) keyEvents[numKeyEvents++] = scan case DIET_KEYPRESS: case DIET_KEYRELEASE: { // @@@AH development hack to get out of it! if ((event.key_id == DIKI_ESCAPE) && (event.modifiers & (DIMM_CONTROL | DIMM_ALT))) quit = 1; if (numKeyEvents < MAX_KEYEVENTS) { //printf("%s: key_code: 0x%x\n", event.type == DIET_KEYPRESS ? "DIET_KEYPRESS" : "DIET_KEYRELEASE", event.key_code); switch ((uint32_t)event.key_id) { case DIKI_CONTROL_R: QUEUEEXT(); QUEUEKEY(0x1d); break; case DIKI_INSERT: QUEUEEXT(); QUEUEKEY(0x52); break; case DIKI_DELETE: QUEUEEXT(); QUEUEKEY(0x53); break; case DIKI_HOME: QUEUEEXT(); QUEUEKEY(0x47); break; case DIKI_END: QUEUEEXT(); QUEUEKEY(0x4f); break; case DIKI_PAGE_UP: QUEUEEXT(); QUEUEKEY(0x49); break; case DIKI_PAGE_DOWN: QUEUEEXT(); QUEUEKEY(0x51); break; case DIKI_LEFT: QUEUEEXT(); QUEUEKEY(0x4b); break; case DIKI_RIGHT: QUEUEEXT(); QUEUEKEY(0x4d); break; case DIKI_UP: QUEUEEXT(); QUEUEKEY(0x48); break; case DIKI_DOWN: QUEUEEXT(); QUEUEKEY(0x50); break; case DIKI_KP_DIV: QUEUEEXT(); QUEUEKEY(0x35); break; case DIKI_KP_ENTER: QUEUEEXT(); QUEUEKEY(0x1c); break; case DIKI_PRINT: // the break code is inverted! if (event.type == DIET_KEYPRESS) { QUEUEEXT(); QUEUEKEY(0x2a); QUEUEEXT(); QUEUEKEY(0x37); } else { QUEUEEXT(); QUEUEKEY(0x37); QUEUEEXT(); QUEUEKEY(0x2a); } break; case DIKI_PAUSE: // This is a super weird key. No break code and a 6 byte // combination. if (event.type == DIET_KEYPRESS) { QUEUEKEY(0xe1); QUEUEKEY(0x1d); QUEUEKEY(0x45); QUEUEKEY(0xe1); QUEUEKEY(0x9d); QUEUEKEY(0xc5); } break; case DIKI_META_L: // the left Windows logo is a bit different if (event.type == DIET_KEYPRESS) { QUEUEEXT(); QUEUEKEYRAW(0x1f); } else { QUEUEEXT(); QUEUEKEYRAW(0xf0); QUEUEKEYRAW(0x1f); } break; case DIKI_META_R: // the right Windows logo is a bit different if (event.type == DIET_KEYPRESS) { QUEUEEXT(); QUEUEKEYRAW(0x27); } else { QUEUEEXT(); QUEUEKEYRAW(0xf0); QUEUEKEYRAW(0x27); } break; case DIKI_SUPER_R: // the popup menu is a bit different if (event.type == DIET_KEYPRESS) { QUEUEEXT(); QUEUEKEYRAW(0x2f); } else { QUEUEEXT(); QUEUEKEYRAW(0xf0); QUEUEKEYRAW(0x2f); } break; default: // check if we got a hardware scancode if (event.key_code != -1) { // take the scancode from DirectFB as is QUEUEKEY(event.key_code); } else { // XXX need extra handling! } } } break; } #undef QUEUEEXT #undef QUEUEKEY #undef QUEUEKEYRAW case DIET_AXISMOTION: { switch (event.axis) { case DIAI_X: mouseXDelta += event.axisrel; break; case DIAI_Y: mouseYDelta += event.axisrel; break; case DIAI_Z: mouseZDelta += event.axisrel; break; default: break; } // fall through } case DIET_BUTTONPRESS: // fall through; case DIET_BUTTONRELEASE: { int buttonState = 0; if (event.buttons & DIBM_LEFT) buttonState |= MouseButtonState::LeftButton; if (event.buttons & DIBM_RIGHT) buttonState |= MouseButtonState::RightButton; if (event.buttons & DIBM_MIDDLE) buttonState |= MouseButtonState::MiddleButton; mouse->PutMouseEvent(mouseXDelta, mouseYDelta, mouseZDelta, buttonState); break; } default: break; } } // did we get any keyboard events? if (numKeyEvents > 0) { uint32_t codesStored; if (numKeyEvents > 1) { keyboard->PutScancodes(numKeyEvents, keyEvents, &codesStored); } else { keyboard->PutScancode(keyEvents[0]); } } } { nsCOMPtr<IProgress> progress; console->PowerDown(getter_AddRefs(progress)); progress->WaitForCompletion(-1); } } Leave: /* * Perform the standard XPCOM shutdown procedure. */ NS_ShutdownXPCOM(nsnull); return 0; }