ExtPackManagerImpl.cpp revision 8479df0918362ee801608d4f48c6d8ee8fdf505e
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * VirtualBox Main - interface for Extension Packs, VBoxSVC & VBoxC.
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2010 Oracle Corporation
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * available from http://www.virtualbox.org. This file is free software;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * you can redistribute it and/or modify it under the terms of the GNU
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * General Public License (GPL) as published by the Free Software
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync/*******************************************************************************
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync* Header Files *
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync*******************************************************************************/
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync/*******************************************************************************
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync* Defined Constants And Macros *
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync*******************************************************************************/
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync/** @name VBOX_EXTPACK_HELPER_NAME
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * The name of the utility application we employ to install and uninstall the
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * extension packs. This is a set-uid-to-root binary on unixy platforms, which
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * is why it has to be a separate application.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync# define VBOX_EXTPACK_HELPER_NAME "VBoxExtPackHelper.exe"
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync# define VBOX_EXTPACK_HELPER_NAME "VBoxExtPackHelper"
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync/*******************************************************************************
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync* Structures and Typedefs *
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync*******************************************************************************/
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Private extension pack data.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync /** The extension pack descriptor (loaded from the XML, mostly). */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync /** The file system object info of the XML file.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * This is for detecting changes and save time in refresh(). */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync /** Whether it's usable or not. */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync /** Why it is unusable. */
730f8be51b729e8a3c1e32c756cd0f4ec088dd4dvboxsync /** Where the extension pack is located. */
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync /** The file system object info of the extension pack directory.
730f8be51b729e8a3c1e32c756cd0f4ec088dd4dvboxsync * This is for detecting changes and save time in refresh(). */
77db08a24f69bca943d5abc40b1930ee97f593edvboxsync /** The full path to the main module. */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /** The file system object info of the main module.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * This is used to determin whether to bother try reload it. */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /** The module handle of the main extension pack module. */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /** The helper callbacks for the extension pack. */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /** Pointer back to the extension pack object (for Hlp methods). */
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync /** The extension pack registration structure. */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync/** List of extension packs. */
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsynctypedef std::list< ComObjPtr<ExtPack> > ExtPackList;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Private extension pack manager data.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /** The directory where the extension packs are installed. */
aa131431882ca8e44b0480d4af0b5d139f1bde21vboxsync /** The directory where the extension packs can be dropped for automatic
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * installation. */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /** The directory where the certificates this installation recognizes are
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * stored. */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync /** The list of installed extension packs. */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Called by ComObjPtr::createObject when creating the object.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Just initialize the basic object state, do the rest in init().
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @returns S_OK.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * Initializes the extension pack by reading its file.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * @returns COM status code.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * @param a_pszName The name of the extension pack. This is also the
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * name of the subdirector under @a a_pszParentDir
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * where the extension pack is installed.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * @param a_pszParentDir The parent directory.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsyncHRESULT ExtPack::init(const char *a_pszName, const char *a_pszParentDir)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync /* uVBoxVersionRevision = */ 0,
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync /* u32Padding = */ 0,
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * Figure out where we live and allocate + initialize our private data.
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync int vrc = RTPathJoin(szDir, sizeof(szDir), a_pszParentDir, a_pszName);
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync * Probe the extension pack (this code is shared with refresh()).
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * COM cruft.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Do the actual cleanup.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync /* Enclose the state transition Ready->InUninit->NotReady */
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * Calls the installed hook.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * @remarks Caller holds the extension manager lock.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Calls the uninstall hook and closes the module.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @returns S_OK or COM error status with error information.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param a_fForcedRemoval When set, we'll ignore complaints from the
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * uninstall hook.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @remarks The caller holds the manager's write lock.
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsyncHRESULT ExtPack::callUninstallHookAndClose(bool a_fForcedRemoval)
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync LogRel(("ExtPack pfnUninstall returned %Rrc for %s\n", vrc, m->Desc.strName.c_str()));
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync hrc = setError(E_FAIL, tr("pfnUninstall returned %Rrc"), vrc);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * Calls the pfnVMCreate hook.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * @param a_pMachine The machine interface of the new VM.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * @remarks Caller holds the extension manager lock.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsyncvoid ExtPack::callVmCreatedHook(IMachine *a_pMachine)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Calls the pfnVMConfigureVMM hook.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * @returns VBox status code, LogRel called on failure.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * @param a_pConsole The console interface.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * @param a_pVM The VM handle.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync * @remarks Caller holds the extension manager lock.
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsyncint ExtPack::callVmConfigureVmmHook(IConsole *a_pConsole, PVM a_pVM)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync int vrc = m->pReg->pfnVMConfigureVMM(m->pReg, a_pConsole, a_pVM);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync LogRel(("ExtPack pfnVMConfigureVMM returned %Rrc for %s\n", vrc, m->Desc.strName.c_str()));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Calls the pfnVMPowerOn hook.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @returns VBox status code, LogRel called on failure.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param a_pConsole The console interface.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param a_pVM The VM handle.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @remarks Caller holds the extension manager lock.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsyncint ExtPack::callVmPowerOnHook(IConsole *a_pConsole, PVM a_pVM)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync int vrc = m->pReg->pfnVMPowerOn(m->pReg, a_pConsole, a_pVM);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync LogRel(("ExtPack pfnVMPowerOn returned %Rrc for %s\n", vrc, m->Desc.strName.c_str()));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * Calls the pfnVMPowerOff hook.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * @param a_pConsole The console interface.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * @param a_pVM The VM handle.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * @remarks Caller holds the extension manager lock.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsyncvoid ExtPack::callVmPowerOffHook(IConsole *a_pConsole, PVM a_pVM)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync m->pReg->pfnVMPowerOff(m->pReg, a_pConsole, a_pVM);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * Refreshes the extension pack state.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * This is called by the manager so that the on disk changes are picked up.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * @returns S_OK or COM error status with error information.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * @param pfCanDelete Optional can-delete-this-object output indicator.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * @remarks Caller holds the extension manager lock for writing.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS); /* for the COMGETTERs */
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * Has the module been deleted?
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync int vrc = RTPathQueryInfoEx(m->strExtPackPath.c_str(), &ObjInfoExtPack, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * We've got a directory, so try query file system object info for the
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * files we are interested in as well.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync vrc = RTPathJoin(szDescFilePath, sizeof(szDescFilePath), m->strExtPackPath.c_str(), VBOX_EXTPACK_DESCRIPTION_NAME);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync vrc = RTPathQueryInfoEx(szDescFilePath, &ObjInfoDesc, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync vrc = RTPathQueryInfoEx(m->strMainModPath.c_str(), &ObjInfoMainMod, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (m->strMainModPath.isEmpty() || RT_FAILURE(vrc))
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * If we have a usable module already, just verify that things haven't
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * changed since we loaded it.
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync /** @todo not important, so it can wait. */
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * Ok, it is currently not usable. If anything has changed since last time
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * reprobe the extension pack.
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync else if ( !objinfoIsEqual(&ObjInfoDesc, &m->ObjInfoDesc)
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync || !objinfoIsEqual(&ObjInfoMainMod, &m->ObjInfoMainMod)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync || !objinfoIsEqual(&ObjInfoExtPack, &m->ObjInfoExtPack) )
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * Probes the extension pack, loading the main dll and calling its registration
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * entry point.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * This updates the state accordingly, the strWhyUnusable and fUnusable members
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * being the most important ones.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * Query the file system info for the extension pack directory. This and
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * all other file system info we save is for the benefit of refresh().
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync int vrc = RTPathQueryInfoEx(m->strExtPackPath.c_str(), &m->ObjInfoExtPack, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync m->strWhyUnusable.printf(tr("RTPathQueryInfoEx on '%s' failed: %Rrc"), m->strExtPackPath.c_str(), vrc);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (!RTFS_IS_DIRECTORY(m->ObjInfoExtPack.Attr.fMode))
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync m->strWhyUnusable.printf(tr("'%s' is a symbolic link, this is not allowed"), m->strExtPackPath.c_str(), vrc);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync else if (RTFS_IS_FILE(m->ObjInfoExtPack.Attr.fMode))
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync m->strWhyUnusable.printf(tr("'%s' is a symbolic file, not a directory"), m->strExtPackPath.c_str(), vrc);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync m->strWhyUnusable.printf(tr("'%s' is not a directory (fMode=%#x)"), m->strExtPackPath.c_str(), m->ObjInfoExtPack.Attr.fMode);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vrc = SUPR3HardenedVerifyDir(m->strExtPackPath.c_str(), true /*fRecursive*/, true /*fCheckFiles*/, szErr, sizeof(szErr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync m->strWhyUnusable.printf(tr("%s (rc=%Rrc)"), szErr, vrc);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Read the description file.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync iprt::MiniString *pStrLoadErr = VBoxExtPackLoadDesc(m->strExtPackPath.c_str(), &m->Desc, &m->ObjInfoDesc);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync m->strWhyUnusable.printf(tr("Failed to load '%s/%s': %s"),
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync m->strExtPackPath.c_str(), VBOX_EXTPACK_DESCRIPTION_NAME, pStrLoadErr->c_str());
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Make sure the XML name and directory matches.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!m->Desc.strName.equalsIgnoreCase(strSavedName))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync m->strWhyUnusable.printf(tr("The description name ('%s') and directory name ('%s') does not match"),
c9a593aa048a154e59b52d1237d89e3cdaee9b3dvboxsync * Load the main DLL and call the predefined entry point.
c9a593aa048a154e59b52d1237d89e3cdaee9b3dvboxsync if (!findModule(m->Desc.strMainModule.c_str(), NULL /* default extension */,
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync &m->strMainModPath, &fIsNative, &m->ObjInfoMainMod))
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync m->strWhyUnusable.printf(tr("Failed to locate the main module ('%s')"), m->Desc.strMainModule.c_str());
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vrc = SUPR3HardenedVerifyPlugIn(m->strMainModPath.c_str(), szErr, sizeof(szErr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vrc = RTLdrLoad(m->strMainModPath.c_str(), &m->hMainMod);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync m->strWhyUnusable.printf(tr("Failed to locate load the main module ('%s'): %Rrc"),
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync m->strWhyUnusable.printf(tr("Only native main modules are currently supported"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Resolve the predefined entry point.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vrc = RTLdrGetSymbol(m->hMainMod, VBOX_EXTPACK_MAIN_MOD_ENTRY_POINT, (void **)&pfnRegistration);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vrc = pfnRegistration(&m->Hlp, &m->pReg, szErr, sizeof(szErr) - 16);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync && m->pReg->u32EndMarker == VBOXEXTPACKREG_VERSION)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if ( (!m->pReg->pfnInstalled || RT_VALID_PTR(m->pReg->pfnInstalled))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync && (!m->pReg->pfnUninstall || RT_VALID_PTR(m->pReg->pfnUninstall))
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync && (!m->pReg->pfnUnload || RT_VALID_PTR(m->pReg->pfnUnload))
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync && (!m->pReg->pfnVMCreated || RT_VALID_PTR(m->pReg->pfnVMCreated))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync && (!m->pReg->pfnVMConfigureVMM || RT_VALID_PTR(m->pReg->pfnVMConfigureVMM))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync && (!m->pReg->pfnVMPowerOn || RT_VALID_PTR(m->pReg->pfnVMPowerOn))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync && (!m->pReg->pfnVMPowerOff || RT_VALID_PTR(m->pReg->pfnVMPowerOff))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync && (!m->pReg->pfnQueryObject || RT_VALID_PTR(m->pReg->pfnQueryObject))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * We're good!
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync m->strWhyUnusable = tr("The registration structure contains on or more invalid function pointers");
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync m->strWhyUnusable.printf(tr("Unsupported registration structure version %u.%u"),
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync RT_HIWORD(m->pReg->u32Version), RT_LOWORD(m->pReg->u32Version));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync m->strWhyUnusable.printf(tr("%s returned %Rrc, pReg=%p szErr='%s'"),
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync VBOX_EXTPACK_MAIN_MOD_ENTRY_POINT, vrc, m->pReg, szErr);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync m->strWhyUnusable.printf(tr("Failed to resolve exported symbol '%s' in the main module: %Rrc"),
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Finds a module.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @returns true if found, false if not.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param a_pszName The module base name (no extension).
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param a_pszExt The extension. If NULL we use default
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * extensions.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param a_pStrFound Where to return the path to the module we've
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param a_pfNative Where to return whether this is a native module
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * or an agnostic one. Optional.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * @param a_pObjInfo Where to return the file system object info for
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * the module. Optional.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncbool ExtPack::findModule(const char *a_pszName, const char *a_pszExt,
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Utf8Str *a_pStrFound, bool *a_pfNative, PRTFSOBJINFO a_pObjInfo) const
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * Try the native path first.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync int vrc = RTPathJoin(szPath, sizeof(szPath), m->strExtPackPath.c_str(), RTBldCfgTargetDotArch());
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPathAppend(szPath, sizeof(szPath), a_pszName);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTStrCat(szPath, sizeof(szPath), RTLdrGetSuff());
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vrc = RTPathQueryInfo(szPath, a_pObjInfo, RTFSOBJATTRADD_UNIX);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (RT_SUCCESS(vrc) && RTFS_IS_FILE(a_pObjInfo->Attr.fMode))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return true;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Try the platform agnostic modules.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync RTStrPrintf(szSubDir, sizeof(szSubDir), "%s.%s", RTBldCfgCompiler(), RTBldCfgTargetArch());
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPathJoin(szPath, sizeof(szPath), m->strExtPackPath.c_str(), szSubDir);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPathAppend(szPath, sizeof(szPath), a_pszName);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPathQueryInfo(szPath, a_pObjInfo, RTFSOBJATTRADD_UNIX);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (RT_SUCCESS(vrc) && RTFS_IS_FILE(a_pObjInfo->Attr.fMode))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return true;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vrc = RTPathJoin(szPath, sizeof(szPath), m->strExtPackPath.c_str(), RTBldCfgTargetArch());
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vrc = RTPathAppend(szPath, sizeof(szPath), a_pszName);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPathQueryInfo(szPath, a_pObjInfo, RTFSOBJATTRADD_UNIX);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (RT_SUCCESS(vrc) && RTFS_IS_FILE(a_pObjInfo->Attr.fMode))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return true;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return false;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Compares two file system object info structures.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @returns true if equal, false if not.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * @param pObjInfo1 The first.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param pObjInfo2 The second.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * @todo IPRT should do this, really.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync/* static */ bool ExtPack::objinfoIsEqual(PCRTFSOBJINFO pObjInfo1, PCRTFSOBJINFO pObjInfo2)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!RTTimeSpecIsEqual(&pObjInfo1->ModificationTime, &pObjInfo2->ModificationTime))
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return false;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!RTTimeSpecIsEqual(&pObjInfo1->ChangeTime, &pObjInfo2->ChangeTime))
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return false;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!RTTimeSpecIsEqual(&pObjInfo1->BirthTime, &pObjInfo2->BirthTime))
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync return false;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync return false;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (pObjInfo1->Attr.fMode != pObjInfo2->Attr.fMode)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync return false;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pObjInfo1->Attr.enmAdditional == pObjInfo2->Attr.enmAdditional)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pObjInfo1->Attr.u.Unix.uid != pObjInfo2->Attr.u.Unix.uid)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return false;
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync if (pObjInfo1->Attr.u.Unix.gid != pObjInfo2->Attr.u.Unix.gid)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return false;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (pObjInfo1->Attr.u.Unix.INodeIdDevice != pObjInfo2->Attr.u.Unix.INodeIdDevice)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync return false;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pObjInfo1->Attr.u.Unix.INodeId != pObjInfo2->Attr.u.Unix.INodeId)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return false;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (pObjInfo1->Attr.u.Unix.GenerationId != pObjInfo2->Attr.u.Unix.GenerationId)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return false;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return true;
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync * @interface_method_impl{VBOXEXTPACKHLP,pfnFindModule}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncExtPack::hlpFindModule(PCVBOXEXTPACKHLP pHlp, const char *pszName, const char *pszExt,
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync * Validate the input and get our bearings.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync AssertPtrNullReturn(pfNative, VERR_INVALID_POINTER);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync ExtPack::Data *m = RT_FROM_CPP_MEMBER(pHlp, Data, Hlp);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * This is just a wrapper around findModule.
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync if (pThis->findModule(pszName, pszExt, &strFound, pfNative, NULL))
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync return RTStrCopy(pszFound, cbFound, strFound.c_str());
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncExtPack::hlpGetFilePath(PCVBOXEXTPACKHLP pHlp, const char *pszFilename, char *pszPath, size_t cbPath)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Validate the input and get our bearings.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync ExtPack::Data *m = RT_FROM_CPP_MEMBER(pHlp, Data, Hlp);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * This is a simple RTPathJoin, no checking if things exists or anything.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync int vrc = RTPathJoin(pszPath, cbPath, pThis->m->strExtPackPath.c_str(), pszFilename);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsyncSTDMETHODIMP ExtPack::COMGETTER(Name)(BSTR *a_pbstrName)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncSTDMETHODIMP ExtPack::COMGETTER(Description)(BSTR *a_pbstrDescription)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsyncSTDMETHODIMP ExtPack::COMGETTER(Version)(BSTR *a_pbstrVersion)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncSTDMETHODIMP ExtPack::COMGETTER(Revision)(ULONG *a_puRevision)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncSTDMETHODIMP ExtPack::COMGETTER(PlugIns)(ComSafeArrayOut(IExtPackPlugIn *, a_paPlugIns))
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync /** @todo implement plug-ins. */
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsyncSTDMETHODIMP ExtPack::COMGETTER(Usable)(BOOL *a_pfUsable)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncSTDMETHODIMP ExtPack::COMGETTER(WhyUnusable)(BSTR *a_pbstrWhy)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncSTDMETHODIMP ExtPack::QueryObject(IN_BSTR a_bstrObjectId, IUnknown **a_ppUnknown)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync void *pvUnknown = m->pReg->pfnQueryObject(m->pReg, ObjectId.raw());
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Called by ComObjPtr::createObject when creating the object.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Just initialize the basic object state, do the rest in init().
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @returns S_OK.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Initializes the extension pack manager.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @returns COM status code.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * @param a_pszDropZoneDir The path to the drop zone directory.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * @param a_fCheckDropZone Whether to check the drop zone for new
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * extensions or not. Only VBoxSVC does this
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * and then only when wanted.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsyncHRESULT ExtPackManager::init(const char *a_pszDropZoneDir, bool a_fCheckDropZone)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * Figure some stuff out before creating the instance data.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync int rc = RTPathAppPrivateArch(szBaseDir, sizeof(szBaseDir));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync rc = RTPathAppend(szBaseDir, sizeof(szBaseDir), VBOX_EXTPACK_INSTALL_DIR);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync rc = RTPathAppPrivateNoArch(szCertificatDir, sizeof(szCertificatDir));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync rc = RTPathAppend(szCertificatDir, sizeof(szCertificatDir), VBOX_EXTPACK_CERT_DIR);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Allocate and initialize the instance data.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Go looking for extensions. The RTDirOpen may fail if nothing has been
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * installed yet, or if root is paranoid and has revoked our access to them.
129986ce8b48d5e5973ad84edae4465788db89aavboxsync * We ASSUME that there are no files, directories or stuff in the directory
129986ce8b48d5e5973ad84edae4465788db89aavboxsync * that exceed the max name length in RTDIRENTRYEX.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync vrc = RTDirReadEx(pDir, &Entry, NULL /*pcbDirEntry*/, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync AssertLogRelMsg(vrc == VERR_NO_MORE_FILES, ("%Rrc\n", vrc));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * All directories are extensions, the shall be nothing but
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * extensions in this subdirectory.
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync /* else: ignore, the directory probably does not exist or something. */
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync * Look for things in the drop zone.
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync * COM cruft.
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync * Do the actual cleanup.
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync /* Enclose the state transition Ready->InUninit->NotReady */
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsyncSTDMETHODIMP ExtPackManager::COMGETTER(InstalledExtPacks)(ComSafeArrayOut(IExtPack *, a_paExtPacks))
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync SafeIfaceArray<IExtPack> SaExtPacks(m->llInstalledExtPacks);
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync SaExtPacks.detachTo(ComSafeArrayOutArg(a_paExtPacks));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncSTDMETHODIMP ExtPackManager::Find(IN_BSTR a_bstrName, IExtPack **a_pExtPack)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync ComPtr<ExtPack> ptrExtPack = findExtPack(strName.c_str());
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsyncSTDMETHODIMP ExtPackManager::Install(IN_BSTR a_bstrTarball, BSTR *a_pbstrName)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Check that the file exists and that we can access it.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync int vrc = RTFileOpen(&hFile, strTarball.c_str(), RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN);
fabb3e1e51b589494ebe849b7c000e8bcc9ff473vboxsync vrc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * Derive the name of the extension pack from the file
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * name. Certain restrictions are here placed on the
fabb3e1e51b589494ebe849b7c000e8bcc9ff473vboxsync * tarball name.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync iprt::MiniString *pStrName = VBoxExtPackExtractNameFromTarballPath(strTarball.c_str());
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * Refresh the data we have on the extension pack as it
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * may be made stale by direct meddling or some other user.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = refreshExtPack(pStrName->c_str(), false /*a_fUnsuableIsError*/, &pExtPack);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * Run the set-uid-to-root binary that performs the actual
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * installation. Then create an object for the packet (we
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * do this even on failure, to be on the safe side).
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync RTStrPrintf(szTarballFd, sizeof(szTarballFd), "0x%RX64",
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync "--certificate-dir", m->strCertificatDirPath.c_str(),
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync hrc = refreshExtPack(pStrName->c_str(), true /*a_fUnsuableIsError*/, &pExtPack);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync LogRel(("ExtPackManager: Successfully installed extension pack '%s'.\n", pStrName->c_str()));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync refreshExtPack(pStrName->c_str(), false /*a_fUnsuableIsError*/, NULL);
0721bcb57f5e05054e2b5092075617983ec2914evboxsync " In case of a reinstallation, please uninstall it first"),
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync hrc = setError(E_FAIL, tr("Malformed '%s' file name"), strTarball.c_str());
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync hrc = setError(E_FAIL, tr("'%s' is not a regular file"), strTarball.c_str());
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync hrc = setError(E_FAIL, tr("Failed to query info on '%s' (%Rrc)"), strTarball.c_str(), vrc);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync hrc = setError(E_FAIL, tr("Failed to open '%s' (%Rrc)"), strTarball.c_str(), vrc);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = setError(E_FAIL, tr("'%s' is not a regular file"), strTarball.c_str());
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = setError(E_FAIL, tr("File '%s' was inaccessible or not found"), strTarball.c_str());
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsyncSTDMETHODIMP ExtPackManager::Uninstall(IN_BSTR a_bstrName, BOOL a_fForcedRemoval)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * Refresh the data we have on the extension pack as it may be made
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * stale by direct meddling or some other user.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync hrc = refreshExtPack(strName.c_str(), false /*a_fUnsuableIsError*/, &pExtPack);
aa131431882ca8e44b0480d4af0b5d139f1bde21vboxsync LogRel(("ExtPackManager: Extension pack '%s' is not installed, so nothing to uninstall.\n", strName.c_str()));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * Call the uninstall hook and unload the main dll.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync hrc = pExtPack->callUninstallHookAndClose(a_fForcedRemoval != FALSE);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * Run the set-uid-to-root binary that performs the
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * uninstallation. Then refresh the object.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * This refresh is theorically subject to races, but it's of
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * the don't-do-that variety.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync const char *pszForcedOpt = a_fForcedRemoval ? "--forced" : NULL;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync hrc = refreshExtPack(strName.c_str(), false /*a_fUnsuableIsError*/, &pExtPack);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync LogRel(("ExtPackManager: Successfully uninstalled extension pack '%s'.\n", strName.c_str()));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync tr("Uninstall extension pack '%s' failed under mysterious circumstances"),
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync refreshExtPack(strName.c_str(), false /*a_fUnsuableIsError*/, NULL);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Run the set-uid-to-root binary that performs the cleanup.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * Take the write lock to prevent conflicts with other calls to this
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * VBoxSVC instance.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsyncSTDMETHODIMP ExtPackManager::QueryAllPlugInsForFrontend(IN_BSTR a_bstrFrontend, ComSafeArrayOut(BSTR, a_pabstrPlugInModules))
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync CheckComArgOutSafeArrayPointerValid(a_pabstrPlugInModules);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync /** @todo implement plug-ins */
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync saPaths.detachTo(ComSafeArrayOutArg(a_pabstrPlugInModules));
0721bcb57f5e05054e2b5092075617983ec2914evboxsync * Runs the helper application that does the privileged operations.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * @returns S_OK or a failure status with error information set.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * @param a_pszCommand The command to execute.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * @param ... The argument strings that goes along with the
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * command. Maximum is about 16. Terminated by a
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncHRESULT ExtPackManager::runSetUidToRootHelper(const char *a_pszCommand, ...)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Calculate the path to the helper application.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync int vrc = RTPathAppPrivateArch(szExecName, sizeof(szExecName));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPathAppend(szExecName, sizeof(szExecName), VBOX_EXTPACK_HELPER_NAME);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Convert the variable argument list to a RTProcCreate argument vector.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync unsigned cArgs = 0;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync AssertReturn(cArgs < RT_ELEMENTS(apszArgs) - 1, E_UNEXPECTED);
77db08a24f69bca943d5abc40b1930ee97f593edvboxsync * Create a PIPE which we attach to stderr so that we can read the error
77db08a24f69bca943d5abc40b1930ee97f593edvboxsync * message on failure and report it back to the caller.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPipeCreate(&hPipeR, &hStdErrPipe.u.hPipe, RTPIPE_C_INHERIT_WRITE);
d862f0eeb9eacdb46b9f5cc420de30a3d7c2c3f6vboxsync * Spawn the process.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync 0 /*fFlags*/,
9161d9a8318db73b2848c1feaef3880980474e64vboxsync * Read the pipe output until the process completes.
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync RTPROCSTATUS ProcStatus = { -42, RTPROCEXITREASON_ABEND };
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Service the pipe. Block waiting for output or the pipe breaking
9161d9a8318db73b2848c1feaef3880980474e64vboxsync * when the process terminates.
9161d9a8318db73b2848c1feaef3880980474e64vboxsync vrc = RTPipeReadBlocking(hPipeR, achBuf, sizeof(achBuf), &cbRead);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync /* grow the buffer? */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /* append if we've got room. */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync memcpy(&pszStdErrBuf[offStdErrBuf], achBuf, cbRead);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync AssertLogRelMsg(vrc == VERR_BROKEN_PIPE, ("%Rrc\n", vrc));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Service the process. Block if we have no pipe.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hPipeR == NIL_RTPIPE ? RTPROCWAIT_FLAGS_BLOCK : RTPROCWAIT_FLAGS_NOBLOCK,
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync AssertLogRelMsgStmt(vrc != VERR_PROCESS_RUNNING, ("%Rrc\n", vrc), hProcess = NIL_RTPROCESS);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Compose the status code and, on failure, error message.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync LogRel(("ExtPack: enmReason=%d iStatus=%d stderr='%s'\n",
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync ProcStatus.enmReason, ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : ""));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if ( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else if (ProcStatus.enmReason == RTPROCEXITREASON_NORMAL)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync AssertMsg(ProcStatus.iStatus != 0, ("%s\n", pszStdErrBuf));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = setError(E_UNEXPECTED, tr("The installer failed with exit code %d: %s"),
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : "");
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else if (ProcStatus.enmReason == RTPROCEXITREASON_SIGNAL)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = setError(E_UNEXPECTED, tr("The installer was killed by signal #d (stderr: %s)"),
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : "");
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else if (ProcStatus.enmReason == RTPROCEXITREASON_ABEND)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = setError(E_UNEXPECTED, tr("The installer aborted abnormally (stderr: %s)"),
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = setError(E_UNEXPECTED, tr("internal error: enmReason=%d iStatus=%d stderr='%s'"),
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync ProcStatus.enmReason, ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : "");
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to launch the helper application '%s' (%Rrc)"), szExecName, vrc);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Finds an installed extension pack.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @returns Pointer to the extension pack if found, NULL if not. (No reference
aaa6e7826ca134b41d12c1f570bd7874ae1d8135vboxsync * counting problem here since the caller must be holding the lock.)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param a_pszName The name of the extension pack.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncExtPack *ExtPackManager::findExtPack(const char *a_pszName)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync && pExtPackData->Desc.strName.compare(a_pszName, iprt::MiniString::CaseInsensitive) == 0)
730f8be51b729e8a3c1e32c756cd0f4ec088dd4dvboxsync * Removes an installed extension pack from the internal list.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * The package is expected to exist!
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * @param a_pszName The name of the extension pack.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncvoid ExtPackManager::removeExtPack(const char *a_pszName)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync && pExtPackData->Desc.strName.compare(a_pszName, iprt::MiniString::CaseInsensitive) == 0)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Refreshes the specified extension pack.
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync * This may remove the extension pack from the list, so any non-smart pointers
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * to the extension pack object may become invalid.
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * @returns S_OK and *ppExtPack on success, COM status code and error message
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * on failure.
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * @param a_pszName The extension to update..
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * @param a_fUnsuableIsError If @c true, report an unusable extension pack
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * as an error.
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync * @param a_ppExtPack Where to store the pointer to the extension
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync * pack of it is still around after the refresh.
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync * This is optional.
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync * @remarks Caller holds the extension manager lock.
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsyncHRESULT ExtPackManager::refreshExtPack(const char *a_pszName, bool a_fUnsuableIsError, ExtPack **a_ppExtPack)
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync * Refresh existing object.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Does the dir exist? Make some special effort to deal with case
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * sensitivie file systems (a_pszName is case insensitive).
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync int vrc = RTPathJoin(szDir, sizeof(szDir), m->strBaseDir.c_str(), a_pszName);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPathQueryInfoEx(szDir, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync bool fExists = RT_SUCCESS(vrc) && RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync vrc = RTDirReadEx(pDir, &Entry, NULL /*pcbDirEntry*/, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync AssertLogRelMsg(vrc == VERR_NO_MORE_FILES, ("%Rrc\n", vrc));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * The installed extension pack has a uses different case.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * Update the name and directory variables.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPathJoin(szDir, sizeof(szDir), m->strBaseDir.c_str(), Entry.szName); /* not really necessary */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync AssertLogRelRCReturnStmt(vrc, E_UNEXPECTED, RTDirClose(pDir));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * We've got something, create a new extension pack object for it.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = NewExtPack->init(a_pszName, m->strBaseDir.c_str());
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync LogRel(("ExtPackManager: Found extension pack '%s'.\n", a_pszName));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync LogRel(("ExtPackManager: Found bad extension pack '%s': %s\n",
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync a_pszName, NewExtPack->m->strWhyUnusable.c_str() ));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Report error if not usable, if that is desired.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hrc = setError(E_FAIL, "%s", pExtPack->m->strWhyUnusable.c_str());
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Processes anything new in the drop zone.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync int vrc = RTDirOpen(&pDir, m->strDropZoneDir.c_str());
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync vrc = RTDirReadEx(pDir, &Entry, NULL /*pcbDirEntry*/, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync AssertMsg(vrc == VERR_NO_MORE_FILES, ("%Rrc\n", vrc));
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync * We're looking for files with the right extension. Symbolic links
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync * will be ignored.
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync && RTStrICmp(RTPathExt(Entry.szName), VBOX_EXTPACK_SUFFIX) == 0)
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync /* We create (and check for) a blocker file to prevent this
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync extension pack from being installed more than once. */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTPathJoin(szPath, sizeof(szPath), m->strDropZoneDir.c_str(), Entry.szName);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync vrc = RTPathAppend(szPath, sizeof(szPath), "-done");
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vrc = RTFileOpen(&hFile, szPath, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE);
it++)
it++)
return vrc;
return VINF_SUCCESS;
it++)
return vrc;
return VINF_SUCCESS;
it++)