VirtualBox

Ignore:
Timestamp:
Apr 23, 2021 7:24:05 PM (4 years ago)
Author:
vboxsync
Message:

VBoxRT: Added RTTHREADFLAGS_COM_MTA and RTTHREADFLAGS_COM_STA flags to RTThreadCreate to make it easier to initialize COM for worker threads in (PDM) drivers and such. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/thread-win.cpp

    r86171 r88688  
    4242#include <iprt/cpuset.h>
    4343#include <iprt/err.h>
     44#include <iprt/ldr.h>
    4445#include <iprt/log.h>
    4546#include <iprt/mem.h>
     
    5556typedef HRESULT (WINAPI *PFNSETTHREADDESCRIPTION)(HANDLE hThread, WCHAR *pwszName); /* Since W10 1607 */
    5657
     58/** CoInitializeEx */
     59typedef HRESULT (WINAPI *PFNCOINITIALIZEEX)(LPVOID, DWORD);
     60/** CoUninitialize */
     61typedef void (WINAPI *PFNCOUNINITIALIZE)(void);
     62/** OleUninitialize */
     63typedef void (WINAPI *PFNOLEUNINITIALIZE)(void);
     64
     65
    5766
    5867/*********************************************************************************************************************************
     
    6069*********************************************************************************************************************************/
    6170/** The TLS index allocated for storing the RTTHREADINT pointer. */
    62 static DWORD g_dwSelfTLS = TLS_OUT_OF_INDEXES;
     71static DWORD                    g_dwSelfTLS = TLS_OUT_OF_INDEXES;
    6372/** Pointer to SetThreadDescription (KERNEL32.DLL) if available. */
    64 static PFNSETTHREADDESCRIPTION g_pfnSetThreadDescription = NULL;
     73static PFNSETTHREADDESCRIPTION  g_pfnSetThreadDescription = NULL;
     74
     75/** Pointer to CoInitializeEx (OLE32.DLL / combase.dll) if available. */
     76static PFNCOINITIALIZEEX volatile   g_pfnCoInitializeEx  = NULL;
     77/** Pointer to CoUninitialize (OLE32.DLL / combase.dll) if available. */
     78static PFNCOUNINITIALIZE volatile   g_pfnCoUninitialize  = NULL;
     79/** Pointer to OleUninitialize (OLE32.DLL / combase.dll) if available. */
     80static PFNOLEUNINITIALIZE volatile  g_pfnOleUninitialize = NULL;
    6581
    6682
     
    251267                         cComInits, cComInits, cOleInits, cOleInits));
    252268
    253         HMODULE hOle32 = GetModuleHandle("ole32.dll");
    254         AssertReturnVoid(hOle32 != NULL);
    255 
    256         typedef void (WINAPI *PFNOLEUNINITIALIZE)(void);
    257         PFNOLEUNINITIALIZE  pfnOleUninitialize = (PFNOLEUNINITIALIZE)GetProcAddress(hOle32, "OleUninitialize");
    258         AssertReturnVoid(pfnOleUninitialize);
    259 
    260         typedef void (WINAPI *PFNCOUNINITIALIZE)(void);
    261         PFNCOUNINITIALIZE   pfnCoUninitialize  = (PFNCOUNINITIALIZE)GetProcAddress(hOle32, "CoUninitialize");
    262         AssertReturnVoid(pfnCoUninitialize);
     269        PFNOLEUNINITIALIZE  pfnOleUninitialize = g_pfnOleUninitialize;
     270        PFNCOUNINITIALIZE   pfnCoUninitialize  = g_pfnCoUninitialize;
     271        if (pfnCoUninitialize && pfnOleUninitialize)
     272        { /* likely */ }
     273        else
     274        {
     275            HMODULE hOle32 = GetModuleHandle("ole32.dll");
     276            AssertReturnVoid(hOle32 != NULL);
     277
     278            pfnOleUninitialize = (PFNOLEUNINITIALIZE)GetProcAddress(hOle32, "OleUninitialize");
     279            AssertReturnVoid(pfnOleUninitialize);
     280
     281            pfnCoUninitialize  = (PFNCOUNINITIALIZE)GetProcAddress(hOle32, "CoUninitialize");
     282            AssertReturnVoid(pfnCoUninitialize);
     283        }
    263284
    264285        while (cOleInits-- > 0)
     
    276297
    277298/**
     299 * Implements the RTTHREADFLAGS_COM_MTA and RTTHREADFLAGS_COM_STA flags.
     300 *
     301 * @returns true if COM uninitialization should be done, false if not.
     302 * @param   fFlags      The thread flags.
     303 */
     304static bool rtThreadNativeWinCoInitialize(unsigned fFlags)
     305{
     306    /*
     307     * Resolve the ole32 init and uninit functions dynamically.
     308     */
     309    PFNCOINITIALIZEEX pfnCoInitializeEx = g_pfnCoInitializeEx;
     310    PFNCOUNINITIALIZE pfnCoUninitialize = g_pfnCoUninitialize;
     311    if (pfnCoInitializeEx && pfnCoUninitialize)
     312    { /* likely */ }
     313    else
     314    {
     315        RTLDRMOD hModOle32 = NIL_RTLDRMOD;
     316        int rc = RTLdrLoadSystem("ole32.dll", true /*fNoUnload*/, &hModOle32);
     317        AssertRCReturn(rc, false);
     318
     319        PFNOLEUNINITIALIZE pfnOleUninitialize;
     320        pfnOleUninitialize = (PFNOLEUNINITIALIZE)RTLdrGetFunction(hModOle32, "OleUninitialize");
     321        pfnCoUninitialize  = (PFNCOUNINITIALIZE )RTLdrGetFunction(hModOle32, "CoUninitialize");
     322        pfnCoInitializeEx  = (PFNCOINITIALIZEEX )RTLdrGetFunction(hModOle32, "CoInitializeEx");
     323
     324        RTLdrClose(hModOle32);
     325        AssertReturn(pfnCoInitializeEx && pfnCoUninitialize, false);
     326
     327        if (pfnOleUninitialize && !g_pfnOleUninitialize)
     328            g_pfnOleUninitialize = pfnOleUninitialize;
     329        g_pfnCoInitializeEx = pfnCoInitializeEx;
     330        g_pfnCoUninitialize = pfnCoUninitialize;
     331    }
     332
     333    /*
     334     * Do the initializating.
     335     */
     336    DWORD fComInit;
     337    if (fFlags & RTTHREADFLAGS_COM_MTA)
     338        fComInit = COINIT_MULTITHREADED     | COINIT_SPEED_OVER_MEMORY | COINIT_DISABLE_OLE1DDE;
     339    else
     340        fComInit = COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY;
     341    HRESULT hrc = pfnCoInitializeEx(NULL, fComInit);
     342    AssertMsg(SUCCEEDED(hrc), ("%Rhrc fComInit=%#x\n", hrc, fComInit));
     343    return SUCCEEDED(hrc);
     344}
     345
     346
     347/**
    278348 * Wrapper which unpacks the param stuff and calls thread function.
    279349 */
     
    287357    rtThreadWinSetThreadName(pThread, dwThreadId);
    288358
     359    bool fUninitCom = (pThread->fFlags & (RTTHREADFLAGS_COM_MTA | RTTHREADFLAGS_COM_STA)) != 0;
     360    if (fUninitCom)
     361        fUninitCom = rtThreadNativeWinCoInitialize(pThread->fFlags);
     362
    289363    int rc = rtThreadMain(pThread, dwThreadId, &pThread->szName[0]);
     364
     365    if (fUninitCom && g_pfnCoUninitialize)
     366        g_pfnCoUninitialize();
    290367
    291368    TlsSetValue(g_dwSelfTLS, NULL);
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