Can we remove ATL dependencies? #958

Closed
opened 2026-01-30 22:12:25 +00:00 by claunia · 7 comments
Owner

Originally created by @miniksa on GitHub (May 10, 2019).

OK. The ATL/MFC dependency we seem to have here is super gross.

Can anyone run around and:

  1. Investigate what is actually using ATL in our project
  2. Come up with a proposal for changing it to use something that isn't ATL (because I presume it's something dumb like a CComPtr that could easily be replaced with another non-ATL ComPtr class)
  3. If it is just the ComPtr, then change it over in a PR.
Originally created by @miniksa on GitHub (May 10, 2019). OK. The ATL/MFC dependency we seem to have here is super gross. Can anyone run around and: 1. Investigate what is actually using ATL in our project 2. Come up with a proposal for changing it to use something that isn't ATL (because I presume it's something dumb like a CComPtr that could easily be replaced with another non-ATL ComPtr class) 3. If it is just the ComPtr, then change it over in a PR.
Author
Owner

@mikedn commented on GitHub (May 10, 2019):

Eh, it's a bit more complicated than CComPtr:

  • TSF also uses CComQIPtr and CComBSTR
  • The fuzzer uses CStringA and CComAllocator. It also includes atlcoll.h but apparently doesn't use it.

Needless to say that they all can be replaced but there aren't any "drop in" replacements. There's VC++'s own _com_ptr_t and _bstr_t classes but they're not quite like CComPtr and CComBSTR. winrt has a com_ptr but no bstr it seems.

As for CStringA, that surely won't be replaced by std::string without a fight. Kind of strange that the fuzzer doesn't already use std::string considering that it's already pretty C++ish.

Not sure if it's worth the trouble, these are all header only dependencies and AFAIR ATL headers are always installed so...

@mikedn commented on GitHub (May 10, 2019): Eh, it's a bit more complicated than `CComPtr`: * TSF also uses `CComQIPtr` and `CComBSTR` * The fuzzer uses `CStringA` and `CComAllocator`. It also includes `atlcoll.h` but apparently doesn't use it. Needless to say that they all can be replaced but there aren't any "drop in" replacements. There's VC++'s own `_com_ptr_t` and `_bstr_t` classes but they're not quite like `CComPtr` and `CComBSTR`. `winrt` has a `com_ptr` but no `bstr` it seems. As for `CStringA`, that surely won't be replaced by `std::string` without a fight. Kind of strange that the fuzzer doesn't already use `std::string` considering that it's already pretty C++ish. Not sure if it's worth the trouble, these are all header only dependencies and AFAIR ATL headers are always installed so...
Author
Owner

@ChrisGuzak commented on GitHub (May 12, 2019):

wil/com.h provides replacements for CComQIPtr . wil::com_ptr, wil::com_query, wil::com_try_query, com_ptr.query(), .try_query(), etc.

IUnknown* obj;
auto objPersist = wil::com_query<IPersist>(obj);

wil::com_ptr<IUnknown> unk;
auto other = unk.query<IOther>();

see the tests for examples.

