I think nothing is inherently wrong with your code (even though the behavior that you get is obviously undesired, I think it is somehow nevertheless exactly doing what you're asking for).
What you are doing is peek and drain the message queue until it is empty, then you draw some stuff and flip buffers, which presumably blocks for 16ms.
16ms is a very long time for a computer, and everything else that you do happens more or less "instantly" in comparison to that. Therefore most of the time, this will just work fine, as you spend 99% of your time inside SwapBuffers, and so your different key presses all arrive while your application is blocked. When you next drain the message queue, you get all events that are in the queue, and it's correct.
However, sometimes, it may just happen that one key event arrives in the message queue while you're draining it. After that, there are none left, so your loop continues (of course, what else!). The next event arrives, but that is now irrelevant since you're already somewhere in your OpenGL calls, and after that you block for 16ms. So you get a huge delay between two keypresses that actually happen simultaneously (or nearly so).
Now, why you get figures of 100+ milliseconds, I can't answer. That's truly odd.
(I once upon a time, years ago, tried stamping messages with values obtained from timeGetTime by the way, and Windows message queues push events through much faster than the minimum resolution (which is 0.5ms here), so I doubt it's a Windows message problem as such)