How to handle managed exception in unmanaged code - c++

I have C++ project which is COM based, in which am accessing the C# assembly. I want to write the code to handle the exception in com project which are thrown by C# assembly.
I tried by placing the try and catch blocks, but exceptions are not been thrown instead the HRESULT value is less than zero. I need the exact message string to display which is thrown by C# API.
Please provide the guidelines for this.

You have two sources of info available. First off, the HRESULT that is returned is not arbitrary, every managed exception has a distinctive HRESULT that helps you identify the kind of Exception object that was thrown.
Next, the CLR implements the IErrorInfo interface. You can QI on the interface pointer you used to call the managed method to get the IErrorInfo interface pointer. IErrorInfo::GetDescription() returns the Exception.Message property value.
That's where it ends, no way to get the holy stack trace.

Related

SEHException while in paint() - .NET handling is ruining call stack

I have error handling code that is designed to catch unnhandled exceptions, and then create a dump.
Now, i've encountered a few situations where this doesn't work well in the transition between Native and managed code.
For example if in a Paint() event I call some native code, and that native code throws an exception.
The message loop dispatcher will catch the native exception, and then rethrow a .NET SEHException.
Same thing happens sometimes with DLLS that host COM objects.
The problem with this is that because of the stack-roll back and the way it catches and creates an SEHException from the native exception, the actual Native call stack is destroyed.
Can i get the native call stack somehow, using the SEHException ? (note that the call stack in the SEHException is the CLR call stack).
Or can i set the application so it will save the call stack somehow ?
Try !dumpheap -type SEHException . Use the address of SEHException to print !pe address of exception . You will get the callstack
What happens is that .Net called Paint() when it needed to paint a window.
Apparently .Net made this very safe and added extra precautions and error handling.
Now my Paint() event called a C++/CLI wrapper dll that called a native C++ dll. The native C++ exception raised an Access Violation exception.
Now the .Net caught that exception, and wrapped it up as a managed SEHException object, and I've lost all the call stack from the actual error point.
Solution:
We need to catch the exception before the .Net exception handling.
The usual exception handling flow can be found on the net, but this sites gives a good example of the actual flow: Exception handlers
It seems that the .Net catches the exceptions and wraps them before the SetUnhandledExceptionFilter handler is called.
So, I've added a first chance exception handler with AddVectoredExceptionHandler and checked for fatal exceptions by checking the errorcode.
//SEH exceptions have code 0xC0000xxxx
#define SEH_TYPE (DWORD)0xC0000000L
//mask the last byte
#define SEH_MASK (DWORD)0xFF000000L
LONG WINAPI CheckForSEHException( struct _EXCEPTION_POINTERS *lpTopLevelExceptionFilter)
{
if ((lpTopLevelExceptionFilter->ExceptionRecord->ExceptionCode & SEH_MASK) == SEH_TYPE) //mask and check the last bits if it's an SEH exception
{
//handle exception here (create a dump or something)
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
}
The exception codes can be found in WinBase.h, you can follow the definitions to the actual error codes. (ie. look for EXCEPTION_ACCESS_VIOLATION)

CoGetClassObject gives many First-chance exceptions in ATL project. Should I worry?

I have written a COM object that in turn uses a thrid party ActiveX control. In my FinalConstruct() for my COM object, I instantiate the ActiveX control with the follow code:
HRESULT hRes;
LPCLASSFACTORY2 pClassFactory;
hRes = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
bool bTest = SUCCEEDED(hRes);
if (!bTest)
return E_FAIL;
if (SUCCEEDED(CoGetClassObject(__uuidof(SerialPortSniffer), CLSCTX_INPROC_SERVER, NULL,
IID_IClassFactory2, (LPVOID *)(&pClassFactory))))
{ ... more set up code
When I step over the line if (SUCCEEDED(CoGetClassObject(__uuidof(SerialPortSniffer), ...,
I get 20+ lines in the Output window stating:
First-chance exception at 0x0523f82e
in SillyComDriver.exe: 0xC0000005:
Access violation writing location
0x00000000.
I also get the lines:
First-chance exception at 0x051e3f3d
in SillyComDriver.exe: 0xC0000096:
Privileged instruction. First-chance
exception at 0x100ab9e6 in
SillyComDriver.exe: 0xC000001D:
Illegal Instruction.
Notice these are first-chance exceptions. The program runs as expected I can access the third party methods/properties. Still, I'm left wondering why they are occurring. Perhaps my way of instantiating the ActiveX control (for which I want use of it's methods/properties and not it's GUI stuff) is incorrect? Besides the code I'm showing, I also put the line
#import "spsax.dll" no_namespace
in the stdafx.h
That's all the code necessary for my simple demo project. I noticed this problem because I had (inadvertently) set the "break on exceptions" options in my "real" project and it was breaking on this line. Once I removed it, it also works.
If you're read this far thank you, and perhaps I can ask one other minor question. In my demo project, if I right click on SerialPortSniffer and "go to definition", it takes me to the file C:....\AppData\Local\Temp\spsax.tlh. Can someone explain that? Finally, in my "real" project, right clicking on SerialPortSniffer and going to difinition leads to "The symbol 'SerialPortSniffer' is not defined". It doesn't seem to affect the program though. Is there some setting I've messed up?
By the way, all my code is written w/ VS2008.
Thanks,
Dave
These are definitely the worst kind of hardware exceptions that you'd ever could encounter in a Windows program. There is absolutely no reason that something as simple as a serial port sniffer should ever throw exceptions like that, let alone catch them and handle them.
Still, it does and there's nothing you can do about it. You can only hope and pray that this doesn't byte you in the ass some day. Personally, that component would quickly end up on my thrash heap.
The #import statement auto-generates code from the COM type library. It generates a .tlh file with declarations and a .tli file with COM method wrappers. The .tlh file contains smart pointers (xxxxPtr) to make instantiating the COM object and calling its methods easy. That's why "Goto Definition" takes you to that file.
It's usually nothing to worry about.
When an exception is thrown, the debugger is notified and depending on the debugger configuration, it may stop the application or let the application resume normally. This is a "first-chance" exception. If the application resumes, then it may catch the exception, and do whatever is necessary in the exceptional case.
If the application does not handle the exception, it becomes a "second-chance" exception and the debugger is notified again. The debugger is usually configured to stop the application at this point to let you see what went wrong.
So if you get a first-chance exception and not receive a second-chance exception later, it's usually means that nothing is wrong, and the application is handling exceptions in a "graceful" matter.
(Also see Link)

Get pContext in Try/Catch handler?

When an exception happens, as you know, it passes pContext to the SEH. Is there anyways to access the pContext in a Try/Catch? I guess I could have the exception class grab it when being initiated but that would only work for that class and not for every exception.
Hard to know what you're looking for...
THE Guide for SEH: http://www.microsoft.com/msj/0197/Exception/Exception.aspx
Have a look to that as well:
http://www.programmingunlimited.net/siteexec/content.cgi?page=mingw-seh
http://msdn.microsoft.com/en-us/library/swezty51(VS.80).aspx
Note: take care depending on the version of your compiler C++ exceptions and SEH exceptions might not be handle all together: http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/

Error instantiating COM object

currently I'm struggling trying to use a COM dll on a simple system that I've made. Everything compiles successfully, but in runtime the CoCreateInstace is returning S_OK, but somehow my object pointer is returning NULL.
This interface pointer is created on my class header. The weirdest thing is that instantiating this same pointer type on the method stack results in a correct object, but subsequent calls to __hook turn on an access violation when trying to create a BASE com class.
Some other aspects that might be useful:
Tried to run the program with CoInitalizeEx started as COINIT_MULTITHREADED and COINIT_APARTMENTTHREADED
The project is a dll which uses the COM dll in it
I've tried the same method without starting a new thread and the error persists
I've made a test program ( no threads, executable ) and the object is created normally, and hooked correctly. So my guess it is something related to it being a DLL itself or threaded related.
PS: As bonus question, why google doesn't return anything favorable related to COM? :)
It sounds like a bug in the COM object's implementation of IUnknown::QueryInterface - not setting the output pointer but returning S_OK.
CoCreateInstance for an in-proc server is basically:
Load the DLL into memory
Call DllGetClassObject to get the class factory
Call IClassFactory::CreateInstance from the class factory which allocates a new object
Call IUnknown::QueryInterface on the new object to get the desired interface.
Returning NULL but S_OK at any step should result in a crash, except for the QI call at the end.
Found the problem: The module attribute was defined on a static library, and that made the COM object go crazy; Moving it to the DLL source resolved the problem.

How do you catch a managed exception (from a delegate) in unmanaged C++?

I have unmanaged C++ calling a managed delegate via the function pointer provided by Marshal::GetFunctionPointerForDelegate. This delegate has the potential to throw an exception. I need to be able to properly handle this exception in my unmanaged C++ to ensure things like pointer cleanup, and potentially rethrow the exception up into more managed code. The call stack is similar to this:
Managed Code -> Unmanaged C++ -> callback to Managed Code via delegate (exception can be thrown here).
Anyone have pointers for properly handling this situation so that the resources in unmanaged code can be cleaned up and a usable exception can be thrown out to the managed code which initiated the whole call stack?
Catching from managed code with
try
{
throw gcnew InvalidOperationException();
}
catch(InvalidOperationException^ e)
{
// Process e
throw;
}
And an
[assembly:RuntimeCompatibility(WrapNonExceptionThrows = true)];
on your assembly catches managed and unmanaged exceptions
Don't even remotely try to make the "unmanaged" code aware of the fact that it will have to deal with .NET.
Return a non-zero value from your callback to signal the presence of an error. Provide a (thread local) global string object describing the error so that you can retrieve a helpful error message for the user.
This may involve wrapping your delegate into another function under the scenes, which will catch all the exceptions and return the error code.
One approach would be to use SEH, and do the cleanup in the exception filter before continuing the exception propagation. But I'm not sure that is overly legal since you would be doing a lot of work in the filter. You also wouldn't know anything about the managed exception being propagated.
An alternative is to wrap the managed delegate with your own managed function that catches the exception and in turn throws an unmanaged exception ... which you can then catch in your unmanaged code.
When the unmanaged code has done its cleanup use another helper managed function to re-throw the original managed exception
Managed code represents exceptions as hardware exceptions, unlike C++. You could use SEH. Remember that you always get the chance to run the exception filter.
http://msdn.microsoft.com/en-us/library/ms680657(v=VS.85).aspx
I was told...{the vector can't show if variables a&b weren't declared in the scope process. After a bit of digging figured out that the loop hole was as follows--- weibull_distribution> unmanaged_code