@ChrisGuzak commented on GitHub (May 12, 2019): `wil/com.h` provides replacements for CComQIPtr . wil::com_ptr, wil::com_query, wil::com_try_query, com_ptr.query(), .try_query(), etc. ``` IUnknown* obj; auto objPersist = wil::com_query<IPersist>(obj); wil::com_ptr<IUnknown> unk; auto other = unk.query<IOther>(); ``` see [the tests](https://github.com/microsoft/wil/blob/master/tests/ComTests.cpp) for examples.
Author
Owner

@mikedn commented on GitHub (May 12, 2019):

Thanks, wil::com_ptr_nothrow (I don't think this codebase will want to deal with exceptions) looks like the best choice. The only "missing" feature would be a direct equivalent to CComPtr::CoCreateInstance - wil's own CoCreateInstance swallows the HRESULT. But the ::CoCreateInstance function works just fine.

As for CComBSTR, it turns out that there's no real need for BSTRs and std::wstring can be used instead.

@mikedn commented on GitHub (May 12, 2019): Thanks, `wil::com_ptr_nothrow` (I don't think this codebase will want to deal with exceptions) looks like the best choice. The only "missing" feature would be a direct equivalent to `CComPtr::CoCreateInstance` - `wil`'s own `CoCreateInstance` swallows the `HRESULT`. But the `::CoCreateInstance` function works just fine. As for `CComBSTR`, it turns out that there's no real need for BSTRs and `std::wstring` can be used instead.
Author
Owner

@ChrisGuzak commented on GitHub (May 12, 2019):

exceptions... if your using std::wstring you are using exceptions. go all in (this is our position for windows).

I see we should normalize on wil instead of WRL (watching the //build video I see lots of use of WRL). Much better than ATL but wil covers this ground better.

@ChrisGuzak commented on GitHub (May 12, 2019): exceptions... if your using std::wstring you are using exceptions. go all in (this is our position for windows). I see we should normalize on wil instead of WRL (watching the //build video I see lots of use of WRL). Much better than ATL but wil covers this ground better.
Author
Owner

@DHowett-MSFT commented on GitHub (May 12, 2019):

Yeah, we have exceptions here... but we do have some exception boundaries, which @adiviness is better qualified to speak on. There’s a document about exceptions in the /doc folder.

@ChrisGuzak is there a WIL version of WRL::RuntimeClass and the module management stuff? I think wil is great, but I’m hesitant to go from “that one component that uses ATL for COM” to “that one component that still doesn’t use WRL for COM” and keep a mixed-paradigm codebase...

@DHowett-MSFT commented on GitHub (May 12, 2019): Yeah, we have exceptions here... but we do have some exception boundaries, which @adiviness is better qualified to speak on. There’s a document about exceptions in the `/doc` folder. @ChrisGuzak is there a WIL version of `WRL::RuntimeClass` and the module management stuff? I think wil is great, but I’m hesitant to go from “that one component that uses ATL for COM” to “that one component that still doesn’t use WRL for COM” and keep a mixed-paradigm codebase...
Author
Owner

@mikedn commented on GitHub (May 12, 2019):

exceptions... if your using std::wstring you are using exceptions. go all in (this is our position for windows).

Hmm, right. And as far as I can tell most wil::com_ptr members don't actually throw exceptions anyway. Only a few do and the ones relevant to TSF (query) have "try" versions.

@mikedn commented on GitHub (May 12, 2019): > exceptions... if your using std::wstring you are using exceptions. go all in (this is our position for windows). Hmm, right. And as far as I can tell most `wil::com_ptr` members don't actually throw exceptions anyway. Only a few do and the ones relevant to TSF (`query`) have "try" versions.
Author
Owner

@adiviness commented on GitHub (May 12, 2019):

So for error handling, we have three ways: exceptions, HRESULT, and NTSTATUS. We've been trying to remove as much of the NTSTATUS usage as possible since it tends to cause problems when we mix HRESULT and NTSTATUS.

Exceptions can be used internally but they can't be leaked out publicly, such as through any of the ApiDispatchers in /src/server.

If a function can only return a single HRESULT (like S_OK) then it's better off being a function with a void return type then one that returns an HRESULT. We do have some implementations of interfaces that only return a single HRESULT but since it's required by the interface to return something they get a bit of a pass.

Any function that returns a status code of some sort must be marked noexcept and have the [[nodiscard]] attribute applied to it, unless there is some compelling reason why it can't (interop with C code for instance, or is implementing an API outside of our control).

Actually, we do have another status code, BOOL. I think this is mainly restricted to ConhostInternalGetSet and whatever interface it's implementing. This is something that I feel should be fixed up but hasn't been gotten around to yet. I'd also like to see us get rid of the mixed usage of bool, BOOL, and BOOLEAN as much as possible.

@adiviness commented on GitHub (May 12, 2019): So for error handling, we have three ways: exceptions, `HRESULT`, and `NTSTATUS`. We've been trying to remove as much of the `NTSTATUS` usage as possible since it tends to cause problems when we mix `HRESULT` and `NTSTATUS`. Exceptions can be used internally but they can't be leaked out publicly, such as through any of the `ApiDispatchers` in `/src/server`. If a function can only return a single `HRESULT` (like `S_OK`) then it's better off being a function with a `void` return type then one that returns an `HRESULT`. We do have some implementations of interfaces that only return a single `HRESULT` but since it's required by the interface to return something they get a bit of a pass. Any function that returns a status code of some sort must be marked `noexcept` and have the `[[nodiscard]]` attribute applied to it, unless there is some compelling reason why it can't (interop with C code for instance, or is implementing an API outside of our control). Actually, we do have another status code, `BOOL`. I think this is mainly restricted to `ConhostInternalGetSet` and whatever interface it's implementing. This is something that I feel should be fixed up but hasn't been gotten around to yet. I'd also like to see us get rid of the mixed usage of `bool`, `BOOL`, and `BOOLEAN` as much as possible.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#958