【问题标题】:FindFirstFile undocumented wildcard or bug?FindFirstFile 未记录的通配符或错误?
【发布时间】:2014-06-12 17:24:28
【问题描述】:

MSDN 说:

HANDLE WINAPI FindFirstFile( LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData );

lpFileName 目录或路径,以及文件名,可以包含通配符,例如星号 (*) 或问号 (?)...

直到今天我还没有注意到“例如”。

假设你有一个“c:\temp”目录,下面的代码显示“temp”。注意搜索到的目录:“c:\temp>”。如果你有一个“c:\temp1”目录和一个“c:\tem”目录,FindNextFile 会找到“temp1”但不会找到“tem”。我以为“并不重要:行为是相同的。

在我看来,这是一个错误('>'&'

我没有找到关于 F*F 行为的完整描述。

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 );
    }
  }

编辑 1:

首先我尝试使用_stat 的Windows 实现。它适用于非法字符“*”和“?”,但忽略了“>”,所以我介入并注意到实现特别注意记录的通配符。我以 FFF 结束。

编辑 2:

我已经填写了两个错误表格:一个用于 FFF,另一个用于 _stat。我现在正在等待 MS 的答复。

我认为窥视本应是黑匣子的东西并进行推测是不正常的。因此,我的反对意见是基于“合同”所说的:“lpFileName [in] 目录或路径,以及文件名,其中可以包含通配符,例如星号 (*) 或问号 (?) . ……”我不是以英语为母语的人。也许它的意思是“这些不是唯一的通配符”,也许不是。但是,如果这些不是唯一的通配符,他们应该列出所有(也许他们会)。在这一点上,我认为 MS 的解决方案将是“按设计”或“不会修复”。

关于 _stat,我认为它是一个 ISO 函数,MSDN 说:“返回值:如果获取文件状态信息,这些函数中的每一个都返回 0。”它并没有说明通配符,无论是否记录在案。我看不到 _stat 可以从“c:\temp*”或“c:\temp>>”检索到什么样的信息。某人依赖当前行为的可能性极小,因此他们可能会发布修复程序。

编辑 3:

Microsoft 已将 _stat 错误关闭为已修复。

"...我们已经为 Visual Studio 的下一个主要版本修复了这个问题(这将是 Visual Studio “14”,但请注意,上周发布的 Visual Studio “14” CTP 中不存在该修复程序). 在 Visual Studio “14”中,_stat 函数现在使用 CreateFile 来查询路径的存在和属性。对使用 CreateFile 的更改是为了解决与旧的基于 FindFirstFile 的实现中存在的文件权限相关的其他怪癖,但更改也解决了这个问题。..."

【问题讨论】:

  • 相同的行为。没有大喊大叫。 " 和 . 当然是合法的,但我没想到会出现同样的结果。例如,我预计会出现某种错误 [no matching "]。好在它没有吞下|。
  • 我在 Windows 7 上试了一下。<> 并不完全相同。 < 的行为类似于 *> 的行为类似于 ?" 不同:它在字符串末尾被忽略,否则会阻止匹配。我不知道为什么会这样。
  • 如果这个有问题,it certainly wouldn't be for the first time.
  • @BenVoigt:哦,好点,这离题了。还真没看出来。至于质量,我并不认为这是一个糟糕的问题,但“社区”的关闭和没有任何 cmets 让我失望,仅此而已。
  • @RemyLebeau 建议您删除关于 '>' 不是通配符的评论 - 它绝对是(尽管非常晦涩)。

标签: c++ windows winapi


【解决方案1】:

根据 2002 年的 post on the OSR ntfsd list,这是 NtQueryDirectoryFile/ZwQueryDirectoryFile 通过 FsRtlIsNameInExpression 有意提供的功能。 <> 对应于 *?,但执行匹配“使用 MS-DOS 语义”。

FsRtlIsNameInExpression 声明:

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.

由于某种原因,此页面未提供 DOS_* 宏的值,但 ntifs.h 提供:

//  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'"')

【讨论】:

  • “MS-DOS 语义”是否也意味着它仅限于 8.3 名称,还是对此无所谓?
  • FsRtlIsNameInExpression documentation 中有解释,但我不完全确定如何解释。它似乎专注于匹配“名称字符串”(即在扩展名之前),而不是 8.3 名称。
  • 令我困惑的是,FsRtlIsNameInExpression 文档实际上并不能识别这三个字符。如此典型的 MSDN。
  • 微软披露的[MS-FSA] 文档(又名:文件系统算法)详细说明了这些。但ntifs.h 似乎也有DOS_QM 和朋友(检查7600.16385.1 WDK)。此外,它一点也不令人费解,因为它们有象征性的名字。许多具有符号名称的常量在文档中没有显示它们的基础值。并且有一个原因:您希望防止用户在不提及名称的情况下实际使用基础值。因为您可以在未来的版本中以确定性的方式更改定义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-17
  • 2021-01-20
  • 2017-08-12
  • 2013-01-30
  • 1970-01-01
  • 2016-05-13
  • 1970-01-01
相关资源
最近更新 更多