The Windows API CopyFile function is rather straightforward:
BOOL CopyFileW(
[in] LPCWSTR lpExistingFileName,
[in] LPCWSTR lpNewFileName,
[in] BOOL bFailIfExists
);
...
If the function fails, the return value is zero. To get extended error
information, call GetLastError.
However, I found this gem in our C++ source code, dating back to Oct / 2006:
try { //Exception, if the file already exists and is write protected
bCopyOK = CopyFile(csSourceFile, csDestinationFile, bFailIfExists);
} catch (...) {
bCopyOK = FALSE;
}
I even found the old ticket title (of course without details): "function 'CopyFile' throws Exception if Destination is write protected, catch Exception" :-)
Even today we still compile with /EHa, so this would have caught any SEH exceptions raised.
Now, at this point in time we would've been using Visual Studio 6 on Windows XP, and that one had all kinds of quirks, but still: I have a hard time imagining this function ever raising an exception (apart from invalid/null parameters and such).
Does or DID Win32 CopyFile(W) ever raise a (SEH) exception?
NO.
at first not exist SEH exceptions at all. SEH this is type of exception handler but not type of exception. another type of handlers (not exceptions) is VEH.
exception can be raised or via invoke RaiseException /RtlRaiseException / ZwRaiseException or by CPU. of course CPU exception alwas can be raised (in case lpExistingFileName or lpNewFileName for instanse point to invalid memory ) but CopyFileW never call RaiseException - by fact and by documentation.
//Exception, if the file already exists and is write protected
so in what problem ? create write protected file lpNewFileName and call CopyFile and test result. will be exception or error code returned
// Self answer, with historical perspective.
It is not documented to throw exceptions, as is apparent from the current docs linked above.
Both the other answer and also, e.g. Do DeleteFile() Or CopyFile() throw exceptions? quite definitely assert that there should be no exception being raised.
However, as is mentioned in comments:
Very few API calls are documented to raise SEH exceptions, but that
doesn't mean that they won't, or prevent SEH exceptions raised in
foreign code from passing through.
and in the linked question:
comment: ... Some odds that getting rid of the installed anti-malware product can rescue it, ymmv. ...
A: It was ... corporate info safety system, anti-malware like product.
It is very well possible that the original developer could actually reproduce this behavior on his machine, and swallowing the error "fixed" it well enough back then.
Things have improved since then. Given that no reproduction is possible in current code, and given that this only works with /EHa anyways, the try-catch is a candidate for cleanup.
Related
I'm curious how Windows handles exceptions. More exactly, how Windows find the catch block of a try / catch. I saw that the compiler makes a separate function in assembly for catch block. Since the catch block was represented by another function in assembly, I couldn't find any correlation between the instruction that was generating the exception and the RUNTIME_FUNCTION entries from .pdata section.
I tried to put a breakpoint on RaiseException, RtlRaiseException and RtlVirtualUnwind but all I could find was the address after the RaiseException call. Tried to debug a divide by 0 exception, but it looks like the debugger has some additional exception handlers and the message in the catch block was not printed.
Any additional information about Stack Unwinding on Windows 64bit are welcome :D.
The exceptions are handled by exception handler routines.
When you add a try/catch block to your C++ code you will see that the compiler added __CxxFrameHandler3 to your import table (providing that the MSVCRT is not statically linked). So this is your exception handler that will be called when an exception occurs in the try block.
Another one __C_specific_handler is imported when you add __try/__except block to your C or C++ code.
There are a few others but these two are used in the C/C++ code.
To answer your question, the best way is to hook (replace the import table pointer with a pointer to your local routine) one of these functions and see how your "handler" will be called when an exception is thrown.
With the goal of finding C++ catch you can set Vectored Exception Handler and set a breakpoint in it. VEH goes before frame-based handlers, so it it not too late:
LONG NTAPI vh(EXCEPTION_POINTERS* ExceptionInfo)
{
return EXCEPTION_CONTINUE_SEARCH;
}
AddVectoredExceptionHandler(TRUE, vh);
Alternatively, if you want to set breakpoint closer to catch block, have __try...__except deeper in call stack than target catch block, in __except expression return EXCEPTION_CONTINUE_SEARCH and have your breakpoint there.
I'm working on Ethernet code on an STM32F429 ARM Cortex M4 device and running into a situation where I'm getting an MemManage exception where the cause is proving very difficult to track down. From what I understand, the MemManage exception is caused by some violation of the MPU such as trying to execute code in the protected register space at 0xE0000000 and above. Cortex M4 documentation I've read indicates the reason for the exception should be captured in the MMSFR register bits and that the address of the error may be captured in the MMFAR register in certain circumstances.
What frustrating me is that MemManage exception is being generated with all bits in the MMSFR register zero. I'm executing a breakpoint instruction just as the exception handler is entered so I'm pretty sure the MMSFR is not being accidentally cleared. Furthermore, no where in my code am I even using the MPU and it should be in its default state on power-up. Finally, I can purposely create a MemManage exception elsewhere in my code and the MMSFR bits correctly identify the issue I triggered. Unwinding the stack from the exception, the only thing unusual thing about the PC is that it's in the middle of code that is called early on to initialize the RTOS, but should not be executing later when the exception occurs. I'm trying to determine how the PC got to the value it did, but it's proving difficult to isolate.
Does someone have some ideas as to why the the MemManage exception might occur without the MMSFR bits being set? Or, suggestions for techniques to better understand the circumstances that occur in my code just before the exception occurs.
My instinct (not necessarily accurate!) is that something's not right here. There's no reason that the MemManage exception should not accurately log the reason for its invocation, and your mention of the PC having been somewhere it shouldn't have been suggests that whatever's wrong went wrong well before the exception entry. On that basis I think you'll learn more by identifying where the exception takes place than by trying to deduce the cause from the exception type.
I'd start by checking the value in LR at the point you've identified that the exception takes place. This won't necessarily tell you where the PC corruption took place, but it'll tell you where the last BL was issued prior to the problem, so it might help put bounds on where the problem might be. You might also find it helpful to check the exception state bits in the PSR ([8-0]) to confirm the type of the fault. (MemManage is 0x004.)
I finally tracked down the issue. It was code executing a callback function within a structure, but the structure pointer was a null pointer. The offset of the callback function within the structure corresponded to the offset of the MemManager exception handler in the vector table from address zero. Thus, the MemManager handler was not being called via an exception, but rather a simple function call. This was why the stack looked confusing to me -- I was expecting to see a an exception stack frame rather than a simple function call stack frame.
The clue to me was the exception state bits in the PSR ([8-0]) being all zeros (thanks to the suggestion from cooperised) which indicates my MemManager exception was not actually being called as an exception. I then backtracked from there to understand what code was responsible for calling the handler as a function call. My flawed assumption was that the only way the MemManager handler could be reached was via an exception -- with the PSR value and non-exception stack frame being the major clues that I was ignoring.
Double-check that the exception you're getting is actually MemManage and not something else (e.g. if you're using a shared handler for several exception types). Another possibility is that you're getting an imprecise fault and the information about the original fault has been discarded. From FreeRTOS debugging guide:
ARM Cortex-M faults can be precise or imprecise. If the IMPRECISERR
bit (bit 2) is set in the BusFault Status Register (or BFSR, which
is byte accessible at address 0xE000ED29) is set then the fault is
imprecise.
...
In the above example, turning off write buffering by setting the
DISDEFWBUF bit (bit 1) in the Auxiliary Control Register (or
ACTLR) will result in the imprecise fault becoming a precise fault,
which makes the fault easier to debug, albeit at the cost of slower
program execution.
I have a Windows Store application (for Windows 8) written in C++/CX and I have wrapped a chunk of my code in a try/catch block.
The catch block is working and catches an exception, but so far I only seem to be able to print out the "message" part of the exception and not the full exception stack:
try
{
...
}
catch(Exception^ e)
{
LogMessage("Exception caught: " + e->ToString());
}
When the exception is caught, the LogMessage outputs only the following text:
"Exception caught: The object already exists"
I've tried e->ToString() and e->Message, but both result in the same output and that does not include the full exception stack.
In C# it seems to be really easy to output the full exception stack, so I am not sure why it seems to be difficult in C++/CX ?
This is difficult in C++/CX because determining what functions would be in the stack requires code to parse debugging symbols. In C#, the CLR does work at runtime to remember which methods are in the stack, but in C++/CX, the names of functions are not recorded in the resulting binary. Put another way, the stack trace you get in C# depends on a C# feature: reflection.
Moreover, an exception may result from a call into code which is a plain COM API, rather than a C++/CX API. In such cases, the exception is generated from an error HRESULT return code underneath, not at the time where the exception is thrown. (Indeed, this is what happens whenever crossing component boundaries; this is handled with plain COM even if both sides of the operation are C++/CX) As such, the stack you would need for a trace is no longer available.
C++ exceptions do not record a stack trace. On the plus side, from native programs you can collect a minidump when an unhandled exception occurs, which lets you view the stack using a debugger if you need to.
Keep in mind that a C++/CX program is pure unmanaged C++ code. The CX language extension only makes it easy to consume WinRT types in your C++ code, it hides the COM implementation details. So it gets the full treatment of the code optimizer. Which does not try to ensure that stack walks can be safely performed. Particularly so in leaf functions that don't throw exceptions. It will readily omit setting the EBP register, the important one that indicates the base of a stack activation frame.
This is not the case in managed code, like C#. Stack walks are very important in a garbage collected runtime environment. The garbage collector must perform them to find object references when it collects garbage. Code Access Security also depends on stack walks. A happy side effect is that it now also becomes very easy to generate a stack trace for an exception. It is even exposed in the framework api, the StackTrace class lets you walk the stack in your own code.
No simple fix for this, you need debugging symbols to have a shot at it. And StackWalk64 from the DbgHelp api. With odds that you still don't get anywhere because the program crashed somewhere in the bowels of a Windows function. Speed trumps convenience in C++.
I'm protecting my own C++ code (Windows x86) from exceptions in a third party COM object and logging those exceptions using the following SEH pseudocode.
__try {
hr = m_ComObj->SomeFunc();
} __except ( LogExceptionInfo(GetExceptionCode(), GetExceptionInformation()) ) {
hr = E_UNEXPECTED;
m_ComObjCrashed = true;
}
Is this approach likely to catch exceptions that would be handled if the SEH code wasn't present?
An MSDN article below mentions that the default unhandled exception filter will catch and fix the case where code writes to memory in loaded resources. Are there other cases where using SEH will interfere with desirable default OS behaviour?
A Crash Course on the Depths of Win32™ Structured Exception Handling
Yes it's quite reasonable.
It will catch all exceptions that are unhandled in the COM function
I don't see any interference-related problems with default OS behaviour
An MFC, C++ application I'm working on seems to be throwing an exception deep inside a device driver. (It's an access violation writing to a NULL pointer from the looks of things. The details of the crash are not what is interesting me right now, however...)
I can get the Visual Studio Debugger to break when the exception occurs through the Exceptions dialog. What I would like to know though is where the exception is being caught. Visual Studio can pass the exception on to the program being debugged, but there doesn't seem to be anyway (that I know of) to single step to the next instruction so I can view the callstack from the exception handler's point of view.
Does anyone know whether it is possible to step to the exception handler that will catch the exception or not?
Cheers,
James
With WinDbg, you can use the !exchain command. With !exchain -c, it will show your C++ destructors and catch blocks. e.g.
Try block 0
Catch block 0, type: module!my_exception `RTTI Type Descriptor'+0 (6071409c)
handler: module!catch_block+582 (6063bcc2)
Then you can set a breakpoint with bp 6063bcc2.
I don't know of a way to do this in Visual Studio.
At the point when the exception is being thrown you should have a call stack available to you in the debugger -- by looking at each stack frame from the point of the throw to main, you should be able to find the first frame with a try/catch block wrapping the call to the next routine in the frame. As long as that try/catch block handles the type of exception being thrown, that's where it'll land.