Missing registry key for IUIAutomation - c++

I'm trying to use the UI Automation sample on msdn located here;
https://code.msdn.microsoft.com/windowsdesktop/UI-Automation-Document-24a37c82#content
i keep getting the error message: REGDB_E_CLASSNOTREG Class not registered
The Microsoft example uses this line to create an instance of the CUIAutomation8;
CoCreateInstance(__uuidof(CUIAutomation8), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&_automation));
which is the part it seems to be failing at, from digging around this seems to be getting the id of the class and then checking the registry key at that location ({E22AD333-B25F-460C-83D0-0581107395C9} in this case) however my machine doesn't have this key already entered which i think is causing the error, i'm not sure if i'm having to install anything extra that i'm currently missing? As of now all i've done is download the sample and tried compiling it
any help would be much appreciated!
note: I'm using windows 7 with SP1 and VS2015
i've also tried changing CUIAutomation8 to IUIAutomation instead but i'm getting the same issue but as a different registry key

CUIAutomation8 is documented to need Windows 8 or higher for Windows 7, you want to use CUIAutomation

Related

How to reactivate Windows Error Reporting for my application (cpp)? (Windows 10)

TLDR
When one of my applications executes _CrtDbgBreak() it just writes a .dmp file and exits. On any other application _CrtDbgBreak() causes the app.exe has stopped working -dialog where I can chose to break into my debugger (VS 2013).
This is my desired behavior.
Background
A few weeks ago I experimented with Windows Error Reporting to find out if/how the WER Dialog could be suppressed. Apparently I succeeded for my application and unfortunately I haven't found the way how to undo this.
In the meantime I have had to deal with a number of other things so that I no longer remember which steps I exactly took at the time. (Should have taken notes, I know.) Since it works for other applications, I am guessing a setting specific to my app needs to be reset.
I turned to the usual suspects on my machine but so far I haven't found anything:
HKCU\Software\Microsoft\Windows\Windows Error Reporting
HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting
Policy Editor: Computer Configuration\Administrative Templates\Windows Components\Windows Error Reporting
Policy Editor: User Configuration\Administrative Templates\Windows Components\Windows Error Reporting
WER Service is running
I have even removed all occurrences of my executable's name from my entire registry but this hasn't made any difference. What else am I missing?
One possible reason is your app/exe is added to the WER's exclusion list. See 'ExcludedApplications' at https://learn.microsoft.com/en-us/windows/desktop/wer/wer-settings.
https://learn.microsoft.com/en-us/windows/desktop/api/Werapi/nf-werapi-weraddexcludedapplication
Check registry at: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\ExcludedApplications
If your app/exe name is found there, remove it.
Maybe you'd set the process error mode, like so
SetErrorMode(SEM_NOGPFAULTERRORBOX);
(see https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-seterrormode)
[yes - the question is dated, but it's not marked as answered, and this alternative solution may help future readers]

C++: MsiOpenDatabase fails with error 110 0x6e ERROR_OPEN_FAILED only when elevated / admin

I am having a problem with calling the function MsiOpenDatabase (https://msdn.microsoft.com/en-us/library/aa370338(v=vs.85).aspx) from inside a program when I choose to "run as administrator". When I run it under an admin account but without explicitly starting the executable as elevated it all works just fine. This indicates that the path to MSI file etc should be correct.
So, when running elevated the MsiOpenDatabase() I get an error code of 110 (0x6e).
I have tried to call MsiGetLastErrorRecord as explained here (https://msdn.microsoft.com/en-us/library/aa370124(v=vs.85).aspx) but nothing happens when I try to print the code in a message box. It simply doesn't get there.
I do not have Visual studio for debuggning on the target machine, so debugging is a bit of a pain.
Target machine is Windows 7 x64. Application is 32-bit.
But just the pure fact that it works un-elevated but fails when run as an administrator...it feels like there should be some kind of answer to this which can be derived from this fact perhaps?
Thankful for any help!
EDIT:
I finally solved it!
Apparently I had to go to the network share where the MSI file is located (which I am trying to call MsiOpenDatabase on) and right cklick on a file there and choose "run as administrator" because then and only then did I get a UAC dialog box asking for credentials (I mean I was able to open Windows Explorer as admin and navigate to the network share without problem so I never thought that it would be what would give me these peoblems). After haing done that I was able to run my application and it did no longer fail on any MsiOpenDatabase call.
But, why must I do this procedure to get access to run file on a network share since I already had access (execute rights) with the same user but when not elevated? How come Windows needs to ask the same user for credentials if it is already running elevated on the very same account that already has access to the network share? Seems strange to me, but I suppose I am missing some crucial part?
SAMPLE CODE
LPCTSTR szPersist = MSIDBOPEN_READONLY;
MSIHANDLE handleDB;
UINT result = MsiOpenDatabase(strPath, szPersist, &handleDB); // strPath is something like _T("\\server\MSI\Setup.msi");
result variable has value 110 when this error occurrs as explained above and keep the part in the update section in mind. I find it strange, but perhaps someone knows UAC better than me and why I have to provide credentials again by going to a file on the netowrk share and choose to run as admin to get it working (since I have already provided credentials as non-admin with the same account earlier at that very same network share location)?
This is standard UAC behavior since Windows Vista and is not related to MSI at all. Do a google search for "uac network drives".
You should be closing your MSI handles though as I commented above. Use PMSIHANDLE instead of MSIHANDLE.

OleCreate fails with E_CLASSNOTREG when compiled with 64-Bit (C++)

I am trying to display a new Word document inside a Widget, using OLE. This works fine as long as I compile my application under x86 architecture. Now I tried porting my application to x64 and it stopped working. The call to OleCreate() fails with REGDB_E_CLASSNOTREG.
CLSID clsID;
IUnknown* pIUnknown;
HRESULT res = CLSIDFromProgID(L"Word.Document.8", &clsID);
if (SUCCEEDED(res)) {
res = OleCreate(clsID, IID_IUnknown, OLERENDER_DRAW, NULL, NULL, storage, reinterpret_cast<void**>(&pIUnknown));
}
After some research I came across some solutions, but none of them were applicable.
I can't set my compiler to x86 when I'm trying to port my application to x64 so following Post hasn't solved my problem.
I tried calling regsvr32.exe withC:\Windows\System32\ole32.dll but it didn't change the result.
I tried installing the hotpatch, which was shipped by microsoft to fix the same problem with OleCreateFromFile(). Sadly it doesn't fix the problem for OleCreate() - hotfix
The only solution, which worked so far was to copy the content of HKLM\SOFTWARE\SysWow64\Classes\CLSID\<CLSID of Word Document> into HKLM\SOFTWARE\Classes\CLSID\<CLSID of Word Document> but this is more of a hack than a fix, because I would have to modify the registry of every machine on which I want to run my application. Since this task requires administrator privileges, I can't do this from inside my application.
I need a solution which works and doesn't force me to manually alter registry entries.
I'm running my application on a Windows 7 Professional SP1 64-Bit machine with a 32-Bit Office 2010.
After some more testing I found the solution to the problem, which was to use Word.Document instead of Word.Document.8 as progID.
I have don't know why this seems to be a problem with 64-Bit compilation. The thing, I noticed though was that CLSIDFromProgID() now resolves to a different CLSID.

CreateInstance Returns "The specified module could not be found."

I've been trying to get a program that worked on Windows 2000 to work on Windows 2003. Everything I've had to do so far to get the program to work on Windows 2003 has had to do with incorrect configuration. Right now, this piece of code:
chr = pAdapterEnvPtr.CreateInstance(__uuidof(PFADAPTERMNGLib::PFAdapterEnv));
is returning:
0x8007007E
or in other words:
The specified module could not be found.
I have two other programs and another .dll and I can successfully create instances of those classes. But this seems to fail.
I have used Procmon to try to figure out what the program can't find, but Procmon did not display anything that could indicate that the program could not find something.
In OleView, if I try to create an instance of the class, I see the following image:
If you look on the left side of the image, trying to create an instance of PFComgMng gives me the same error. (PFAdapterEnv and PFCompMng use the same process, PFAdapterMng.exe.) However, PFMQMonitor, PFSend, and PFTrace all work correctly. (Which use PFMQListen.exe, PFSend.dll, and PFTraceService.exe.)
Another thing that I wanted to note is that the following piece of code:
hr = pPFCompMng.CreateInstance(__uuidof(PFADAPTERMNGLib::PFCompMng));
works perfectly fine when it gets called earlier from PFAdapterMng.exe. So it seems like PFAdapterMng.exe can successfully find the module and create the instance, but any other processes that try to create either of the instances of the classes within PFAdapterMng.exe can't find the module, resulting in this error.
Since Procmon isn't helping with this specific case, does anyone know what I could do to figure out what's keeping other processes from finding the module?
UPDATE:
I can't run Dependency Walker with profiling because PFAdapterMng.exe and PFTraceService.exe must be run as services. I tried to run Dependency Walker while profiling OleView and tried to create instances of PFAdapterEnv and PFCompMng to try to find out why I was getting the Module not found message box. Unfortunately, Dependency Walker didn't show that anything was missing.
UPDATE2:
Maybe I missed something in the Procmon log, so I created a new log by capturing events right before I stepped over the call to CreateInstance and right after the call. Maybe someone else could take a look and tell me if i missed it? I simply can't find any indications that PFMQListen.exe could not find something..
Here's a link to a zipped folder with a Procmon file, a .csv file, and a .xml file.
http://www.mediafire.com/?07jq8zj7emmpsvd
UPDATE3:
So, I managed to get Dependency Walker running under Profile mode to create an instance of PFAdapterEnv. Dependency Walker did not find any missing .dll's.
So, Procmon doesn't show anything, and neither does Dependency Walker. I was stepping through the code at the assembly level with ollydbg, and I noticed that the error was created in the function NdrClientCall2. I don't know if this means anything.
Any ideas as to what else I can try? Do people need more information to help me solve this problem? If so, please ask.
UPDATE4:
I tried using /RegServer to register the applications, and it worked. I tried using /RegServer previously, where I just unregistered everything using /UnregServer. This time, I also deleted the component from Component Services which I needed to have because I wanted to run PFAdapterMng under another identity.
So, it seems like everything works when running on /RegServer and double-clicking the applications. However, I would like everything to run under a different configuration.
How do I configure everything to get the applications to work as follows:
PFAdapterMng.exe - Register as /Service and run under another identity through services.msc
PFTraceServer.exe - Register as /Service and run under another identity through services.msc
PFMQListen.exe - Register as /RegServer which will be started by PFAdapterMng
PFMQSend.dll - Registered with Regsvr32 and loaded by PFAdapterMng
Thanks,
Krzys
My guess is that it is related to the search path of some DLL dependencies of the executable.
You can try the "Dependency Walker" on every module to see if all DLL are available: http://www.dependencywalker.com/
And update the search PATH if needed.

Error 800706B5 when calling IWebBrowser2->get_Document

On Vista using IE8, I have an instance of IWebBrowser2, which I am using to obtain the current HTML document:
IWebBrowser2* browser;
CComPtr<IDispatch> disp;
HRESULT hr = browser->get_Document(&disp);
When this is executed by an Administrator, the call succeeds. However, when called by a regular user, the call returns an error code of "800706B5" ("The interface is unknown") despite the page being on a "Trusted Site" and "Protected Mode" being off.
This same code worked without problems on IE7 on Vista, and with IE8 on XP.
Does anyone know why this error might be occurring, and what I can do to resolve the issue? Running as administrator is less than ideal, and Jon Skeet is stumped by this one too :)
Update: the question seems to revolve around UAC: turning off UAC completely allows things to work for a regular user (though it's distinctly unsafe)
The error is occurring because on Vista, IE 8 runs in "low integrity" mode, whereas my test code, running as a normal user, runs at "medium integrity". The security model is designed so that code can send instructions to lower integrity components, but data cannot be read from "lower" to "higher" components by default.
More information is available in this document about How the Integrity Mechanism Is Implemented in Windows Vista
Was IE8 installed by the Administrator "For this user only"? I don't know why or if that would give this error, just a hunch.