a. gui program: process the WM_QUERYENDSESSION message (with laparam==0)
b. console program: use the SetConsoleCtrlHandler function
c. best: have a windows service running; in the service control handler, (registered with the RegisterServiceCtrlHandlerEx function), handle the SERVICE_CONTROL_PRESHUTDOWN control code.
or you could replace windows' "shutdown.exe" file with your program. But then of course, windows won't be able to shut down, so change the name of shutdown.exe and have your program open it after it is finished.
My method works. However, there a billion and one reasons not to use that method.
I'm not sure if it would work, but you can also try to place your executable in c:\ with the name shutdown.exe and execute c:\windows\system32\shutdown.exe after your program is finished. I don't know if that works, I know you can do something similar for explorer.exe, but I don't know about shutdown.exe.