Is it possible to silently catch errors popup like "the procedure entry point xxx could not be located int the dynamic link library xxx" when calling LoadLibrary() ?
You can suppress the error popups by calling SetErrorMode():
// GetErrorMode() only exists on Vista and higher,
// call SetErrorMode() twice to achieve the same effect.
UINT oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
SetErrorMode(oldErrorMode | SEM_FAILCRITICALERRORS);
HMODULE library = LoadLibrary("YourLibrary.dll");
// Restore previous error mode.
SetErrorMode(oldErrorMode);
The call to LoadLibrary() will still fail, though.
Related
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.
I have a crash that is caught in Sentry.
CWnd::IsWindowVisible
Unhandled
Fatal Error: EXCEPTION_ACCESS_VIOLATION_READ
I downloaded the mini dump file (dmp) and ran through Visual Studio 19. The crash is occurring in the method:
BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
I'm including a screen shot because one of my questions is:
Where exactly is the crash? Is the line (screenshot) really representing the crash?
Using the debugger I can see that the parameter message coming into the method is 275 which is
0113 275 WM_TIMER
See for example: https://wiki.winehq.org/List_Of_Windows_Messages.
My questions:
Where exactly is the crash? I don't see how checking for pResult being NULL and assigning lResult to *pResult could cause a crash of any kind and certainly not EXCEPTION_ACCESS_VIOLATION_READ
In anticipation of somebody stating that the exception is actually elsewhere...
a. How do I get the exact location/problem from the dump
b. Anyone recognize this type of problem with TIMERS? It's not my code, but I'm already imagining such things as multiple stops of timers, doing something to a Window that no longer exists, etc. Based on EXCEPTION_ACCESS_VIOLATION_READ
Any clues/ideas how to proceed?
As always, if better asked in another group, or more clarification needed, please let me know.
And Thanks!
EDIT - ADDITIONAL INFO
Note that Sentry says the program is actually crashing on IsWindowVisible. That certainly isn't present in debugging the dump file (that I can see) and the point of crash as shown by the screen shot doesn't show it, but it might make sense. The OnTimer routine certainly mentions IsWindowVisible().
4. Can IsWindowVisible() crash with EXCEPTION_ACCESS_VIOLATION_READ ?
I'd like to build an application that invokes CancelIoEx on Windows Vista and newer (where it is supported) and does something else on Windows XP (where it is not).
What happens if I compile the application under Windows 7 but run it under Windows XP? What will happen at runtime? Will I get some sort of load error?
How do I get my application to pick one code path or another (avoiding load errors) depending on what operating system is being used at runtime? Please provide sample code.
UPDATE: Please note that the DLL exists on Windows XP but the function does not.
Yes, an application that references a non-existent DLL export will fail to load.
Adding code to take different paths based on the OS version won't help much, because you'll still have the reference to the non-existent function.
Instead, you need to resolve the reference at run-time.
One option is Delay Load Import (with the /DELAYLOAD linker flag), but I don't think this is supported for the core system DLLs (like kernel32).
The other is to use LoadLibrary and GetProcAddress. The code is something like this, though in reality you'd do the lookup once when your app starts, not each time you call the function.
// Declare type of pointer to CancelIoEx function
typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
// Load module; won't fail because it's already imported
HMODULE hKernel32 = LoadLibrary(L"kernel32.dll");
// Look up function address
CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx");
// Do something with it
if (pCancelIoEx)
{
// Function exists so call it
pCancelIoEx(hMyFile, pMyOverlapped);
}
else
{
// Function doesn't exist
}
In order to resolve a symbol at runtime, you need to use LoadLibrary and GetProcAddress:
HMODULE kernel32 = LoadLibrary("kernel32.dll");
BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED) = GetProcAddress(kernel32, "CancelIoEx");
In the case that CancelIoEx is not available, you will get NULL back from GetProcAddress. Once you have the pointer (you only need to do the above once), you can call it normally with:
pCancelIoEx(h, &lp);
I'm playing around with SetWindowsHookEx, specifically I would like be able to find out about any window (on my desktop) thats been activated, via mouse or keyboard.
Reading through MSDN docs for SetWindowsHookEx it would appear that a WH_CBT type would do the job. I've created a dll and put all the code in there, which I control from a gui app (which also handles the unhook).
BUT I only appear to be getting the activation code when I activate my gui app though, any other app I activate is ignored.
In my dll I have the setup code and the CBTProc like so:
LRESULT WINAPI CBTProc(int Code, WPARAM W, LPARAM L) {
if(Code<0) CallN....
if (Code == HCBT_ACTIVATE) { // never get unless I activate my app
HWND a = reinterpret_cast<HWND>(W);
TRACE("this window was activated %d\n", a);
}
CallNext....
}
EXPORTED HHOOK WINAPI Setup(HWND MyWind) {
...
// gDllUInstance set in dllmain
return SetWindowsHookEx(WH_CBT, CBTProc, gDllUInstance, 0);
}
All pretty simple stuff, i've tried moving the setup out of the dll but I still get the same effect.
It would appear that the dll is getting loaded into other processes, I'm counting the number of DLL_PROCESS_ATTACHs I'm getting and can see its going up (not very scientific i know.
NOTE that this is 32 bit code running on 32bit OS - win2k3.
Are my expectations of the hooking mechanism wrong? should I only be getting the activation of my app or do I need a different type of hook?
EDIT: the trace function writes to a file telling me whats sending me activations
TIA.
Turns out its working ok, as Hans points out, i'm just not seeing the output from the debugger from the other processes, if I put in some extra tracing code - one trace file per attached process - I can see can see that things are working after all.
Many thanks for the replies.
Two questions.
1) I understand this must be an expected outcome but maybe someone can tell me what I'm doing wrong; I'm trying to subclass all window classes in a global hook and it works except that I'm not able to close shop as I should and when the program initially registering the hook unregisters the hook and exits, subclassed applications start crashing.
Here's how I'm trying to do it..
// stores original wndprocs. In the hook dll, outside the shared memory.
map<HWND, WNDPROC> origWndProcs;
// in an EnumWindows callback, executed for all HWND's, also in the hook dll (UWM_REMOVE_HOOK is a registered unique message)
SendMessageTimeout(hWnd, UWM_REMOVE_HOOK, 0, 0, SMTO_ABORTIFHUNG | SMTO_NORMAL, 15000, res);
// Still in the same hook, in the subclassing wndproc..
if (msg == UWM_REMOVE_HOOK) {
if (origWndProcs.find(hwnd) != origWndProcs.end()) {
SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)origWndProcs[hwnd]);
}
}
// clears the hook..
__declspec(dllexport) BOOL ClearHooks(HWND hWnd) {
BOOL unhooked = UnhookWindowsHookEx(hook) &&
UnhookWindowsHookEx(kb_hook) &&
UnhookWindowsHookEx(mouse_hook) &&
UnhookWindowsHookEx(cbt_hook);
if(unhooked)
hWndServer = NULL;
return unhooked;
}
In DllMain I don't do anything on DLL_PROCESS_DETACH. Instead, ClearHooks() is called from the program originally registering the hooks and there only after the hook has sent a message signalling that it has executed the EnumWindows operation (restores original wndprocs, see above).
I subclass windows in a WndProc hook; all visible windows that receive a message and whose current wndproc is not the one in the dll, are subclassed.
Basically all (as far as I can tell) applications crash on exit despite the fact that windows do seem to get the wndproc set back to what it was when it was replaced. Anyone have a clue what I might be doing wrong?
2) I need this to intercept WM_MINMAXINFO and modify window maxsize whenever a window is maximized. Unfortunately I can't do this in the dll but I have to talk with a program to get the size info. So, what's the best way to talk to that window; I need it to pass back some info so I can modify the structure that came with the original WM_MINMAXINFO message. Will a structure in WM_COPYDATA preserve it's data until the call to SendMessageTimeout returns?
Thanks
There are plenty of pain points here. You assume that no other code will subclass the window. And that such code will un-subclass it in the right order. There is no right order, your hooking is quite asynchronous from the program's execution.
But, the workaround is simple enough. You are already hooking with SetWindowsHookEx, might as well do one more. WH_CALLWNDPROC or WH_CALLWNDPROCRET, depending on what you want to do.