According to the CiviCRM hook specification (http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+hook+specification), it should be possible to abort an operation using the pre-hook. However, when saving the contact form, although the pre hook fires, the page processing continues regardless of return value.
Patch attached for 2.0 trunk.
A few ambiguities: the spec says "pre-hooks return a boolean and/or an error message which aborts the operation". I'm checking for explicit FALSE return from hooks & page postProcess, to maintain backward compatability with existing functions that return nothing. (I don't handle the error message case, not sure what the intent of spec is for that.)
I've added similar logic for post-hook – the spec only mentions pre-hook, but the code includes same comment for return value. Although the data has already been saved to the database by the time the post-hook fires, there may be scenarios where it's desirable to not proceed to next state.
I only dealt with the form level, specifically CRM_Contact_Form_Edit; I didn't address the other calls to CRM_Utils_Hook from BAO classes.
Similar logic should probably be added in CRM_Utils_Hook_Joomla and CRM_Utils_Hook_Standalone (I didn't do so since I'm not equipped to test those).