For readers I found that setting the timeout for MsgWaitForMultipleObjects to even 1 millisecond is effectively equivalent to a Sleep and takes the CPU usage down from ~50% to less than 1 or 2%. Not sure why the documentation samples suggest a 0 timeout presumably so your app doesn't miss a beat; assuming your app is hogging the CPU and has something to do between timeouts (eg. single-threaded)
If you try to Sleep manually rather than using the timeout parameter then dinput8.dll (2009 build) eventually deadlocks on Acquire. My guess is this is a bug. Possibly a driver bug. But if its a physical hole in the scheduler (very possibly) then it should be documented.
Anyway using the timeout parameter, and not using Sleep, so far no deadlocks. But it's only been a short while of monkeying with it this way.