WinAPI - how to run some clean up code on forceful exit

67 Views Asked by At

I have this snippet:

#include <windows.h>

class Conf {
    public:
        Conf(int i) : m_i{ i } {
            MessageBoxA(NULL, "Conf", "", MB_OK);
        }

        ~Conf() {
            MessageBoxA(NULL, "~Conf", "", MB_OK);
        }

    private:
        int m_i;
};

Conf conf(26);

int WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstace,
    PSTR pCmdLine,
    int nCmdShow) {

    MSG msg;

    while (GetMessage(&msg, NULL, NULL, NULL)) {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    return 13;
}

When I run the executable, I immediately get the message box with text Conf. However, when the program is halted, say, via Task Manager, I expect the message box with text ~Conf, but get none.

How can I "hook" some clean up code to my executable that runs regarless how it is halted?

1

There are 1 best solutions below

0
Adrian McCarthy On

The Task Manager calls TerminateProcess (in effect), which marks all of the process's threads for termination, reclaims system resources, unmaps the process's code from memory, etc. From the process's point of view, it's instantaneous. No more code is going to run. And there's no way for a process to prevent itself from being terminated in this manner.


(I say "in effect" because TerminateProcess is a user mode function that, after checking parameters, delegates to NtTerminateProcess, which passes control on to ZwTerminateProcess. It wouldn't be surprising if the Task Manager skips TerminateProcess and calls directly to a lower-level API.)


When the user wants to log off or shut the machine down, Windows gives the running process's notice and a little bit of time to do some clean-up, but it will terminate them abruptly if they take too long. To get the notifications, GUI processes must handle certain messages, and console applications and system services must register control handlers for shutdown notifications.


My (possibly incorrect) memory is that much older versions of Task Manager would first try some gentler ways of getting the process to shut itself down before resorting to terminating the process. For example, it might have first sent WM_QUIT messages to the top-level windows of a GUI app or triggered the Ctrl+C signal handler of a console app. If the application ended quickly after that, it was done. Otherwise it would terminate the process.

Though uncommon today, a DLL could hold a single copy of its state even if that DLL were loaded into multiple processes. If a process is terminated while executing a call in the DLL, the DLL's global data could be left in an inconsistent state, possibly causing problems for the other processes. Thus it was worth the effort to try to give processes a chance exit in an orderly fashion.


The Restart Manager, which is used by installers and Windows Update, can request that applications shut down but terminate them if they don't do so promptly.