Scenario 2 basically calls Application.Exit(), which should amount to a graceful shutdown of all threads associated with your process. It also fires events you can use to perform any additional cleanup.
3 and 4 can be "trapped" by attaching a handler to the Application.ThreadException event of a WinForms app. This event is fired when any exception is about to be thrown out of the program to be handled by the runtime (which will terminate your assembly's execution and clean the sandbox). However, at this point there's very little you should do other than write something to the Event log or clean up any statics, like an IoC container or repository, and even that's problematic because if one of those objects caused the exception, you could very easily throw another exception in trying to deal with the last one.
Basically, if your user is using "kill" or "End Process" to close your app, there's something VERY wrong and you should probably address the underlying reason why a user would be doing that, before trying to gracefully capture such termination behaviors.