I just watched Christopher Brumme on Channel 9 talk about reliability in the Common Language Runtime. In the presentation he talks about the "exceptions traveling through your code" in a very natural way. What I like about this wording and Chris's tone is that it implies exceptions are a very natural thing to have running around. In other words, rarely will your code execute flawlessly thus you must write code that is able to handle exceptional circumstances.
Of course, good developers know that exceptional circumstances are by no means unique to managed code development. Anytime you write code you must be prepared for errors to occur and handle them appropriately. Therefore, if you share my philosophy that setup is just like any other code in your product then you should expect exceptional circumstances during any invocation of your setup (install, uninstall, repair, upgrade, patch, install on demand, etc.).
So, what is the point of all my sloppy deduction based on some comments made by an Architect on the .NET CLR team while he was sitting in front of a camera?
My point is that when you write a setup package, you must assume that any action during setup could fail and that you must (at least try to) compensate for the action. For the Windows Installer that means you should provide a rollback action for any action that modifies the user's machine . Also, remember uninstall actions are different from install actions while repair actions and upgrade actions are usually not. Of course, the 2nd Axiom of Setup tells you that sometimes repair and upgrade rollback actions are different from install rollback actions and uninstall rollback can sometimes be the same as install rollback (but not usually).
Fortunately, the Windows Installer handles the rollback actions for all the standard actions (except SelfReg). Hopefully, that fact alone encourages you to use the native Windows Installer constructs whenever possible. Thus, in the end, it really is those of us who write CustomActions that modify the users' machines during setup that truly need to internalize Chris's statement that there are always "exceptions traveling through your code" (and setup!) to heart. The rest of you should just keep it in the back of your mind.
 Don't get trapped in a logical infinite loop trying to provide rollback actions for rollback actions. Fix any bugs in your code and if the world is still so messed up that you can't compensate when something goes wrong, don't feel too bad. The only thing you can do in a situation where you can't rollback is try to never do that which can't be compensated.