Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FindFirstFile undocumented wildcard or bug?

MSDN says:

HANDLE WINAPI FindFirstFile( LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData );

lpFileName The directory or path, and the file name, which can include wildcard characters, for example, an asterisk (*) or a question mark (?)...

Until today I didn't noticed the “for example”.

Assuming you have a “c:\temp” directory, the code below displays “temp”. Notice the searched directory: “c:\temp>”. If you have a “c:\temp1” directory and a “c:\tem” directory, FindNextFile will find “temp1” but will not find “tem”. I assumed that ‘<’ will find “tem” but I was wrong: it behaves in the same way. It does not matter how many ‘<’/’>’ you append: the behavior is the same.

From my point of view, this is a bug ('>'&'<' are not valid characters in a file name). From Microsoft’s point of view it may be a feature.

I did not manage to find a complete description of F*F’s behavior.

const TCHAR* s = _T("c:\\temp>");
  {
    WIN32_FIND_DATA d;
    HANDLE h;

    h = FindFirstFile( s, &d );
    if ( h == INVALID_HANDLE_VALUE )
    {
      CString m;
      m.Format( _T("FindFirstFile failed (%d)\n"), GetLastError() );
      AfxMessageBox( m );
      return;
    }
    else
    {
      AfxMessageBox( d.cFileName );
      FindClose( h );
    }
  }

Edit 1:

In the first place I have tried to use Windows implementation of _stat. It worked fine with illegal characters ‘*’ and ‘?’, but ignored ‘>’, so I stepped in and noticed that the implementation took special care of the documented wildcards. I ended in FFF.

Edit 2:

I have filled two bug forms: one for FFF the other for _stat. I am now waiting for MS’s answer.

I do not think that it is normal to peek into something that is supposed to be a black-box and speculate. Therefore, my objections are based on what the “contract” says: “lpFileName [in] The directory or path, and the file name, which can include wildcard characters, for example, an asterisk (*) or a question mark (?). …” I am not a native English speaker. Maybe it means “these are not the only wildcards”, maybe not. However, if these are not the only wildcards, they should have listed all (maybe they will). At this point, I think the MS’s resolution will be “By Design” or “Won’t fix”.

Regarding _stat, which I think it is an ISO function, MSDN says: “Return value: Each of these functions returns 0 if the file-status information is obtained.” It does not say a thing about the wildcards, documented or not. I do not see what kind of information _stat may retrieve from “c:\temp*” or “c:\temp>>”. It is highly unlikely that someone is relying on current behavior, so they may issue a fix.

Edit 3:

Microsoft has closed the _stat bug as Fixed.

"... We have fixed this for the next major release of Visual Studio (this will be Visual Studio “14,” but note that the fix is not present in the Visual Studio “14” CTP that was released last week). In Visual Studio “14,” the _stat functions now use CreateFile to query existence and properties of a path. The change to use CreateFile was done to work around other quirks related to file permissions that were present in the old FindFirstFile-based implementation, but the change has also resolved this issue. ..."

like image 665
zdf Avatar asked Jun 12 '14 17:06

zdf


1 Answers

According to a post on the OSR ntfsd list from 2002, this is an intentional feature of NtQueryDirectoryFile/ZwQueryDirectoryFile via FsRtlIsNameInExpression. < and > correspond to * and ?, but perform matching "using MS-DOS semantics".

The FsRtlIsNameInExpression states:

The following wildcard characters can be used in the pattern string.

Wildcard character  Meaning

* (asterisk)        Matches zero or more characters.

? (question mark)   Matches a single character.

DOS_DOT             Matches either a period or zero characters beyond the name
                    string.

DOS_QM              Matches any single character or, upon encountering a period
                    or end of name string, advances the expression to the end of
                    the set of contiguous DOS_QMs.

DOS_STAR            Matches zero or more characters until encountering and
                    matching the final . in the name.

For some reason, this page does not give the values of the DOS_* macros, but ntifs.h does:

//  The following constants provide addition meta characters to fully
//  support the more obscure aspects of DOS wild card processing.

#define DOS_STAR        (L'<')
#define DOS_QM          (L'>')
#define DOS_DOT         (L'"')
like image 63
nobody Avatar answered Sep 19 '22 03:09

nobody