Another boring thread ...
Keyboard input works in this manner on Windows:
1. Designated message handler receives WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, WM_SYSKEYDOWN. The first 7 bits of the lparam for the message handler contains the virtual key code for the physical key pressed on the keyboard (i.e. pressing 8 in the top row isn't the same physical key as pressing 8 on the keypad, the right shift key isn't the same as left shift key, etc.) and the Windows function can be used to obtain the ASCII (0-255 keycode) which in the Windows implementation appears to be able to support: English, French, German, Italian, Portuguese, Danish, Dutch, Norwegian, Icelandic and Spanish (according to Wikipedia).
In something like Quake where you want to be able to deal with continuous press states, versus say key repeats and the timing issues this would present (example the +turnleft key where this would work differently based on control panel settings, had it been implemented another way), both the virtual key and the what that key represents are 2 separate pieces of information. Quake overcomes this with a fixed key map table, the disadvantage of which this that the hardcoded keys are only correct for, say, an English keyboard. [Quake 3 and, for example, DarkPlaces use the ToAscii method to correctly map the keys for non-English keyboards].
In Quake, there are 3 situations that should be nullified: ALT-SPACE if the Window is full-screen (arguably windowed mode too) as ALT-Space triggers the start menu (WM_SYSCHAR, returning a zero takes care of that.) StickyKeys, ToggleKeys, Filter keys are undesirable and those can be disabled by API (they must be re-enabled on exit). And the "Windows" key and "Context menu key" which can be nullified via SetWindowsHookEx and setting a function to handle it which returns 1 for those keys (VK_LWIN - left Windows key, VK_RWIN - right Windows key, VK_APPS --- context menu).
2. The console. In Quake, certain keys are often coded to behave in a specific way when the console is displayed. The arrow keys, for instance, always move the cursor. Some engines have the numeric keyboard always produce numbers in the console, ignoring the numlock key state.
3. In Quake, the keys that mapped to Quake button functions such as "+attack" or "+jump" also keep track of up to 2 keys that may have been pressed to trigger that function to ensure that a continuous "attack" or "jump" can be maintained even if two separate were pressed to do the same thing.
4. Overcoming timing: It is possible for a key to be pressed and released quickly enough both occur during the same frame (i.e. what you are getting 30 FPS on some giant map in a wide open area). In that event, Quake does something interesting: a button pressed and released within a frame receives a fraction of 0.25, a button pressed or released during a frame gets a fraction of 0.5 and a continuously held button receives a fraction of 1.0 --- these are used in combination with the amount of time for the frame (i.e. 100 frames per second = 1/100 of a second) for angle manipulation like pressing an arrow key to turn left or right or some other key to look up.