[PATCH 2/6] ole32: Allow more functions to use the implicit MTA.

Zebediah Figura z.figura12 at gmail.com
Wed Mar 28 09:21:37 CDT 2018


On 28/03/18 03:43, Huw Davies wrote:
> On Sun, Mar 25, 2018 at 12:33:58PM -0500, Zebediah Figura wrote:
>> It's necessary to introduce the being_destroyed field since a destroyed
>> apartment may end up releasing proxy objects, which will require calling
>> various functions, e.g. CoGetPSClsid(), potentially triggering an infinite
>> recursion otherwise.
>>
>> Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
>> ---
>>  dlls/ole32/compobj.c         | 165 +++++++++++++++++++++++++------------------
>>  dlls/ole32/compobj_private.h |   1 +
>>  dlls/ole32/tests/compobj.c   |  23 ++++++
>>  3 files changed, 120 insertions(+), 69 deletions(-)
>>
>> diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
>> index cd0e67f..61a8ae6 100644
>> --- a/dlls/ole32/compobj.c
>> +++ b/dlls/ole32/compobj.c
>> @@ -717,6 +717,44 @@ static inline BOOL apartment_is_model(const APARTMENT *apt, DWORD model)
>>      return (apt->multi_threaded == !(model & COINIT_APARTMENTTHREADED));
>>  }
>>  
>> +/* gets the multi-threaded apartment if it exists. The caller must
>> + * release the reference from the apartment as soon as the apartment pointer
>> + * is no longer required. */
>> +static APARTMENT *apartment_find_multi_threaded(void)
>> +{
>> +    APARTMENT *result = NULL;
>> +    struct list *cursor;
>> +
>> +    EnterCriticalSection(&csApartment);
>> +
>> +    LIST_FOR_EACH( cursor, &apts )
>> +    {
>> +        struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry );
>> +        if (apt->multi_threaded)
>> +        {
>> +            result = apt;
>> +            apartment_addref(result);
>> +            break;
>> +        }
>> +    }
> 
> I know this function was copied from below, but there's the MTA variable
> (protected by csApartment) that holds the MTA if it exists.  So you
> could simply return that rather than loop through every apt.
> 
>> +
>> +    LeaveCriticalSection(&csApartment);
>> +    return result;
>> +}
>> +
>> +/* Return the current apartment if it exists, or, failing that, the MTA. Caller
>> + * must free the returned apartment in either case. */
>> +static APARTMENT *apartment_get_current_or_mta(void)
>> +{
>> +    APARTMENT *apt = COM_CurrentApt();
>> +    if (apt)
>> +    {
>> +        apartment_addref(apt);
>> +        return apt;
>> +    }
>> +    return apartment_find_multi_threaded();
>> +}
> 
> So this patch is doing a couple of things.  It's taking a ref on the
> current apt if one exists or using the MTA if it doesn't.  Since this
> code is so fragile, I'd like these split.  Something like this would
> work:
> 
> 2.1 Add apartment_addref()s / apartment_release()s to CoGetClassObject(),
> CoLockObjectExternal(), etc.  i.e. implement the 'taking a ref on the
> current apt' bit.
> 
> 2.2 Move apartment_find_multi_threaded() higher up in the file and rewrite
> using the MTA variable.  Also why not rename this to apartment_find_mta()
> 
> 2.3 Add apartment_get_current_or_mta() and use it in CoGetClassObject() etc.
> 
> Also, I'm not yet 100% convinced about the being_destroyed thing.  I'm
> wondering whether there's a better way of doing that.  Hopefully
> splitting this up will help with that.
> 
> Huw.

Thanks, that sounds like a good idea.

I think I considered locking the apartment using its critical section
instead and didn't due to concerns with marshalling, but I'll take a
closer look and see if that should be possible.



More information about the wine-devel mailing list