The Windows file system has documented set of rules for creating file and directory names.
IsValidFileName() provides functions to check a filename against this set.
They also return error codes enabling the developer to display more specific codes for the user.
(These functions do NOT do a comprehensive search of the global name space to ensure
there are no other failure modes with the file name in a subsequent file and/or directory
creation. For example, the directory could already exist.)
The File Naming Rules
The file system has the following rules for creating names for files or directories:
- All characters greater than ASCII 31 to be used except for the following: "*/:<>?\|
- The name may not be only dots
- The following device names cannot be used for a file name nor may they be used for the first segment of
a file name (that part which precedes the first dot):
CLOCK$, AUX, CON, NUL, PRN, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9,
LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9
- Device names are case insensitive. (i.e.
aux, AUX, Aux, etc. are identical.)
- Names cannot be longer than 255 characters unless
UNICODE paths are used
(There are additional rules for naming file paths, but they are of no concern here; refer to the WIN32 SDK
documentation under "File Name Conventions" for additional information.)
int IsValidFileName(const char *pFileName);
int IsValidFileName(const wchar_t *pFileName);
const TCHAR *pInvalidFileNameErrStr;
const TCHAR *GetIsValidFileNameErrStr(int err);
IsValidFileName() will validate a file name against the above rules. It is implemented as two
overloaded functions, one which accepts a
const char * and one which accepts a
const wchar_t *.
The function will return zero on success and non-zero on failure. A non-zero return value indicates what the error was.
The possible values are listed in the following table:
||An illegal character was encountered. The return value is the illegal character.
If the return value is a dot ('.', 46) the file name was nothing but dots.
||A NULL or zero length file name was passed.
||A device name was used. The value corresponds to the
series of enumerations. You can pass this value to
GetIsValidFileNameErrStr() to obtain a pointer to the name of this device.
GetIsValidFileNameErrStr() is provided to facilitate reporting errors. This function accepts a
negative value in the range of the
INVALID_FILENAME_... series of enumerations and returns the
device name associated with that value.
The array of strings used for this function is exposed as
const TCHAR *pInvalidFileNameErrStr"
The source code is commented and self explanatory.
The .cpp does not include a precompiled header. If you are using this in a project with precompiled headers, just
add the proper name or include the .cpp file in one of the project's cpp files.
The source may look inefficient and confusing, but it is highly optimized. It is more than 11.5 times faster than
if a scanning method using
_strnicmp was used.
Joe is one of those software engineers with a film degree. His first paid programming job (what, you think film is a good way to make a living?) was writing games for Apple II's using 6502 assembly. He soon moved to 80x86 assembly, C then C++ for a long time and finally, C#/.NET.
He first wrote software for Windows 3.0 in 1990, when it was first released. Save for some continued work in DOS and a horid, and mercifully brief, foray into OS/2, he has concentrated on designing and writing Windows applications, libraries and middleware, whatever that is.