VirtualBox

Changeset 59363 in vbox


Ignore:
Timestamp:
Jan 16, 2016 4:07:40 AM (9 years ago)
Author:
vboxsync
Message:

VBoxProxyStub: Work in progress.

Location:
trunk/src/VBox
Files:
1 added
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Installer/win/VBoxMergeApp.wxi

    r59329 r59363  
    8181        <File Id="file_VBoxProxyStub" Name="VBoxProxyStub.dll" KeyPath="yes"
    8282              Source="$(env.PATH_OUT)\bin\VBoxProxyStub.dll">
    83             <!-- TODO: figure how 327E3C00-EE61-462F-AED3-0DFF6CBF9904 is selected. -->
    84             <Class Id="{327E3C00-EE61-462F-AED3-0DFF6CBF9904}" Context="InprocServer32"
     83            <!-- Note! 0bb3b78c-1807-4249-5ba5-ea42d66af0bf is hardcoded in Main/Makefile.kmk and VBoxMergeCOM32On64.wxi -->
     84            <Class Id="{0bb3b78c-1807-4249-5ba5-ea42d66af0bf}" Context="InprocServer32"
    8585                Description="PSFactoryBuffer" ThreadingModel="both" >
    8686            </Class>
  • trunk/src/VBox/Installer/win/VBoxMergeCOM32On64.wxi

    r59329 r59363  
    3636                Source="$(env.PATH_OUT)\bin\VBoxProxyStub-x86.dll"
    3737                DiskId="$(var.Property_DiskIdCommon)">
    38                 <Class Id="{327E3C00-EE61-462F-AED3-0DFF6CBF9904}" Context="InprocServer32"
     38                <!-- Note! 0bb3b78c-1807-4249-5ba5-ea42d66af0bf is hardcoded in Main/Makefile.kmk and VBoxMergeApp.wix -->
     39                <Class Id="{0bb3b78c-1807-4249-5ba5-ea42d66af0bf}" Context="InprocServer32"
    3940                    Description="PSFactoryBuffer" ThreadingModel="both" />
    4041            </File>
  • trunk/src/VBox/Main/Makefile.kmk

    r59327 r59363  
    858858 VBoxClient-x86_EXTENDS  = VBoxC
    859859 VBoxClient-x86_DEFS = VBOX_COM_INPROC_API_CLIENT $(VBoxC_DEFS)
    860  VBoxClient-x86_INST.win = $(INST_DLL)x86/
    861860 VBoxClient-x86_INCS.win = \
    862861        $(VBoxClient-x86_0_OUTDIR) \
     
    10101009 DLLS += VBoxProxyStub
    10111010 VBoxProxyStub_TEMPLATE = VBOXMAINCOMP
    1012  VBoxProxyStub_DEFS     = REGISTER_PROXY_DLL
     1011 VBoxProxyStub_DEFS     = REGISTER_PROXY_DLL \
     1012        PROXY_CLSID_IS="{0x0bb3b78c,0x1807,0x4249,{0x5b,0xa5,0xea,0x42,0xd6,0x6a,0xf0,0xbf}}"
     1013        # => 0bb3b78c-1807-4249-5ba5-ea42d66af0bf: Also hardcoded in VBoxMergeCOM32On64.wxi and VBoxMergeApp.wxi!
    10131014 VBoxProxyStub_DEFS.win.x86 = WIN32
    10141015 VBoxProxyStub_INCS     = $(VBoxCOM_0_OUTDIR)/
    10151016 VBoxProxyStub_SOURCES  = \
    1016         $(VBoxCOM_0_OUTDIR)/dlldata.c \
    10171017        $(VBoxCOM_0_OUTDIR)/VirtualBox_p.c \
    10181018        $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c \
    10191019        src-all/win/VBoxProxyStub.def \
    1020         src-all/win/VBoxProxyStub.rc
     1020        src-all/win/VBoxProxyStub.rc \
     1021        src-all/win/VBoxProxyStub.c
    10211022  src-all/win/VBoxProxyStub.rc_DEPS = $(VBoxCOM_0_OUTDIR)/VirtualBox.tlb
    10221023
     
    10241025  DLLS += VBoxProxyStub-x86
    10251026  VBoxProxyStub-x86_TEMPLATE = VBoxMainComp-x86
    1026   VBoxProxyStub-x86_DEFS     = REGISTER_PROXY_DLL
    1027   VBoxProxyStub-x86_DEFS.win.x86 = WIN32
     1027  VBoxProxyStub-x86_DEFS     = $(VBoxProxyStub_DEFS) VBOX_PROXY_STUB_32_ON_64 WIN32
    10281028  VBoxProxyStub-x86_INCS     = $(VBoxCOM-x86_0_OUTDIR)/
    10291029  VBoxProxyStub-x86_SOURCES  = \
    1030         $(VBoxCOM-x86_0_OUTDIR)/dlldata.c \
    10311030        $(VBoxCOM-x86_0_OUTDIR)/VirtualBox_p.c \
    10321031        $(VBoxCOM-x86_0_OUTDIR)/VirtualBox_i.c \
    1033         src-all/win/VBoxProxyStub.def \
    1034         src-all/win/VBoxProxyStub-x86.rc
     1032        src-all/win/VBoxProxyStub.c \
     1033        src-all/win/VBoxProxyStub-x86.rc \
     1034        src-all/win/VBoxProxyStub.def
    10351035  src-all/win/VBoxProxyStub-x86.rc_DEPS = $(VBoxCOM-x86_0_OUTDIR)/VirtualBox-x86.tlb
    10361036 endif
  • trunk/src/VBox/Main/src-all/win/VBoxProxyStub.c

    r59360 r59363  
    11/* $Id$ */
    22/** @file
    3  * VBoxC - COM DLL exports and DLL init/term.
     3 * VBoxProxyStub - Proxy Stub and Typelib, COM DLL exports and DLL init/term.
     4 *
     5 * @remarks This is a C file and not C++ because rpcproxy.h isn't C++ clean,
     6 *          at least not in SDK v7.1.
    47 */
    58
     
    2023*   Header Files                                                                                                                 *
    2124*********************************************************************************************************************************/
    22 #include "VBox/com/defs.h"
    23 
    24 #include <SessionImpl.h>
    25 #include <VirtualBoxClientImpl.h>
    26 
    27 #include <atlbase.h>
    28 #include <atlcom.h>
    29 
    30 #include <iprt/initterm.h>
     25#define PROXY_DELEGATION                                                                             /* see generated dlldata.c */
     26#include <rpcproxy.h>
     27#include <Windows.h>
     28#include <Shlwapi.h>
     29#include <stdio.h>
     30
     31#include "VirtualBox.h"
    3132#include <iprt/assert.h>
     33#include <iprt/path.h>
    3234#include <iprt/string.h>
     35
     36
     37/*********************************************************************************************************************************
     38*   Defined Constants And Macros                                                                                                 *
     39*********************************************************************************************************************************/
     40/** @def WITH_MANUAL_CLEANUP
     41 * Manually clean up the registry. */
     42#if 1 /*defined(DEBUG) && !defined(VBOX_IN_32_ON_64_MAIN_API) - needed on testboxes (and obviously dev boxes)! */
     43# define WITH_MANUAL_CLEANUP
     44#endif
    3345
    3446
     
    3648*   Global Variables                                                                                                             *
    3749*********************************************************************************************************************************/
    38 CComModule _Module;
    39 
    40 BEGIN_OBJECT_MAP(ObjectMap)
    41     OBJECT_ENTRY(CLSID_Session, Session)
    42     OBJECT_ENTRY(CLSID_VirtualBoxClient, VirtualBoxClient)
    43 END_OBJECT_MAP()
    44 
    45 
    46 /** @def WITH_MANUAL_CLEANUP
    47  * Manually clean up the registry. */
    48 #if defined(DEBUG) && !defined(VBOX_IN_32_ON_64_MAIN_API)
    49 //# define WITH_MANUAL_CLEANUP
    50 #endif
     50/** For NdrXxx. */
     51CStdPSFactoryBuffer         g_ProxyStubFactory =                                                     /* see generated dlldata.c */
     52{
     53    NULL,
     54    0,
     55    NULL,
     56    0
     57};
     58/** Reference to VirtualBox_p.c structure. */
     59EXTERN_PROXY_FILE(VirtualBox)                                                                        /* see generated dlldata.c */
     60/** For NdrXxx and for returning. */
     61static const ProxyFileInfo *g_apProxyFiles[] =
     62{
     63    REFERENCE_PROXY_FILE(VirtualBox),
     64    NULL /* terminator */
     65};
     66/** The class ID for this proxy stub factory (see Makefile). */
     67static const CLSID          g_ProxyClsId = PROXY_CLSID_IS;
     68/** The instance handle of this DLL.  For use in registration routines. */
     69static HINSTANCE            g_hDllSelf;
    5170
    5271
    5372#ifdef WITH_MANUAL_CLEANUP
    5473/** Type library GUIDs to clean up manually. */
    55 static const char * const g_apszTypelibGuids[] =
     74static const char * const   g_apszTypelibGuids[] =
    5675{
    5776    "{46137EEC-703B-4FE5-AFD4-7C9BBBBA0259}",
     
    6079
    6180/** Same as above but with a "Typelib\\" prefix. */
    62 static const char * const g_apszTypelibGuidKeys[] =
     81static const char * const   g_apszTypelibGuidKeys[] =
    6382{
    6483    "TypeLib\\{46137EEC-703B-4FE5-AFD4-7C9BBBBA0259}",
     
    6786
    6887/** Type library version to clean up manually. */
    69 static const char * const g_apszTypelibVersions[] =
     88static const char * const   g_apszTypelibVersions[] =
    7089{
    7190    "1.0",
     
    83102
    84103
    85 /////////////////////////////////////////////////////////////////////////////
    86 // DLL Entry Point
    87 
    88 extern "C"
    89 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
    90 {
    91     if (dwReason == DLL_PROCESS_ATTACH)
    92     {
    93         _Module.Init(ObjectMap, hInstance, &LIBID_VirtualBox);
    94         DisableThreadLibraryCalls(hInstance);
    95 
    96         // idempotent, so doesn't harm, and needed for COM embedding scenario
    97         RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
    98     }
    99     else if (dwReason == DLL_PROCESS_DETACH)
    100     {
    101         _Module.Term();
    102     }
     104
     105
     106/**
     107 * DLL main function.
     108 *
     109 * @returns TRUE (/ FALSE).
     110 * @param   hInstance           The DLL handle.
     111 * @param   dwReason            The rason for the call (DLL_XXX).
     112 * @param   lpReserved          Reserved.
     113 */
     114BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
     115{
     116    switch (dwReason)
     117    {
     118        case DLL_PROCESS_ATTACH:
     119            g_hDllSelf = hInstance;
     120            DisableThreadLibraryCalls(hInstance);
     121            /* We don't use IPRT, so no need to init it! */
     122            break;
     123
     124        case DLL_PROCESS_DETACH:
     125            break;
     126    }
     127
     128    NOREF(lpReserved);
    103129    return TRUE;
    104130}
    105131
    106 /////////////////////////////////////////////////////////////////////////////
    107 // Used to determine whether the DLL can be unloaded by OLE
    108 
    109 STDAPI DllCanUnloadNow(void)
    110 {
    111     return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
    112 }
    113 
    114 /////////////////////////////////////////////////////////////////////////////
    115 // Returns a class factory to create an object of the requested type
    116 
    117 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
    118 {
    119     return _Module.GetClassObject(rclsid, riid, ppv);
    120 }
    121 
    122 /////////////////////////////////////////////////////////////////////////////
    123 // DllRegisterServer - Adds entries to the system registry
    124 
    125 STDAPI DllRegisterServer(void)
    126 {
    127     // registers object, typelib and all interfaces in typelib
    128     return _Module.RegisterServer(TRUE);
    129 }
    130 
    131 /////////////////////////////////////////////////////////////////////////////
    132 // DllUnregisterServer - Removes entries from the system registry
    133 
    134 STDAPI DllUnregisterServer(void)
    135 {
    136     HRESULT hrc = _Module.UnregisterServer(TRUE);
     132
     133/**
     134 * RPC entry point returning info about the proxy.
     135 */
     136void RPC_ENTRY GetProxyDllInfo(const ProxyFileInfo ***ppapInfo, const CLSID **ppClsid)
     137{
     138    *ppapInfo = &g_apProxyFiles[0];
     139    *ppClsid  = &g_ProxyClsId;
     140};
     141
     142
     143/**
     144 * Instantiate the proxy stub class object.
     145 *
     146 * @returns COM status code
     147 * @param   rclsid      Reference to the ID of the call to instantiate (our
     148 *                      g_ProxyClsId).
     149 * @param   riid        The interface ID to return (IID_IPSFactoryBuffer).
     150 * @param   ppv         Where to return the interface pointer on success.
     151 */
     152HRESULT STDAPICALLTYPE DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
     153{
     154    HRESULT hrc;
     155    Assert(memcmp(rclsid, &g_ProxyClsId, sizeof(g_ProxyClsId)) == 0);
     156
     157    hrc = NdrDllGetClassObject(rclsid, riid, ppv,                                 /* see DLLGETCLASSOBJECTROUTINE in RpcProxy.h */
     158                               g_apProxyFiles, &g_ProxyClsId, &g_ProxyStubFactory);
     159
     160    /*
     161     * This may fail if the IDL compiler generates code that is incompatible
     162     * with older windows releases.  Like for instance 64-bit W2K8 SP1 not
     163     * liking the output of MIDL 7.00.0555 (from the v7.1 SDK), despite
     164     * /target being set to NT51.
     165     */
     166    AssertMsg(hrc == S_OK, ("%Rhrc\n",  hrc));
     167    return hrc;
     168}
     169
     170
     171/**
     172 * Checks whether the DLL can be unloaded or not.
     173 *
     174 * @returns S_OK if it can be unloaded, S_FALSE if not.
     175 */
     176HRESULT STDAPICALLTYPE DllCanUnloadNow(void)
     177{
     178    return NdrDllCanUnloadNow(&g_ProxyStubFactory);                                        /* see DLLCANUNLOADNOW in RpcProxy.h */
     179}
     180
     181
     182
     183/**
     184 * Release call that could be referenced by VirtualBox_p.c via
     185 * CStdStubBuffer_METHODS.
     186 *
     187 * @returns New reference count.
     188 * @param   pThis               Buffer to release.
     189 */
     190ULONG STDMETHODCALLTYPE CStdStubBuffer_Release(IRpcStubBuffer *pThis)                /* see CSTDSTUBBUFFERRELEASE in RpcProxy.h */
     191{
     192    return NdrCStdStubBuffer_Release(pThis, (IPSFactoryBuffer *)&g_ProxyStubFactory);
     193}
     194
     195
     196/**
     197 * Release call referenced by VirtualBox_p.c via
     198 * CStdStubBuffer_DELEGATING_METHODS.
     199 *
     200 * @returns New reference count.
     201 * @param   pThis               Buffer to release.
     202 */
     203ULONG WINAPI CStdStubBuffer2_Release(IRpcStubBuffer *pThis)                         /* see CSTDSTUBBUFFER2RELEASE in RpcProxy.h */
     204{
     205    return NdrCStdStubBuffer2_Release(pThis, (IPSFactoryBuffer *)&g_ProxyStubFactory);
     206}
     207
     208
     209/**
     210 * Pure virtual method implementation referenced by VirtualBox_p.c
     211 *
     212 * @returns New reference count.
     213 * @param   pThis               Buffer to release.
     214 */
     215void __cdecl _purecall(void)                                                              /* see DLLDUMMYPURECALL in RpcProxy.h */
     216{
     217    AssertFailed();
     218}
     219
     220
     221/**
     222 * Registry modifier state.
     223 */
     224typedef struct VBPSREGSTATE
     225{
     226    /** Where the classes and stuff are to be registered. */
     227    HKEY hkeyClassesRootDst;
     228    /** The handle to the CLSID key under hkeyClassesRootDst. */
     229    HKEY hkeyClsidRootDst;
     230    /** For logging purposes.   */
     231    const char *pszLogRoot;
     232
     233    /** Alternative location where duplicates must always be unregistered from. */
     234    HKEY hkeyAltClassesRootsUnreg;
     235    /** The handle to the CLSID key under hkeyAltClassesRootsUnreg. */
     236    HKEY hkeyAltClsidRootsUnreg;
     237
     238    /** The current total result. */
     239    LSTATUS rc;
     240
     241    /** KEY_WOW64_32KEY, KEY_WOW64_64KEY or 0 (for default).  Allows doing all
     242     * almost the work from one process (at least W7+ due to aliases). */
     243    DWORD   fSamWow;
     244    /** Desired key Access when only unregistring. */
     245    DWORD   fSamUnreg;
     246    /** Desired key Access when both unregistring and registering. */
     247    DWORD   fSamBoth;
     248    /** Set if we're only unregistering. */
     249    bool    fUnregisterOnly;
     250} VBPSREGSTATE;
     251
     252
     253/**
     254 * Initializes a registry modification job state.
     255 *
     256 * Always call vbpsRegTerm!
     257 *
     258 * @returns Windows error code (ERROR_SUCCESS on success).
     259 * @param   pState          The state to init.
     260 * @param   hkeyRoot        The registry root tree constant.
     261 * @param   pszSubRoot      The path to the where the classes are registered,
     262 *                          NULL if @a hkeyRoot.
     263 * @param   pszLogRoot      For error logging/debugging?
     264 * @param   hkeyAltRoot     The registry root tree constant for the alternative
     265 *                          registrations (remove only).
     266 * @param   pszAltSubRoot   The path to where classes could also be registered,
     267 *                          but shouldn't be in our setup.
     268 * @param   fUnregisterOnly If true, only unregister. If false, also register.
     269 * @param   fSamWow         KEY_WOW64_32KEY or 0.
     270 */
     271static LSTATUS vbpsRegInit(VBPSREGSTATE *pState, HKEY hkeyRoot, const char *pszSubRoot, const char *pszLogRoot,
     272                           HKEY hkeyAltRoot, const char *pszAltSubRoot, bool fUnregisterOnly, DWORD fSamWow)
     273{
     274    LSTATUS rc;
     275    REGSAM  fAccess = !fUnregisterOnly
     276                    ? DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY
     277                    : DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE;
     278
     279    pState->hkeyClassesRootDst          = NULL;
     280    pState->hkeyClsidRootDst            = NULL;
     281    pState->pszLogRoot                  = pszLogRoot;
     282    pState->hkeyAltClassesRootsUnreg    = NULL;
     283    pState->hkeyAltClsidRootsUnreg      = NULL;
     284    pState->fUnregisterOnly             = fUnregisterOnly;
     285    pState->fSamWow                     = fSamWow;
     286    pState->fSamUnreg                   = pState->fSamWow | DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE;
     287    pState->fSamBoth                    = pState->fSamUnreg | (!fUnregisterOnly ? KEY_SET_VALUE | KEY_CREATE_SUB_KEY : 0);
     288    pState->rc                          = ERROR_SUCCESS;
     289
     290    rc = RegOpenKeyExA(hkeyRoot, pszSubRoot, 0 /*fOptions*/, pState->fSamBoth, &pState->hkeyClassesRootDst);
     291    AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     292    rc = RegOpenKeyExA(pState->hkeyClassesRootDst, "CLSID", 0 /*fOptions*/, pState->fSamBoth, &pState->hkeyClsidRootDst);
     293    AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     294    if (hkeyAltRoot)
     295    {
     296        rc = RegOpenKeyExA(hkeyAltRoot, pszAltSubRoot, 0 /*fOptions*/, pState->fSamUnreg, &pState->hkeyAltClassesRootsUnreg);
     297        AssertMsgReturn(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc);
     298        if (pState->hkeyAltClassesRootsUnreg)
     299        {
     300            rc = RegOpenKeyExA(pState->hkeyAltClassesRootsUnreg, "CLSID", 0 /*fOptions*/, pState->fSamUnreg,
     301                               &pState->hkeyAltClsidRootsUnreg);
     302            AssertMsgReturn(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc);
     303        }
     304    }
     305    return ERROR_SUCCESS;
     306}
     307
     308
     309/**
     310 * Terminates the state, closing all open keys.
     311 *
     312 * @param   pState          The state to clean up.
     313 */
     314static void vbpsRegTerm(VBPSREGSTATE *pState)
     315{
     316    LSTATUS rc;
     317    if (pState->hkeyClassesRootDst)
     318    {
     319        rc = RegCloseKey(pState->hkeyClassesRootDst);
     320        Assert(rc == ERROR_SUCCESS);
     321        pState->hkeyClassesRootDst = NULL;
     322    }
     323    if (pState->hkeyClsidRootDst)
     324    {
     325        rc = RegCloseKey(pState->hkeyClsidRootDst);
     326        Assert(rc == ERROR_SUCCESS);
     327        pState->hkeyClsidRootDst = NULL;
     328    }
     329    if (pState->hkeyAltClassesRootsUnreg)
     330    {
     331        rc = RegCloseKey(pState->hkeyAltClassesRootsUnreg);
     332        Assert(rc == ERROR_SUCCESS);
     333        pState->hkeyAltClassesRootsUnreg = NULL;
     334    }
     335    if (pState->hkeyAltClsidRootsUnreg)
     336    {
     337        rc = RegCloseKey(pState->hkeyAltClsidRootsUnreg);
     338        Assert(rc == ERROR_SUCCESS);
     339        pState->hkeyAltClsidRootsUnreg = NULL;
     340    }
     341}
     342
     343
     344/** The destination buffer size required by vbpsFormatUuidInCurly. */
     345#define CURLY_UUID_STR_BUF_SIZE     48
     346
     347/**
     348 * Formats a UUID to a string, inside curly braces.
     349 *
     350 * @returns ERROR_SUCCESS on success, otherwise windows error code.
     351 * @param   pszUuid             Output buffer of size CURLY_UUID_STR_BUF_SIZE.
     352 * @param   pUuid               The UUID to format.
     353 */
     354static LSTATUS vbpsFormatUuidInCurly(char *pszUuid, const CLSID *pUuid)
     355{
     356    unsigned char *pszTmpStr = NULL;
     357    size_t cchTmpStr;
     358    RPC_STATUS rc = UuidToStringA((UUID *)pUuid, &pszTmpStr);
     359    AssertReturnStmt(rc == RPC_S_OK, *pszUuid = '\0', ERROR_OUTOFMEMORY);
     360
     361    cchTmpStr = strlen((const char *)pszTmpStr);
     362    AssertReturnStmt(cchTmpStr == 36 && cchTmpStr < CURLY_UUID_STR_BUF_SIZE - 3, RpcStringFreeA(&pszTmpStr), ERROR_INVALID_DATA);
     363
     364    pszUuid[0] = '{';
     365    memcpy(pszUuid + 1, pszTmpStr, cchTmpStr);
     366    pszUuid[1 + cchTmpStr] = '}';
     367    pszUuid[1 + cchTmpStr + 1] = '\0';
     368
     369    RpcStringFreeA(&pszTmpStr);
     370    return ERROR_SUCCESS;
     371}
     372
     373
     374/**
     375 * Sets a registry string value.
     376 *
     377 * @returns See RegSetValueExA (errors are remembered in the state).
     378 * @param   pState              The registry modifier state.
     379 * @param   hKey                The key to add the value to.
     380 * @param   pszValueNm          The value name. NULL for setting the default.
     381 * @param   pszValue            The value string.
     382 * @param   uLine               The line we're called from.
     383 */
     384static LSTATUS vbpsSetRegValueAA(VBPSREGSTATE *pState, HKEY hKey, const char *pszValueNm, const char *pszValue, unsigned uLine)
     385{
     386    LSTATUS rc = RegSetValueExA(hKey, pszValueNm, 0 /*Reserved*/, REG_SZ, pszValue, (DWORD)strlen(pszValue) + 1);
     387    if (rc == ERROR_SUCCESS)
     388        return ERROR_SUCCESS;
     389    AssertMsgFailed(("%d: '%s'='%s' -> %u\n", uLine, pszValueNm, pszValue, rc));
     390    return pState->rc = rc;
     391}
     392
     393/**
     394 * Creates a registry key.
     395 *
     396 * @returns See RegCreateKeyA and RegSetValueExA (errors are remembered in the
     397 *          state).
     398 * @param   pState              The registry modifier state.
     399 * @param   hKeyParent          The parent key.
     400 * @param   pszKey              The new key under @a hKeyParent.
     401 * @param   phKey               Where to return the handle to the new key.
     402 * @param   uLine               The line we're called from.
     403 */
     404static LSTATUS vbpsCreateRegKeyA(VBPSREGSTATE *pState, HKEY hKeyParent, const char *pszKey, PHKEY phKey, unsigned uLine)
     405{
     406    HKEY hNewKey;
     407    LSTATUS rc = RegCreateKeyExA(hKeyParent, pszKey, 0 /*Reserved*/, NULL /*pszClass*/, 0 /*fOptions*/,
     408                                 pState->fSamBoth, NULL /*pSecAttr*/, &hNewKey, NULL /*pdwDisposition*/);
     409    if (rc == ERROR_SUCCESS)
     410        *phKey = hNewKey;
     411    else
     412    {
     413        AssertMsgFailed(("%d: create key '%s' -> %u\n", uLine, pszKey,  rc));
     414        pState->rc = rc;
     415        *phKey = NULL;
     416    }
     417    return rc;
     418}
     419
     420
     421/**
     422 * Creates a registry key with a default string value.
     423 *
     424 * @returns See RegCreateKeyA and RegSetValueExA (errors are remembered in the
     425 *          state).
     426 * @param   pState              The registry modifier state.
     427 * @param   hKeyParent          The parent key.
     428 * @param   pszKey              The new key under @a hKeyParent.
     429 * @param   pszValue            The value string.
     430 * @param   uLine               The line we're called from.
     431 */
     432static LSTATUS vbpsCreateRegKeyWithDefaultValueAA(VBPSREGSTATE *pState, HKEY hKeyParent, const char *pszKey,
     433                                                  const char *pszValue, unsigned uLine)
     434{
     435    HKEY hNewKey;
     436    LSTATUS rc = vbpsCreateRegKeyA(pState, hKeyParent, pszKey, &hNewKey, uLine);
     437    if (rc == ERROR_SUCCESS)
     438    {
     439        rc = vbpsSetRegValueAA(pState, hNewKey, NULL /*pszValueNm*/, pszValue, uLine);
     440        RegCloseKey(hNewKey);
     441    }
     442    else
     443    {
     444        AssertMsgFailed(("%d: create key '%s'(/Default='%s') -> %u\n", uLine, pszKey, pszValue, rc));
     445        pState->rc = rc;
     446    }
     447    return rc;
     448}
     449
     450
     451/**
     452 * Creates a registry key with a default string value, return the key.
     453 *
     454 * @returns See RegCreateKeyA and RegSetValueExA (errors are remembered in the
     455 *          state).
     456 * @param   pState              The registry modifier state.
     457 * @param   hKeyParent          The parent key.
     458 * @param   pszKey              The new key under @a hKeyParent.
     459 * @param   pszValue            The value string.
     460 * @param   phKey               Where to return the handle to the new key.
     461 * @param   uLine               The line we're called from.
     462 */
     463static LSTATUS vbpsCreateRegKeyWithDefaultValueAAEx(VBPSREGSTATE *pState, HKEY hKeyParent, const char *pszKey,
     464                                                    const char *pszValue, PHKEY phKey, unsigned uLine)
     465{
     466    HKEY hNewKey;
     467    LSTATUS rc = vbpsCreateRegKeyA(pState, hKeyParent, pszKey, &hNewKey, uLine);
     468    if (rc == ERROR_SUCCESS)
     469    {
     470        rc = vbpsSetRegValueAA(pState, hNewKey, NULL /*pszValueNm*/, pszValue, uLine);
     471        *phKey = hNewKey;
     472    }
     473    else
     474    {
     475        AssertMsgFailed(("%d: create key '%s'(/Default='%s') -> %u\n", uLine, pszKey, pszValue, rc));
     476        pState->rc = rc;
     477        *phKey = NULL;
     478    }
     479    return rc;
     480}
     481
     482
     483/**
     484 * Register an application id.
     485 *
     486 * @returns Windows error code (errors are rememberd in the state).
     487 * @param   pState              The registry modifier state.
     488 * @param   pszAppId            The application UUID string.
     489 * @param   pszDescription      The description string.
     490 */
     491LSTATUS VbpsRegisterAppId(VBPSREGSTATE *pState, const char *pszAppId, const char *pszDescription)
     492{
     493    LSTATUS rc;
     494    HKEY hkeyAppIds;
     495    Assert(*pszAppId == '{');
     496
     497    /* Always unregister. */
     498    if (pState->hkeyAltClassesRootsUnreg)
     499    {
     500        rc = RegOpenKeyExW(pState->hkeyAltClassesRootsUnreg, L"AppID", 0 /*fOptions*/, pState->fSamUnreg, &hkeyAppIds);
     501        AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc);
     502        if (rc == ERROR_SUCCESS)
     503        {
     504            rc = SHDeleteKeyA(hkeyAppIds, pszAppId);
     505            AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc);
     506            RegCloseKey(hkeyAppIds);
     507        }
     508    }
     509
     510    rc = RegOpenKeyExW(pState->hkeyClassesRootDst, L"AppID", 0 /*fOptions*/, pState->fSamBoth, &hkeyAppIds);
     511    AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     512    if (rc == ERROR_SUCCESS)
     513    {
     514        rc = SHDeleteKeyA(hkeyAppIds, pszAppId);
     515        AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc);
     516    }
     517
     518    /* Register */
     519    if (!pState->fUnregisterOnly)
     520        vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyAppIds, pszAppId, pszDescription, __LINE__);
     521
     522    RegCloseKey(hkeyAppIds);
     523
     524    return pState->rc;
     525}
     526
     527
     528/**
     529 * Register an class name.
     530 *
     531 * @returns Windows error code (errors are rememberd in the state).
     532 * @param   pState              The registry modifier state.
     533 * @param   pszClassName        The name of the class.
     534 * @param   pszDescription      The description string
     535 * @param   pClsId              The UUID for the class.
     536 * @param   pszCurVerSuffIfRootName     This is the current version suffix to
     537 *                                      append to @a pszClassName when
     538 *                                      registering the version idependent name.
     539 */
     540LSTATUS VbpsRegisterClassName(VBPSREGSTATE *pState, const char *pszClassName, const char *pszDescription,
     541                              const CLSID *pClsId, const char *pszCurVerSuffIfRootName)
     542{
     543    LSTATUS rc;
     544
     545    /*
     546     * Always unregister.
     547     */
     548    if (pState->hkeyAltClassesRootsUnreg)
     549    {
     550        rc = SHDeleteKeyA(pState->hkeyAltClassesRootsUnreg, pszClassName);
     551        AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc);
     552    }
     553
     554    rc = SHDeleteKeyA(pState->hkeyClassesRootDst, pszClassName);
     555    AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc);
     556
     557    if (!pState->fUnregisterOnly)
     558    {
     559        /*
     560         * Register
     561         */
     562        /* pszClassName/Default = description. */
     563        HKEY hkeyClass;
     564        rc = vbpsCreateRegKeyWithDefaultValueAAEx(pState, pState->hkeyClassesRootDst, pszClassName, pszDescription,
     565                                                  &hkeyClass, __LINE__);
     566        if (rc == ERROR_SUCCESS)
     567        {
     568            char szClsId[CURLY_UUID_STR_BUF_SIZE];
     569
     570            /* CLSID/Default = pClsId. */
     571            rc = vbpsFormatUuidInCurly(szClsId, pClsId);
     572            AssertMsgStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     573            if (rc == ERROR_SUCCESS)
     574                vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyClass, "CLSID", szClsId, __LINE__);
     575
     576            /* CurVer/Default = pszClassName+Suffix. */
     577            if (pszCurVerSuffIfRootName != NULL)
     578            {
     579                char szCurClassNameVer[128];
     580                rc = RTStrCopy(szCurClassNameVer, sizeof(szCurClassNameVer), pszClassName);
     581                if (RT_SUCCESS(rc))
     582                    rc = RTStrCat(szCurClassNameVer, sizeof(szCurClassNameVer), pszCurVerSuffIfRootName);
     583                AssertStmt(RT_SUCCESS(rc), pState->rc = rc = ERROR_INVALID_DATA);
     584                if (rc == ERROR_SUCCESS)
     585                    vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyClass, "CurVer", szCurClassNameVer, __LINE__);
     586            }
     587
     588            RegCloseKey(hkeyClass);
     589        }
     590    }
     591
     592    return pState->rc;
     593}
     594
     595
     596/**
     597 * Registers a class ID.
     598 *
     599 * @returns Windows error code (errors are rememberd in the state).
     600 * @param   pState                      The registry modifier state.
     601 * @param   pClsId                      The UUID for the class.
     602 * @param   pszDescription              The description string.
     603 * @param   pszAppId                    The application ID.
     604 * @param   pszClassName                The version idependent class name.
     605 * @param   pszCurClassNameVerSuffix    The suffix to add to @a pszClassName for
     606 *                                      the current version.
     607 * @param   pTypeLibId                  The UUID for the typelib this class
     608 *                                      belongs to.
     609 * @param   pszServerType               The server type (InprocServer32 or
     610 *                                      LocalServer32).
     611 * @param   pwszVBoxDir                 The VirtualBox install directory
     612 *                                      (unicode), trailing slash.
     613 * @param   pszServerSubPath            What to append to @a pwszVBoxDir to
     614 *                                      construct the server module name.
     615 * @param   pszThreadingModel           The threading model for inproc servers,
     616 *                                      NULL for local servers.
     617 */
     618LSTATUS VbpsRegisterClassId(VBPSREGSTATE *pState, const CLSID *pClsId, const char *pszDescription, const char *pszAppId,
     619                            const char *pszClassName, const char *pszCurClassNameVerSuffix, const CLSID *pTypeLibId,
     620                            const char *pszServerType, PCRTUTF16 pwszVBoxDir, const char *pszServerSubPath,
     621                            const char *pszThreadingModel)
     622{
     623    LSTATUS rc;
     624    char szClsId[CURLY_UUID_STR_BUF_SIZE];
     625    char szTypeLibId[CURLY_UUID_STR_BUF_SIZE];
     626
     627    Assert(!pszAppId || *pszAppId == '{');
     628    Assert((pwszVBoxDir == NULL && pState->fUnregisterOnly) || pwszVBoxDir[RTUtf16Len(pwszVBoxDir) - 1] == '\\');
     629
     630    /*
     631     * Format the UUID first to get it over with.  We always need CLSID.
     632     */
     633    rc = vbpsFormatUuidInCurly(szClsId, pClsId);
     634    AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     635    if (pTypeLibId)
     636    {
     637        rc = vbpsFormatUuidInCurly(szTypeLibId, pTypeLibId);
     638        AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     639    }
     640    else
     641        szTypeLibId[0] = '\0';
     642
     643    /*
     644     * Always unregister.
     645     */
     646    if (pState->hkeyAltClsidRootsUnreg)
     647    {
     648        rc = SHDeleteKeyA(pState->hkeyAltClsidRootsUnreg, szClsId);
     649        AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc);
     650    }
     651
     652    rc = SHDeleteKeyA(pState->hkeyClsidRootDst, szClsId);
     653    AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc);
     654
     655    if (!pState->fUnregisterOnly)
     656    {
     657        /*
     658         * Register
     659         */
     660        HKEY hkeyClass;
     661        rc = vbpsCreateRegKeyWithDefaultValueAAEx(pState, pState->hkeyClsidRootDst, szClsId, pszDescription,
     662                                                  &hkeyClass, __LINE__);
     663        if (rc == ERROR_SUCCESS)
     664        {
     665            HKEY hkeyServerType;
     666            char szCurClassNameVer[128];
     667
     668            /* pszServerType/Default = module. */
     669            rc = vbpsCreateRegKeyA(pState, hkeyClass, pszServerType, &hkeyServerType, __LINE__);
     670            if (rc == ERROR_SUCCESS)
     671            {
     672                RTUTF16 wszModule[MAX_PATH * 2];
     673                PRTUTF16 pwszCur = wszModule;
     674                bool fQuoteIt = strcmp(pszServerType, "LocalServer32") == 0;
     675                if (fQuoteIt)
     676                    *pwszCur++ = '"';
     677
     678                rc = RTUtf16Copy(pwszCur, MAX_PATH, pwszVBoxDir); AssertRC(rc);
     679                pwszCur += RTUtf16Len(pwszCur);
     680                rc = RTUtf16CopyAscii(pwszCur, MAX_PATH - 3, pszServerSubPath); AssertRC(rc);
     681                pwszCur += RTUtf16Len(pwszCur);
     682
     683                if (fQuoteIt)
     684                    *pwszCur++ = '"';
     685                *pwszCur++ = '\0';      /* included, so ++. */
     686
     687                rc = RegSetValueExW(hkeyServerType, NULL /*pszValueNm*/, 0 /*Reserved*/,
     688                                    REG_SZ, (const BYTE *)&wszModule[0], (DWORD)((uintptr_t)pwszCur - (uintptr_t)&wszModule[0]));
     689                AssertMsgStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     690
     691                /* pszServerType/ThreadingModel = pszThreading Model. */
     692                if (pszThreadingModel)
     693                    vbpsSetRegValueAA(pState, hkeyServerType, "ThreadingModel", pszThreadingModel, __LINE__);
     694
     695                RegCloseKey(hkeyServerType);
     696            }
     697
     698            /* ProgId/Default = pszClassName + pszCurClassNameVerSuffix. */
     699            if (pszClassName)
     700            {
     701                rc = RTStrCopy(szCurClassNameVer, sizeof(szCurClassNameVer), pszClassName);
     702                if (RT_SUCCESS(rc))
     703                    rc = RTStrCat(szCurClassNameVer, sizeof(szCurClassNameVer), pszCurClassNameVerSuffix);
     704                AssertStmt(RT_SUCCESS(rc), pState->rc = rc = ERROR_INVALID_DATA);
     705                if (rc == ERROR_SUCCESS)
     706                    vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyClass, "ProgId", szCurClassNameVer, __LINE__);
     707
     708                /* VersionIndependentProgID/Default = pszClassName. */
     709                vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyClass, "VersionIndependentProgID", pszClassName, __LINE__);
     710            }
     711
     712            /* TypeLib/Default = pTypeLibId. */
     713            if (pTypeLibId)
     714                vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyClass, "TypeLib", szTypeLibId, __LINE__);
     715
     716            RegCloseKey(hkeyClass);
     717        }
     718    }
     719
     720    return pState->rc;
     721}
     722
     723
     724/**
     725 * Register modules and classes from the VirtualBox.xidl file.
     726 *
     727 * @returns COM status code.
     728 * @param   pwszVBoxDir         The VirtualBox application directory.
     729 * @param   fIs32On64           Set if this is the 32-bit on 64-bit component.
     730 *
     731 * @todo convert to XSLT.
     732 */
     733void RegisterXidlModulesAndClassesGenerated(VBPSREGSTATE *pState, PCRTUTF16 pwszVBoxDir, bool fIs32On64)
     734{
     735    const char *pszAppId = "{819B4D85-9CEE-493C-B6FC-64FFE759B3C9}";
     736    const char *pszInprocDll = !fIs32On64 ? "VBoxC.dll" : "x86\\VBoxClient-x86.dll";
     737
     738    VbpsRegisterAppId(pState, pszAppId, "VirtualBox Application");
     739
     740    /* VBoxSVC */
     741    VbpsRegisterClassName(pState, "VirtualBox.VirtualBox.1", "VirtualBox Class", &CLSID_VirtualBox, NULL);
     742    VbpsRegisterClassName(pState, "VirtualBox.VirtualBox",   "VirtualBox Class", &CLSID_VirtualBox, ".1");
     743    VbpsRegisterClassId(pState, &CLSID_VirtualBox, "VirtualBox Class", pszAppId, "VirtualBox.VirtualBox", ".1",
     744                        &LIBID_VirtualBox, "LocalServer32", pwszVBoxDir, "VBoxSVC.exe", NULL /*N/A*/);
     745    /* VBoxC */
     746    VbpsRegisterClassName(pState, "VirtualBox.Session.1", "Session Class", &CLSID_Session, NULL);
     747    VbpsRegisterClassName(pState, "VirtualBox.Session", "Session Class", &CLSID_Session, "VirtualBox.Session.1");
     748    VbpsRegisterClassId(pState, &CLSID_Session, "Session Class", pszAppId, "VirtualBox.Session", ".1",
     749                        &LIBID_VirtualBox, "InprocServer32", pwszVBoxDir, pszInprocDll, "Free");
     750
     751    VbpsRegisterClassName(pState, "VirtualBox.VirtualBoxClient.1", "VirtualBoxClient Class", &CLSID_VirtualBoxClient, NULL);
     752    VbpsRegisterClassName(pState, "VirtualBox.VirtualBoxClient", "VirtualBoxClient Class", &CLSID_VirtualBoxClient, ".1");
     753    VbpsRegisterClassId(pState, &CLSID_VirtualBoxClient, "VirtualBoxClient Class", pszAppId,
     754                        "VirtualBox.VirtualBoxClient", ".1",
     755                        &LIBID_VirtualBox, "InprocServer32", pwszVBoxDir, pszInprocDll, "Free");
     756
     757}
     758
     759#ifndef VBOX_PROXY_STUB_32_ON_64
     760void RegisterOtherProxyStubAndTypelibDll(VBPSREGSTATE *pState, PCRTUTF16 pwszVBoxDir, bool fIs32On64)
     761{
     762    if (!pState->fUnregisterOnly)
     763    {
     764        const char *pszWinXx = !fIs32On64 ? "win64"             : "win32";
     765        const char *pszPsDll = !fIs32On64 ? "VBoxProxyStub.dll" : "VBoxProxyStub-x86.dll";
     766        char szTypeLibId[CURLY_UUID_STR_BUF_SIZE];
     767        char szMajMin[64];
     768        HKEY hKeyTypeLibs;
     769        HKEY hKeyTypeLibId;
     770        HKEY hKeyMajMin;
     771        HKEY hKey0;
     772        HKEY hKeyWinXx;
     773        LSTATUS rc;
     774
     775        /* Proxy stub factory class ID. */
     776        VbpsRegisterClassId(pState, &g_ProxyClsId, "PSFactoryBuffer", NULL /*pszAppId*/,
     777                            NULL /*pszClassName*/, NULL /*pszCurClassNameVerSuffix*/, NULL /*pTypeLibId*/,
     778                            "InprocServer32", pwszVBoxDir, pszPsDll, "Both");
     779
     780        /*
     781         * Typelib DLL.
     782         */
     783        rc = vbpsFormatUuidInCurly(szTypeLibId, &LIBID_VirtualBox);
     784        AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     785
     786        rc = RegOpenKeyExA(pState->hkeyClassesRootDst, "TypeLib", 0 /*fOptions*/, pState->fSamBoth, &hKeyTypeLibs);
     787        AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     788        rc = RegOpenKeyExA(hKeyTypeLibs, szTypeLibId, 0 /*fOptions*/, pState->fSamBoth, &hKeyTypeLibId);
     789        if (rc == ERROR_FILE_NOT_FOUND)
     790            rc = vbpsCreateRegKeyA(pState, hKeyTypeLibs, szTypeLibId, &hKeyTypeLibId, __LINE__);
     791        RegCloseKey(hKeyTypeLibs);
     792
     793        AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     794
     795        /* Major.Minor/Default = Name. */
     796        sprintf(szMajMin, "%u.%u", kTypeLibraryMajorVersion, kTypeLibraryMinorVersion);
     797        rc = RegOpenKeyExA(hKeyTypeLibId, szMajMin, 0 /*fOptions*/, pState->fSamBoth, &hKeyMajMin);
     798        if (rc == ERROR_FILE_NOT_FOUND)
     799            rc = vbpsCreateRegKeyWithDefaultValueAAEx(pState, hKeyTypeLibId, szMajMin, "VirtualBox Type Library",
     800                                                      &hKeyMajMin, __LINE__);
     801        RegCloseKey(hKeyTypeLibId);
     802        AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     803
     804        /* 0/. */
     805        rc = RegOpenKeyExA(hKeyMajMin, "0", 0 /*fOptions*/, pState->fSamBoth, &hKey0);
     806        if (rc == ERROR_FILE_NOT_FOUND)
     807            rc = vbpsCreateRegKeyA(pState, hKeyMajMin, "0", &hKey0, __LINE__);
     808        RegCloseKey(hKeyMajMin);
     809        AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     810
     811        /* winXx/Default = VBoxProxyStub. */
     812        rc = RegOpenKeyExA(hKey0, pszWinXx, 0 /*fOptions*/, pState->fSamBoth, &hKeyWinXx);
     813        if (rc == ERROR_FILE_NOT_FOUND)
     814        {
     815            RTUTF16 wszDllPath[MAX_PATH * 2];
     816
     817            rc = RTUtf16Copy(wszDllPath, MAX_PATH, pwszVBoxDir); AssertRC(rc);
     818            rc = RTUtf16CatAscii(wszDllPath, MAX_PATH * 2, pszPsDll); AssertRC(rc);
     819
     820            rc = vbpsCreateRegKeyA(pState, hKey0, pszWinXx, &hKeyWinXx, __LINE__);
     821            if (rc == ERROR_SUCCESS)
     822            {
     823                rc = RegSetValueExW(hKeyWinXx, NULL /*pszValueNm*/, 0 /*Reserved*/,
     824                                    REG_SZ, (const BYTE *)&wszDllPath[0], (DWORD)((RTUtf16Len(wszDllPath) + 1 )* 2));
     825                AssertMsgStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     826            }
     827        }
     828        RegCloseKey(hKey0);
     829        AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);
     830        RegCloseKey(hKeyWinXx);
     831    }
     832
     833}
     834#endif
     835
     836
     837HRESULT RegisterXidlModulesAndClasses(PRTUTF16 pwszDllName, bool fUnregisterOnly)
     838{
     839    VBPSREGSTATE State;
     840    LSTATUS rc;
     841
     842    /*
     843     * Drop the filename and get the directory containing the DLL.
     844     */
     845    if (!fUnregisterOnly)
     846    {
     847        RTUTF16 wc;
     848        size_t off = RTUtf16Len(pwszDllName);
     849        while (   off > 0
     850               && (   (wc = pwszDllName[off - 1]) >= 127U
     851                   || !RTPATH_IS_SEP((unsigned char)wc)))
     852            off--;
     853#ifdef VBOX_PROXY_STUB_32_ON_64
     854        /* The -x86 variant is in a x86 subdirectory, drop it. */
     855        while (   off > 0
     856               && (   (wc = pwszDllName[off - 1]) < 127U
     857                   && RTPATH_IS_SEP((unsigned char)wc)))
     858            off--;
     859        while (   off > 0
     860               && (   (wc = pwszDllName[off - 1]) >= 127U
     861                   || !RTPATH_IS_SEP((unsigned char)wc)))
     862            off--;
     863#endif
     864        pwszDllName[off] = '\0';
     865    }
     866
     867    /*
     868     * Do registration for the current execution mode of the DLL.
     869     */
     870    rc = vbpsRegInit(&State,
     871                     HKEY_CLASSES_ROOT, NULL, "HKCR", /* HKEY_LOCAL_MACHINE, "Software\\Classes", "HKLM\\Software\\Classes", */
     872                     HKEY_CURRENT_USER,  "Software\\Classes",
     873                     fUnregisterOnly, 0);
     874    if (rc == ERROR_SUCCESS)
     875    {
     876#ifdef VBOX_PROXY_STUB_32_ON_64
     877        RegisterXidlModulesAndClassesGenerated(&State, pwszDllName, true);
     878#else
     879        RegisterXidlModulesAndClassesGenerated(&State, pwszDllName, false);
     880#endif
     881        rc = State.rc;
     882    }
     883
     884    vbpsRegTerm(&State);
     885
     886#ifndef VBOX_PROXY_STUB_32_ON_64
     887    /*
     888     * Do the WOW6432Node registrations too.
     889     */
     890    if (rc == ERROR_SUCCESS)
     891    {
     892        rc = vbpsRegInit(&State,
     893                         HKEY_CLASSES_ROOT, "Wow6432Node", "HKCR\\Wow6432Node",
     894                         HKEY_CURRENT_USER, "Software\\Classes",
     895                         fUnregisterOnly, KEY_WOW64_32KEY);
     896        if (rc == ERROR_SUCCESS)
     897        {
     898            RegisterXidlModulesAndClassesGenerated(&State, pwszDllName, true);
     899            RegisterOtherProxyStubAndTypelibDll(&State, pwszDllName, true);
     900            rc = State.rc;
     901        }
     902        vbpsRegTerm(&State);
     903    }
     904#endif
     905
     906    /*
     907     * Translate error code? Return.
     908     */
     909    if (rc == ERROR_SUCCESS)
     910        return S_OK;
     911    return E_FAIL;
     912}
     913
     914
     915/**
     916 * Register the interfaces proxied by this DLL, and to avoid duplication and
     917 * minimize work the VBox type library, classes and servers are also registered.
     918 *
     919 * @returns COM status code.
     920 */
     921HRESULT STDAPICALLTYPE DllRegisterServer(void)
     922{
     923    HRESULT hrc;
     924
     925    /*
     926     * Register the type library first.
     927     */
     928    ITypeLib *pITypeLib;
     929    WCHAR wszDllName[MAX_PATH];
     930    DWORD cwcRet = GetModuleFileNameW(g_hDllSelf, wszDllName, RT_ELEMENTS(wszDllName));
     931    AssertReturn(cwcRet > 0 && cwcRet < RT_ELEMENTS(wszDllName), CO_E_PATHTOOLONG);
     932
     933    hrc = LoadTypeLib(wszDllName, &pITypeLib);
     934    AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc);
     935    hrc = RegisterTypeLib(pITypeLib, wszDllName, NULL /*pszHelpDir*/);
     936    pITypeLib->lpVtbl->Release(pITypeLib);
     937    AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc);
     938
     939    /*
     940     * Register proxy stub.
     941     */
     942    hrc = NdrDllRegisterProxy(g_hDllSelf, &g_apProxyFiles[0], &g_ProxyClsId);         /* see DLLREGISTRY_ROUTINES in RpcProxy.h */
     943    AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc);
     944
     945    /*
     946     * Register the VBox modules and classes.
     947     */
     948    hrc = RegisterXidlModulesAndClasses(wszDllName, false /*fUnregisterOnly*/);
     949    AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc);
     950
     951    return S_OK;
     952}
     953
     954
     955/**
     956 * Reverse of DllRegisterServer.
     957 *
     958 * @returns COM status code.
     959 */
     960HRESULT STDAPICALLTYPE DllUnregisterServer(void)
     961{
     962    HRESULT hrc = S_OK;
     963    HRESULT hrc2;
     964
     965    /*
     966     * Unregister the type library.
     967     *
     968     * We ignore TYPE_E_REGISTRYACCESS as that is what is returned if the
     969     * type lib hasn't been registered (W10).
     970     */
     971    hrc2 = UnRegisterTypeLib(&LIBID_VirtualBox, kTypeLibraryMajorVersion, kTypeLibraryMinorVersion,
     972                             0 /*LCid*/, RT_CONCAT(SYS_WIN, ARCH_BITS));
     973    AssertMsgStmt(SUCCEEDED(hrc2) || hrc2 == TYPE_E_REGISTRYACCESS, ("%Rhrc\n", hrc2), if (SUCCEEDED(hrc)) hrc = hrc2);
     974
     975    /*
     976     * Unregister the proxy stub.
     977     *
     978     * We ignore ERROR_FILE_NOT_FOUND as that is returned if not registered (W10).
     979     */
     980    hrc2 = NdrDllUnregisterProxy(g_hDllSelf, &g_apProxyFiles[0], &g_ProxyClsId);      /* see DLLREGISTRY_ROUTINES in RpcProxy.h */
     981    AssertMsgStmt(   SUCCEEDED(hrc2)
     982                  || hrc2 == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND),
     983                  ("%Rhrc\n", hrc2), if (SUCCEEDED(hrc)) hrc = hrc2);
     984
     985    /*
     986     * Register the VBox modules and classes.
     987     */
     988    hrc2 = RegisterXidlModulesAndClasses(NULL, true /*fUnregisterOnly*/);
     989    AssertMsgStmt(SUCCEEDED(hrc2), ("%Rhrc\n", hrc2), if (SUCCEEDED(hrc)) hrc = hrc2);
     990
    137991#ifdef WITH_MANUAL_CLEANUP
     992    /*
     993     * Purge old mess.
     994     */
    138995    removeOldMess();
    139996#endif
     997
    140998    return hrc;
    141999}
     
    1821040{
    1831041    HKEY hkeyClsId;
    184     LONG rc = RegOpenKeyExA(hkeyClassesRoot, "CLSID", NULL, DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
     1042    LONG rc = RegOpenKeyExA(hkeyClassesRoot, "CLSID", 0, DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
    1851043                            &hkeyClsId);
    1861044    if (rc == ERROR_SUCCESS)
    1871045    {
    188         for (DWORD idxKey = 0;; idxKey++)
     1046        DWORD idxKey;
     1047        for (idxKey = 0;; idxKey++)
    1891048        {
    1901049            char szCurNm[128 + 128];
    1911050            DWORD cbCurNm = 128;
    1921051            rc = RegEnumKeyExA(hkeyClsId, idxKey, szCurNm, &cbCurNm, NULL, NULL, NULL, NULL);
    193             if (rc == ERROR_NO_MORE_ITEMS)
     1052            if (rc == ERROR_SUCCESS)
     1053            {
     1054                /*
     1055                 * Get the typelib GUID and program ID with the class ID.
     1056                 */
     1057                HKEY hkeyIfTypelib;
     1058                strcpy(&szCurNm[cbCurNm], "\\TypeLib");
     1059                rc = RegOpenKeyExA(hkeyClsId, szCurNm, 0, KEY_QUERY_VALUE, &hkeyIfTypelib);
     1060                if (rc == ERROR_SUCCESS)
     1061                {
     1062                    char szTypelibGuid[128];
     1063                    DWORD cbValue = sizeof(szTypelibGuid) - 1;
     1064                    rc = RegQueryValueExA(hkeyIfTypelib, NULL, NULL, NULL, (PBYTE)&szTypelibGuid[0], &cbValue);
     1065                    if (rc != ERROR_SUCCESS)
     1066                        cbValue = 0;
     1067                    szTypelibGuid[cbValue] = '\0';
     1068                    RegCloseKey(hkeyIfTypelib);
     1069                    if (isTypelibGuidToRemove(szTypelibGuid))
     1070                    {
     1071                        /* ProgId */
     1072                        HKEY hkeyIfProgId;
     1073                        strcpy(&szCurNm[cbCurNm], "\\ProgId");
     1074                        rc = RegOpenKeyExA(hkeyClsId, szCurNm, 0, KEY_QUERY_VALUE, &hkeyIfProgId);
     1075                        if (rc == ERROR_SUCCESS)
     1076                        {
     1077                            char szProgId[64];
     1078                            cbValue = sizeof(szProgId) - 1;
     1079                            rc = RegQueryValueExA(hkeyIfProgId, NULL, NULL, NULL, (PBYTE)&szProgId[0], &cbValue);
     1080                            if (rc != ERROR_SUCCESS)
     1081                                cbValue = 0;
     1082                            szProgId[cbValue] = '\0';
     1083                            RegCloseKey(hkeyIfProgId);
     1084                            if (   rc == ERROR_SUCCESS
     1085                                && strnicmp(szProgId, RT_STR_TUPLE("VirtualBox.")) == 0)
     1086                            {
     1087                                /*
     1088                                 * Ok, it's an orphaned VirtualBox interface. Delete it.
     1089                                 */
     1090                                szCurNm[cbCurNm] = '\0';
     1091#ifdef DEBUG_bird
     1092                                RTAssertMsg2("Should delete HCR/CLSID/%s\n", szCurNm);
     1093#endif
     1094                                rc = SHDeleteKeyA(hkeyClsId, szCurNm);
     1095                                Assert(rc == ERROR_SUCCESS);
     1096                            }
     1097                        }
     1098                    }
     1099                }
     1100
     1101            }
     1102            else
     1103            {
     1104                Assert(rc == ERROR_NO_MORE_ITEMS);
    1941105                break;
    195 
    196             /*
    197              * Get the typelib GUID and program ID with the class ID.
    198              */
    199             AssertBreak(rc == ERROR_SUCCESS);
    200             strcpy(&szCurNm[cbCurNm], "\\TypeLib");
    201             HKEY hkeyIfTypelib;
    202             rc = RegOpenKeyExA(hkeyClsId, szCurNm, NULL, KEY_QUERY_VALUE, &hkeyIfTypelib);
    203             if (rc != ERROR_SUCCESS)
    204                 continue;
    205 
    206             char szTypelibGuid[128];
    207             DWORD cbValue = sizeof(szTypelibGuid) - 1;
    208             rc = RegQueryValueExA(hkeyIfTypelib, NULL, NULL, NULL, (PBYTE)&szTypelibGuid[0], &cbValue);
    209             if (rc != ERROR_SUCCESS)
    210                 cbValue = 0;
    211             szTypelibGuid[cbValue] = '\0';
    212             RegCloseKey(hkeyIfTypelib);
    213             if (!isTypelibGuidToRemove(szTypelibGuid))
    214                 continue;
    215 
    216             /* ProgId */
    217             strcpy(&szCurNm[cbCurNm], "\\ProgId");
    218             HKEY hkeyIfProgId;
    219             rc = RegOpenKeyExA(hkeyClsId, szCurNm, NULL, KEY_QUERY_VALUE, &hkeyIfProgId);
    220             if (rc != ERROR_SUCCESS)
    221                 continue;
    222 
    223             char szProgId[64];
    224             cbValue = sizeof(szProgId) - 1;
    225             rc = RegQueryValueExA(hkeyIfProgId, NULL, NULL, NULL, (PBYTE)&szProgId[0], &cbValue);
    226             if (rc != ERROR_SUCCESS)
    227                 cbValue = 0;
    228             szProgId[cbValue] = '\0';
    229             RegCloseKey(hkeyIfProgId);
    230             if (strnicmp(szProgId, RT_STR_TUPLE("VirtualBox.")))
    231                 continue;
    232 
    233             /*
    234              * Ok, it's an orphaned VirtualBox interface. Delete it.
    235              */
    236             szCurNm[cbCurNm] = '\0';
    237             RTAssertMsg2("Should delete HCR/CLSID/%s\n", szCurNm);
    238             //rc = SHDeleteKeyA(hkeyClsId, szCurNm);
    239             Assert(rc == ERROR_SUCCESS);
     1106            }
    2401107        }
    2411108
     
    2521119{
    2531120    HKEY hkeyInterface;
    254     LONG rc = RegOpenKeyExA(hkeyClassesRoot, "Interface", NULL, DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
     1121    LONG rc = RegOpenKeyExA(hkeyClassesRoot, "Interface", 0, DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
    2551122                            &hkeyInterface);
    2561123    if (rc == ERROR_SUCCESS)
    2571124    {
    258         for (DWORD idxKey = 0;; idxKey++)
     1125        DWORD idxKey;
     1126        for (idxKey = 0;; idxKey++)
    2591127        {
    2601128            char szCurNm[128 + 128];
    2611129            DWORD cbCurNm = 128;
    2621130            rc = RegEnumKeyExA(hkeyInterface, idxKey, szCurNm, &cbCurNm, NULL, NULL, NULL, NULL);
    263             if (rc == ERROR_NO_MORE_ITEMS)
     1131            if (rc == ERROR_SUCCESS)
     1132            {
     1133                /*
     1134                 * Get the typelib GUID and version associated with the interface.
     1135                 */
     1136                HKEY hkeyIfTypelib;
     1137                strcpy(&szCurNm[cbCurNm], "\\TypeLib");
     1138                rc = RegOpenKeyExA(hkeyInterface, szCurNm, 0, KEY_QUERY_VALUE, &hkeyIfTypelib);
     1139                if (rc == ERROR_SUCCESS)
     1140                {
     1141                    char szTypelibGuid[128];
     1142                    DWORD cbValue = sizeof(szTypelibGuid) - 1;
     1143                    rc = RegQueryValueExA(hkeyIfTypelib, 0, NULL, NULL, (PBYTE)&szTypelibGuid[0], &cbValue);
     1144                    if (rc != ERROR_SUCCESS)
     1145                        cbValue = 0;
     1146                    szTypelibGuid[cbValue] = '\0';
     1147                    if (   rc == ERROR_SUCCESS
     1148                        && isTypelibGuidToRemove(szTypelibGuid))
     1149                    {
     1150                        char szTypelibVer[64];
     1151                        cbValue = sizeof(szTypelibVer) - 1;
     1152                        rc = RegQueryValueExA(hkeyIfTypelib, "Version", 0, NULL, (PBYTE)&szTypelibVer[0], &cbValue);
     1153                        if (rc != ERROR_SUCCESS)
     1154                            cbValue = 0;
     1155                        szTypelibVer[cbValue] = '\0';
     1156
     1157                        if (   rc == ERROR_SUCCESS
     1158                            && isTypelibVersionToRemove(szTypelibVer))
     1159                        {
     1160                            /*
     1161                             * Ok, it's an orphaned VirtualBox interface. Delete it.
     1162                             */
     1163                            szCurNm[cbCurNm] = '\0';
     1164                            RTAssertMsg2("Should delete HCR/Interface/%s\n", szCurNm);
     1165                            rc = SHDeleteKeyA(hkeyInterface, szCurNm);
     1166                            Assert(rc == ERROR_SUCCESS);
     1167                        }
     1168                    }
     1169                    RegCloseKey(hkeyIfTypelib);
     1170                }
     1171            }
     1172            else
     1173            {
     1174                Assert(rc == ERROR_NO_MORE_ITEMS);
    2641175                break;
    265 
    266             /*
    267              * Get the typelib GUID and version associated with the interface.
    268              */
    269             AssertBreak(rc == ERROR_SUCCESS);
    270             strcpy(&szCurNm[cbCurNm], "\\TypeLib");
    271             HKEY hkeyIfTypelib;
    272             rc = RegOpenKeyExA(hkeyInterface, szCurNm, NULL, KEY_QUERY_VALUE, &hkeyIfTypelib);
    273             if (rc != ERROR_SUCCESS)
    274                 continue;
    275 
    276             char szTypelibGuid[128];
    277             DWORD cbValue = sizeof(szTypelibGuid) - 1;
    278             rc = RegQueryValueExA(hkeyIfTypelib, NULL, NULL, NULL, (PBYTE)&szTypelibGuid[0], &cbValue);
    279             if (rc != ERROR_SUCCESS)
    280                 cbValue = 0;
    281             szTypelibGuid[cbValue] = '\0';
    282             if (!isTypelibGuidToRemove(szTypelibGuid))
    283             {
    284                 RegCloseKey(hkeyIfTypelib);
    285                 continue;
    2861176            }
    287 
    288             char szTypelibVer[64];
    289             cbValue = sizeof(szTypelibVer) - 1;
    290             rc = RegQueryValueExA(hkeyIfTypelib, "Version", NULL, NULL, (PBYTE)&szTypelibVer[0], &cbValue);
    291             if (rc != ERROR_SUCCESS)
    292                 cbValue = 0;
    293             szTypelibVer[cbValue] = '\0';
    294 
    295             RegCloseKey(hkeyIfTypelib);
    296 
    297             if (!isTypelibVersionToRemove(szTypelibVer))
    298                 continue;
    299 
    300 
    301             /*
    302              * Ok, it's an orphaned VirtualBox interface. Delete it.
    303              */
    304             szCurNm[cbCurNm] = '\0';
    305             //RTAssertMsg2("Should delete HCR/Interface/%s\n", szCurNm);
    306             rc = SHDeleteKeyA(hkeyInterface, szCurNm);
    307             Assert(rc == ERROR_SUCCESS);
    3081177        }
    3091178
     
    3251194    {
    3261195        HKEY hkeyTyplib;
    327         LONG rc = RegOpenKeyExA(hkeyClassesRoot, g_apszTypelibGuidKeys[i], NULL,
     1196        LONG rc = RegOpenKeyExA(hkeyClassesRoot, g_apszTypelibGuidKeys[i], 0,
    3281197                                DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkeyTyplib);
    3291198        if (rc == ERROR_SUCCESS)
     
    3331202            {
    3341203                HKEY hkeyVer;
    335                 rc = RegOpenKeyExA(hkeyTyplib, g_apszTypelibVersions[iVer], NULL, KEY_READ, &hkeyVer);
     1204                rc = RegOpenKeyExA(hkeyTyplib, g_apszTypelibVersions[iVer], 0, KEY_READ, &hkeyVer);
    3361205                if (rc == ERROR_SUCCESS)
    3371206                {
     
    3501219                             * Delete the type library.
    3511220                             */
    352                             //RTAssertMsg2("Should delete HCR\\%s\\%s\n", g_apszTypelibGuidKeys[i], g_apszTypelibVersions[iVer]);
     1221                            RTAssertMsg2("Should delete HCR\\%s\\%s\n", g_apszTypelibGuidKeys[i], g_apszTypelibVersions[iVer]);
    3531222                            rc = SHDeleteKeyA(hkeyTyplib, g_apszTypelibVersions[iVer]);
    3541223                            Assert(rc == ERROR_SUCCESS);
     
    3771246static void removeOldMess(void)
    3781247{
     1248    HKEY hkeyWow64;
     1249    LONG rc;
     1250
    3791251    /*
    3801252     * The standard location.
     
    3871259     * Wow64 if present.
    3881260     */
    389     HKEY hkeyWow64;
    390     LONG rc = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Wow6432Node", NULL,
    391                             DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkeyWow64);
     1261    rc = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Wow6432Node", 0, DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkeyWow64);
    3921262    if (rc == ERROR_SUCCESS)
    3931263    {
  • trunk/src/VBox/Main/src-all/win/VBoxProxyStub.def

    r49908 r59363  
    11; $Id$
    22;; @file
    3 ; VBoxC DLL Definition File.
     3; VBoxProxyStub DLL Definition File.
    44;
    55
    66;
    7 ; Copyright (C) 2006-2013 Oracle Corporation
     7; Copyright (C) 2006-2016 Oracle Corporation
    88;
    99; This file is part of VirtualBox Open Source Edition (OSE), as
     
    2323    DllRegisterServer   PRIVATE
    2424    DllUnregisterServer PRIVATE
     25    GetProxyDllInfo     PRIVATE
    2526
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette