When I enable Page Heap for my process under test, it triggers an Access Violation which indicates to me some type of heap corruption has occurred when SHGetFileInfo is called.
The top of the call stack shows msvcr90!wcspbrk and walking down it shows COM-related items in ole32 until shell32 is reached where we call SHGetFileInfo.
From what I've found online, a common problem for weirdness using shell32 is not calling CoInitialize/CoInitializeEx first, but at this point CoInitializeEx() has already been called, and calling it immediately prior to the below code simply returns S_FALSE.
The below code is in our DLL which is PInvoked from .NET (the code is used to retrieve the icon used for a particular file):
SHFILEINFOW shfi;
memset(&shfi,0,sizeof(shfi));
SHGetFileInfoW(A2W("C:\\logfile.txt"),
FILE_ATTRIBUTE_NORMAL,
&shfi,
sizeof(shfi),
SHGFI_USEFILEATTRIBUTES
| SHGFI_ICON
);
(where logfile.txt is random text file on my root drive)
I've hard-coded the first parameter to a file on my machine for simplicity.
I'm using a 64-bit Windows OS, but the code is run in a 32-bit context. I get the same result if I use the narrow version of SHGetFileInfo.
If I disable Page Heap for my process, there is no problem.
When I don't use the flag SHGFI_ICON, the issue doesn't occur.
EDIT: #HansPassant requested I add a reproduceable sample, here's a link to a Visual Studio 2010 Win32 Console Application demonstrating the issue: sample
Related
I'm using IConverterSession to create mail items from mhtm files. This works fine with Outlook Versions < 2016. With Office 2016, IConverterSession cannot be created.
If you are running C2R (click-to-run) version of Outlook 2016, all registry keys are virtualized - see the registry keys below (%s needs to be replaced by the Outlook version, e.g. 16.0). Since the COM system does not look there, you will need to implement your own version of CoCreateInstance that reads the default value from the key to figure out the dll file name, then calls LoadLibrary / GetProcAddress("DllGetClassObject") / DllGetClassObject(..., IID_IClassFactory, ...) / IClassFactory.CreateInstance.
SOFTWARE\Microsoft\Office\%s.0\ClickToRun\REGISTRY\MACHINE\Software\Classes\CLSID\%s\InprocServer32
SOFTWARE\Microsoft\Office\%s.0\ClickToRun\REGISTRY\MACHINE\Software\Classes\Wow6432Node\CLSID\%s\InprocServer32
SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Classes\CLSID\%s\InprocServer32
SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Classes\Wow6432Node\CLSID\%s\InprocServer32
Instead of implementing CoCreateInstance() on your own, you have to enable registry redirection to enable C2R (click-to-run) virtualization of Outlook which is using detours to redirect the call to RegOpenKey(). After enabling that redirection just use the normal CoCreateInstance().
The reason why implementing CoCreateInstance() on your own doesn't work is, that the converter will also call CoCreateInstance() internally and that will fail like your original call because it doesn't find the CLSID in the normal hive of the registry.
I found out the code myself by looking on the jitv.dll exports. The parameters may be wrong, but as a first start it was working without a crash. To find out the parameters I have to debug an Office application and look at the disassembly (or any volunteers?).
Here the experimental code that worked for me :
HMODULE jitv = ::LoadLibrary(TEXT("jitv.dll"));
if (jitv) {
FARPROC efv = ::GetProcAddress(jitv, "EnableFullVirtualization");
if(efv)
efv();
// call CoCreateInstance(guid::CLSID_IConverterSession)
// and do your work
}
if (jitv)
FreeLibrary(jitv);
There are some other exports in the jitv.dll whose names are mostly selfexplanary:
"APIExportForDetours"
"DisableVirtualizationOnThread"
"EnableVirtualizationOnThread"
"IsCurrentThreadVirtualized"
Thanks to this posting by nickekallen which mentioned that dll and brought me to that idea.
When calling a 32 bit COM component method registered in sysWOW64 fails with an error message:
"type mismatch in method OleVarToLsVal, Unknown found, Unknown
expected"
Its win7 64 bit, but the Notes client is installed by default as a 32 bit application. The code looks like:
dim c as Variant
dim n as Variant
set c = createobject("MSWC.counters")
n = c.Get("xx")
When debugging the call, the object is set and testable with "isObject(c)", (although you can't inspect each method/property in detail in LotusScript debug).
The method is supposed to return a primitive long. I've tried setting n as long, clng-ing the values, cstr-ing the values, the parameter, strconv the parameter, using a variable for the parameter, all to no avail.
The exact same code run by WScript VBS host (in syswow64) runs the code as expected.
So, does anybody know:
If Notes 9 COM value marshalling is working for any components?
Is Notes 9 COM set to recognize the 'wow64' alternate 32 bit registry
Are there some COM related marshalling settings somewhere in the registry I can check (if so what/where are they)?
Is there some setting to tell Notes to use 32 bit components (like IIS 32bit compatibility option)
Is there anything I need to do or could do in the main OS to 'redirect or configure' COM
Or is Notes just broken again and nobody cares?
Any help appreciated - Thanks.
The easiest and probably most productive way to solve this would be to open a PMR with IBM. They should be able to answer this quite quickly.
Well, 7 years on (and seriously obsolete!) just an update for anybody looking for an answer... There are a couple of Notes settings needed and not all COM/Active-X componenets or data types are supported by LotusScript, so even if Notes is setup correctly, you still may not be able to acces/use any specific component or some methods in the component.
The user must be allowed to run unrestricted agents/code in the 'Sign or run unrestricted methods and operations:' in the security section of the server(s) document.
The Notes client execution control list ('ECL') must allow access to 'External programs' either by default or to the code-signer. An ECL warning box will ask the user to continue if the external access has not been granted.
If you try to execute an unsupported method or unsupported data type, then further errors will be issued either by LotusScript or COM/Active-X error reporting. The Notes developer help file for 'CreateObject' gives a bit more detail about unsupported data types:
LotusScript does not support identifying arguments for OLE methods or properties by name rather than by the order in which they appear, nor does LotusScript support using an OLE name by itself (without an explicit property) to identify a default property.
Results are unspecified for arguments to OLE methods and properties of type boolean, byte, and date that are passed by reference. LotusScript does not support these data types.
Relying on the 'default property' to access a default method is a common mistake and requires you to pay extra attention to the component details. It is easy to assume the component is not working, but in fact you're just not using it properly.
One way to test this is to try to open a common object available on all Windows machines (maybe others?) maybe 'FileSystemObject' (FSO) or VbScript 'regExp' component. If these work, you can build on that. Getting the 32/64bit registration correct for your client install is another element to test/get right.
For my issues, I suspect that I was using unsupported methods or data types and having used COM/Active-X in Notes occasionally, its all worked ok in general.
I am the IT department of a Non-Profit organization. I have a question today which might be too specialized for this forum and I hope I do not waste my time writing it up. We are using Blackbaud's 'Raiser's Edge' (RE) Software (written in VB6 and VB.net as far as I know) to keep track of our membership and donations. We have an MS Access application (have been using it since before we got RE) to process donations and for now I want to keep it and only do minor changes to adapt it to the new software.
The MS Access program is now doing a few calls to the RE API which work great. To login and establish a connection I have to create a new 'REAPI' object and use it for other API calls. That REAPI object has a method called: SignOutOnTerminate which needs to be set to TRUE when creating that object. It is supposed to kill all connections to RE once my application closes. There is no regular .close method.
Once I create the object I can do work as many times as I want and there is no problem at all as far as I can see.
However when trying to close the application or set the object to nothing (Set REAPI = Nothing) Access crashes immediately (It fades out and I get the message that Windows is looking for a solution to the problem. Then Access closes and restarts itself.)
It is more annoying and unprofessional then hindering production but I want to fix it.
The App was developed on Windows 7 64-bit with Access 2010 32-bit. It was tested on Windows XP with Office 2003 or 2007 machines (32-bit) and behaves the same way.
I have posted this problem already on 2 Blackbaud forums and tried a suggested a work around which did not work (kill the process with a shell command and then set the object to nothing). Hopefully I will get more answers soon.
I tried to just exclude the SignOutOnTerminate when creating the object. But got the same behavior.
I looked in the Event Manager --> Application Log and found the Crash. It reported that access crashed because of this dll: C:\Windows\System32\MSVBVM60.dll (It is actually located in the SysWos64 folder as it is a 32-bit application).
Looking up this error I found some suggestions to replace it with an earlier version of the dll, the one which ships with XP. I found a file and tried the suggestion but it still crashed. The error log reported the older version number as faulting so I registered it correctly.
I also created a case with Blackbaud but the rep did not know what the problem is and did not have MS Access installed. He is trying to get his support team to install it for him so he can test and investigate this error.
The last suspicion I have is that the API is causing the error and my code is fine.
But before I make this assumption and until I get my answer from Blackbaud I want to do a final check, but I have run out of ideas for further trouble shooting and resorted to pose this problem in this forum.
Any Ideas?
I realise that this is an old thread and if you have solved this by now then that is great. However this is a known issue with The Raiser's Edge API. If you use .NET with RE's API (which is COM based) there is definitely some resource that is not cleaned up properly. At one point I suspected that it was something to with making use of RE's graphical interface i.e. by calling the regular login method to log you into RE. However even if you log in to RE using the "as a server" method supplying the user name and password it still crashes on exiting the application.
We have an installer that sets up credentials in RE. The installer is in .NET and accesses the RE API. We now show a message just before the end of the application telling users to ignore the impending crash... Not a great solution by any means.
EDIT: See end of post for more information.
I am trying to to get plugins created via the Firebreath framework (1.7.0) to load. I am on Windows 8 in Desktop Mode using Internet Explorer 10. I've reproduced this with the built-in test FBTtestPlugin that comes with Firebreath. The failure is silent in that the object element is created, but fails to have any properties specified by the plugin. How does one go about debugging this? The Microsoft Internet Explorer Compatibility Tool reports that the plugin is failing to load.
(The FBTtestPlugin loads three plugins, hence the three errors.)
I've got other (non-FB) plugins working on the same settings (e.g. the example here: http://msdn.microsoft.com/en-us/library/dd565667(v=vs.85).aspx works fine as do all the examples from this site http://ie.microsoft.com/testdrive/browser/activexfiltering/Default.html ).
I've tried a huge combination of security settings, but here's the most relaxed set I have so far follows:
Tools / Safety / ActiveX Filtering: is unchecked
Internet Options / Security / Internet: "Enable Protected Mode" is unchecked
Internet Options / Security / Internet: is at Custom Level. Under ActiveX everything is "enabled" except restrictive properties such as "Allow ActiveX Filtering"
All sorts of security warnings are visible based on these settings.
Note: I don't intend to keep these settings. I just want to get the plugin working, then work backwards re-enabling security settings.
UPDATE
I figured this out partly and can now run the FB test FBTestPlugin. To make debugging easier for IE, I defined the registry key HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\TabProcGrowth as 0 to limit the browser to use one process. Unfortunately, with IE10 both iexplore.exe in Program Files and Program Files (x86) direct to the 64-bit version of IE. This prevents 32-bit plugins from running (see http://support.microsoft.com/kb/2716529 ), and the symptom is silent failure.
However, my plugin still fails to load in IE and the retitled question above is otherwise still open. The problem is still silent load failure. However, I think it may have something to do with plugin configuration. The CLSID listed in the Compatibility Test Tool (like the example shown above) is listed as all 0's instead of a valid GUID. Moreover the registry looks funky: The key HKCR\Company.Name exists as does HKCR\Company.Name.1, but both are empty (instead of having a CLSID child as in normally working plugins). The expected GUID does exist, but under a bogus name "applications.'". I am now digging into the code that gets called when regsvr32 is run.
Thanks all!
I am providing this answer in the hopes that someone can use the result.
IE was not loading the plugin for two reasons.
1) The TabProcGrowth registry key and the 32/64 bit issue with IE 10. ( http://support.microsoft.com/kb/2716529 )
Don't define this key.
2) My plugin description used an apostrophe (e.g. "Gluttco's Plugin") and this messed up the registration of the component.
DETAILS ON 2):
I traced through the DllRegisterServer code and found that the phoney registry entries are due to the fact that my plugin description contained an apostrophe. E.g. "Joe's plugin". The generator (fbgen.py/cmake), generated a malformed FBControls.rgs file (it't didn't escape the quotes and thus contained a string literal such as (s 'Joe's cool plugin'). The DllRegisterServer code (called from regsvr32) used the contents of this file (embedded?) when (deep in atlbase.h). Oddly, the parser did not detect the error (or somehow erroneously recovered). From Process Monitor I could see a bunch of bogus keys being added, before it started adding good registry keys again.
For now Firebreath plugin descriptions should not contain apostrophes (probably other characters are illegal too). It might be sensible to make fbgen.py check for these characters and possibly escape, reject, or replace them.
Searching found this: http://msdn.microsoft.com/en-us/library/dd565667(v=vs.85).aspx
Do you have any group policies in place that could affect it? I don't think this is related directly to FireBreath, rather to the activex configuration...
I also found http://social.technet.microsoft.com/Forums/windows/en-US/90c3202c-448b-42b7-acf7-dab8dba7b000/one-or-more-activex-controls-could-not-be-displayed-because-either which has a few things you could try.
I've created a COM object using NATIVE c++ - both COM object and it's native client works perfectly.
the next step was to implement the COM object as a out of process COM server( hosted by the dllhost process.
I followed the standard registry-change procedure(http://support.microsoft.com/kb/198891) and both client and COM server started to work properly under the dllhost.exe process.
However, I can see that sometime the host server crashes and the dllhost.exe pop up a message stating error 217 - nothing else is detailed.
Any idea how can I debug the COM infrastructure? any preferred tools I can use?
many thanks,
Ofer
However, I can see that sometime the
host server crashes and the
dllhost.exe pop up a message stating
error 217 - nothing else is detailed.
I'm curious as to what happens here, in more detail -- does the dllhost process really crash (with a structured exception) or does it show a message box and then die?
You should be able to attach any debugger (Visual Studio or WinDBG) either when the problem happens or at any time in advance.
Break into the debugger and check the callstack when the problem occurs.
If it's due to a race condition of some kind, it may not surface when the debugger is attached, so I'd start with attaching when the message box is shown, and see what information can be gathered from there.
Presumably your code is in the callstack; if not, you may be short on luck.
Note that it always helps to have Microsoft symbols available, it's easiest via the public symbol server as described at the bottom of this page:
http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx