I'm using SQL Server 2005 and experiencing the same thing, at least in regards to a) (haven't reached b yet). Here's what I've figured out from digging around:
Whether you click 'Update' or 'Cancel', the data changes aren't actually entered into the database until you change records (next/previous). If this is how you're checking to see if the change has occurred, then Update will appear to be working correctly. However, if you click 'Update' and then simply exit the program, you will find on re-opening that the database still has the old values. So, in either case it is not working correctly.
I discovered that when the Update() function is run, it performs a check to see which (if any) fields are "dirty" (modified), but the flags for those fields are never set so they always return as false (clean), so no update is actually performed.
I tracked down the code for the database MoveNext/Prev/etc. functions to see how it was handling things, since that seems to do the trick. In those functions, prior to running the Update() it calls an UpdateData() function. I haven't done the diligence to find out how or why yet, but this function appears to set the appropriate "IsDirty" flags so that when Update() is called the data transfer occurs.
I was able to get it working properly (I think), by adding the line "UpdateData();" just in front of the m_pSet->Update() call in the UPDATE block. For the Cancelupdate operation, the call UpdateData(FALSE) appears to do the trick all on its own -- you don't even seem to need the m_pSet->CancelUpdate() call.
This is just me hacking around blindly, so there's probably several things wrong with doing it that way, but if you haven't lost interest by this time (or if someone else out there is struggling with the same thing), maybe this will help you get in the right direction.