Building custom solutions that extend, automate, and integrate Microsoft 365 apps.
After a lot of trial and error, going through what the Office Update was changing in the Windows registry, attempting various changes in the configuration of the VS project and many other tests to no avail, I finally figured out what the problem was. I'm writing this answer to my own question in case anyone comes here with the same problem.
I was pointed in the right direction by a comment to an old similar question on the Stack Overflow site. Basically, the problem lies with the following line:
HRESULT hResult = CoCreateInstance(__uuidof(DAO::DBEngine), nullptr, CLSCTX_ALL, IID_IDispatch, reinterpret_cast<LPVOID*>(&daoEngine));
This line can be found all over the Internet and the person who originally wrote that code probably copied it from some sample code they found online. The problem is... this line of code is wrong. While this used to work without problems in the past, it stopped working at some point, probably because of recent changes made by Microsoft in how COM objects are instantiated.
The problem lies in the third parameter IID_IDispatch. According to the CoCreateInstance documentation, the first parameter should be the unique id of the concrete implementation of the object (the "class") that we want to create, while the third parameter should be the unique id of the "interface" that we want the object to support. Because we are using IID_IDispatch, we're basically telling the COM system that we will be using the newly allocated pointer as an IDispatch* variable, and the CoCreateInstance actually gives us that. But we are then casting it to a DAO::_DBEngine* pointer, which is more than the IDispatch object we asked for!
So, the solution is simply to use the unique id for the DAO::_DBEngine interface:
HRESULT hResult = CoCreateInstance(__uuidof(DAO::DBEngine), nullptr, CLSCTX_ALL, __uuidof(DAO::_DBEngine), reinterpret_cast<LPVOID*>(&daoEngine));
And now it works like a charm again.