microsoft / wil

Windows Implementation Library
MIT License
2.57k stars 234 forks source link

Add helpers for implementing Out-Of-Proc COM Server with cppwinrt only (without WRL) #440

Closed roxk closed 5 months ago

roxk commented 6 months ago

Fixes #439

roxk commented 6 months ago

I found re-registering the same class doesn't trigger any error. Is there any trivial ways to make CoRegisterClassObject throw error without using e.g. invalid combination of flags? The doc says CoRegisterClassObject would only ever return invalid arguments, out of memory, or unexpected. How to trigger unexpected in a test?

dunhor commented 6 months ago

I found re-registering the same class doesn't trigger any error. Is there any trivial ways to make CoRegisterClassObject throw error without using e.g. invalid combination of flags? The doc says CoRegisterClassObject would only ever return invalid arguments, out of memory, or unexpected. How to trigger unexpected in a test?

You can detour the function to return whatever you wish. E.g.

witest::detoured_thread_function<&::CoRegisterClassObject> detour(
    [](REFCLSID, LPUNKNOWN, DWORD, DWORD, LPDWORD cookie) {
        *cookie = 0;
        return E_UNEXPECTED;
    });

or

witest::detoured_thread_function<&::CoRegisterClassObject> detour(
    [n = 0](REFCLSID clsid, LPUNKNOWN obj, DWORD ctxt, DWORD flags, LPDWORD cookie) mutable {
        // Only return failure on the fifth invocation
        if (++n == 5)
        {
            *cookie = 0;
            return E_UNEXPECTED;
        }
        return ::CoRegisterClassObject(clsid, obj, ctxt, flags, cookie);
    });
roxk commented 6 months ago

You can detour the function to return whatever you wish

Added test to test register_com_server failure mode.

(this witest detour API is so handy I feel like it should be part of wil instead of witest)

dunhor commented 6 months ago

You can detour the function to return whatever you wish

Added test to test register_com_server failure mode.

(this witest detour API is so handy I feel like it should be part of wil instead of witest)

Note that code in mocking.h is something I quickly hacked together over the winter holidays during some spare down time. It was inspired by/meant to resemble a lightweight version of an internal library we have for function mocking for tests. The internal WIL unit tests that existed before this repo used this library for a number of tests, and when I was porting those tests here, I had to hack together some alternate solutions, several of which have caused issues over the years, prompting me to create that header. The hope is that one day that library can be open sourced. That would be much better than this hacked together, minimally tested version that was mostly only designed to fit our testing needs. I actually looked into trying this, however at the time rolling my own seemed like the less time-consuming option.

roxk commented 5 months ago

That said, I'm still not super sold on the usefulness of WIL_CPPWINRT_COM_SERVER_CUSTOM_MODULE_LOCK, so I'm not sure many people would really encounter this.

Indeed. One can argue that if they are implementing a custom module lock anyways, they could add the set_notifier function themselves.

In the meantime, I would go ahead and split the lock impl to a base and an impl class.