The key reason to separating internal business objects from the data contracts/message contracts is that you don't want internal changes to your app to necessarily change the service contract. If you're creating versioned web services (with more than 1 version of the implemented interfaces) then you often have a single version of your apps business objects with more than 1 version of the data contract/message contract objects.
In addition, in complex Enterprise Integration situations you often have a canonical data format (Data and Message contracts) which is shared by a number of applications, which forces each application to map the canonical data format to its internal object model.
If you want a tool to help with the nitty gritty of separating data contract/message contract etc. then check out Microsoft's Web Services Software Factory http://msdn.microsoft.com/en-us/library/cc487895.aspx which has some good recipes for solving the WCF plumbing.
In regards to excpetions, WCF automatically wraps all exceptions in FaultExceptions, which are serialized as wire-format faults.
It's also possible to throw generic Fault Exceptions which allows you to specify additional details to be included with the serialized fault. Since the faults thrown by a web service operation are part of its contract it's a good idea to declare the faults on the operation declaration:
[FaultContract(typeof(AuthenticationFault))]
[FaultContract(typeof(AuthorizationFault))]
StoreLocationResponse StoreLocation(StoreLocationRequest request);
Both the AuthenticationFault and AuthorizationFault types represent the additional details to be serialized and sent over the wire and can be thrown as follows:
throw new FaultException<AuthenticationFault>(new AuthenticationFault());
If you want more details then shout; I've been living and breathing this stuff for so long I almost making a living doing it ;)