13

Is there a Windows API function that I can pass a string value to that will return a value indicating whether a file name is valid or not?

I need to verify that a file name is valid, and I'm looking for an easy way to do it without re-inventing the wheel. I'm working in straight C, but targeting the Win32 API.

If there's no such function built-in, how would I go about writing my own? Is there a general algorithm or pattern that Windows follows for determining file name validity?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
akmal
  • 655
  • 5
  • 24

3 Answers3

7

The problem is not so simple, because it depends from what you consider a "valid file name".

The Windows APIs used with UNC paths will let you happily create a lot of names that are deemed invalid inside normal paths, since with the prefix \\?\ you are telling to the Windows APIs to just deliver the path to the filesystem driver, without performing any check; the filesystems themselves often do not really care about what it's used as a file name, once they know that some string is only the file name (i.e. the path/name split has already been done) they generally treat it just as an opaque sequence of characters.

On the other hand, if you want to play it safe, you should perform validation according to the rules specified by the MSDN document you already linked for Win32 names; I don't think that any file system is allowed to have more stringent rules than these on file naming. On the other hand, violating such requirements, although can be supported by the kernel itself, often give bad headaches to many "normal" applications that expect to deal with "traditional" Win32 paths.

But, in my opinion, if you have to create the file immediately, the best validation you can do is to try to actually create/open the file, letting the OS do such work for you, and be prepared to handle gracefully a failure (GetLastError should return ERROR_BAD_PATHNAME). This will check any other restriction you have on creating such file, e.g. that your application has the appropriate permissions, that the path is not on a readonly medium, ...

If, for some reason, this is not possible, you may like the shell function PathCleanupSpec: provided the requested file name and the directory in the file system where it has to be created, this function will remove all the invalid characters (I'm not sure about reserved DOS names, they are not listed in its documentation) making the path "probably valid" and notifying you if any modification was made (so you can use it also only for validation).

Notice that this function is marked as "modifiable or removable in any future Windows version", although Microsoft policy is generally that "anything that made it way to a public header will remain public forever".

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • 1
    +1 for "try and check for failure" rather than performing your own checks. This is really the only correct way to ever test things like OP's question. – R.. GitHub STOP HELPING ICE Aug 20 '11 at 13:52
  • @Matteo Italia, interesting trick with creating and opening file, but it is not possible in my case, because of I'm working with optical media. – akmal Aug 22 '11 at 05:08
  • @akmal: in this case, you have to consider also the restrictions of ISO 9660, Joliet, UDF, ... depending on which extensions you are going to use (assuming that you are working with CDs or DVDs). But I think that the `PathCleanupSpec` should basically work anyway. – Matteo Italia Aug 22 '11 at 08:34
  • @Matteo Italia, I tried 'PathCleanupSpec', and I think it's not solution because this function is only for cleaning the input file/folder name. – akmal Aug 24 '11 at 07:10
  • @MatteoItalia I liked your create/open idea, but it didn't really work. I just tested with `CreateFile( "C:\Path\To\File\My:File*.ext" )` and it happily created a file named "My" in the path provided. So create/open is not a good solution either. Not to mention times when extra path info is entered within the filename -- security hole anyone? – Steve Valliere Nov 12 '19 at 12:27
  • 1
    @SteveValliere: the file name you entered is actually a valid one. You created a `My` file with an [alternate data stream](http://www.flexhex.com/docs/articles/alternate-streams.phtml) `File*.ext`. – Matteo Italia Nov 12 '19 at 13:29
  • @MatteoItalia It is not valid according to the referenced MSDN document which prohibits colon in a file name. Most folks reading this are probably not interested in supporting alternate data streams. Also, names like "..\..\..\..\..\Windows\System32\somethingbad.dll" can be quite problemmatic, but may open/create OK, too. I just wanted to point these things out for future readers of this answer so that they are aware of the limitations. – Steve Valliere Nov 12 '19 at 18:07
0

In case you are checking if the file name is valid in the sense "can the file be named like this?" :

No, there is no function to directly check that. You will have to write you own function.

But, if you know what is a valid file name (the valid file name does now contain any of the following: \ / : * ? " < > |) that shouldn't be such a problem.

You could perhaps help your self with some of these functions from ctype.h (with them you can check if a specific character belongs to some specific character classes):

http://www.cplusplus.com/reference/clibrary/cctype/

penelope
  • 8,251
  • 8
  • 45
  • 87
  • 1
    Things are not so simple, like you described, there are a lot of additional restrictions on file names, for example: reserved file names like (con, com1,com2,...), names which end with space or period, and so on. – akmal Aug 20 '11 at 09:52
-2

This function gives you the list of invalid chars for a filename. Up to you to check that your filename doesn't contain any:

public static char[] Path.GetInvalidFileNameChars()

Docs here.

Note that if you want to validate a directory name, you should use GetInvalidPathChars().

EDIT: Oooops! Sorry, I thought you were on .NET. Using Reflector, here's what this functions boils down to:

'"', '<', '>', '|', 
'\0', '\x0001', '\x0002', '\x0003', '\x0004', '\x0005', '\x0006', 
'\a', '\b', '\t', '\n', '\v', '\f', '\r', 
'\x000e', '\x000f', '\x0010', '\x0011', '\x0012', '\x0013', '\x0014', '\x0015', 
'\x0016', '\x0017', '\x0018', '\x0019', '\x001a', '\x001b', '\x001c', '\x001d', 
'\x001e', '\x001f', 
':', '*', '?', '\\', '/'

Note that, in addition, there are reserved names such as prn, con, com1, com2,... , lpt1, lpt2,...

Serge Wautier
  • 21,494
  • 13
  • 69
  • 110
  • As [this answer](http://stackoverflow.com/questions/62771/how-check-if-given-string-is-legal-allowed-file-name-under-windows/62888#62888) explains, there is more to consider than just the individual characters. – johnsyweb Aug 20 '11 at 10:05
  • I'm not asking about what I must check to validate file name, I asked about ready function for this purposes. – akmal Aug 20 '11 at 10:09
  • @Serge - appTranslator, [Naming Files, Paths, and Namespaces](http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx) I have read about naming files from this source, is this enough? – akmal Aug 20 '11 at 10:11
  • I just named a file `☺.ini` without issue (\x0001) – Orwellophile May 27 '18 at 19:34
  • @Orwellophile ☺ does not have code 1; ALT codes are different from character codes – SWdV Apr 20 '19 at 14:27