Paths in Windows are relatively complex. In particular, Microsoft has a habit of inventing new features, so even if your HTTP server is really protected against path traversal today, it may become vulnerable under next version of Windows, possibly even a small update.
Right now, your are using "blacklist-thinking": you are trying to enumerate all the "bad" constructions, and specifically detect them. Blacklists are known to be fragile because it is very hard to be exhaustive, and then to remain exhaustive. You should use whitelist-thinking, i.e. define a syntax for allowed paths and exclude everything else.
For instance, define that an allowed path consists in a sequence of components separated by slash characters ("/", not "\"), with the following rules:
- A component contains only letters, digits, dashes ("-"), underscores ("_") or dots (".").
- A dot may not appear as first or last character in a component.
- There shall not be any two consecutive dots in a component.
- A component contains at least one character, and at most 64 characters (arbitrary limit).
- No two consecutive slashes may appear in a path.
- A path does not begin with a slash.
- A path is not empty.
- The total length of a path shall not exceed 250 characters.
All these rules are easy to enforce programmatically. And they guarantee a "clean local path" that you can send to
fopen(). Note that most Windows functions are perfectly happy with the "/" as separator, but you may still want to replace all slashes by backslashes (after checking all the rules above, of course).