Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

FindFirstFile Bug or Explanation Please?

173 views
Skip to first unread message

Hector Santos

unread,
Jul 30, 2003, 9:52:42 PM7/30/03
to
Can someone explain this or do you consider the following a bug?

I was cleaning up my directory of *.exp files. But before I issued a "del
*.exp" command, I typed "dir *.exp" to see what I was about to delete. I
noticed an expected file in the resultant list. It included a file such as:

wcserver.exe.expired

I didn't think this is was right as I did not think Win32 would inherently
use a global wildcard on a extension search. In other words, I would
expected a search spec of "*.exp*" to return this, but not just "*.exp"
To see if Win32 was doing a wildcard search, I typed, "*.expi" to see if
Win32 would pick up the file. It did not.

So why would "*.exp" pick up this file, but "*.expi" will not?

To further explore this, I created 3 dummy files as so:

echo > deleteme.doc1
echo > deleteme.doc2
echo > deleteme.doc3

and typed:

dir *.doc

The result was the 3 first:

07/30/2003 09:42p 13 deleteme.doc1
07/30/2003 09:42p 13 deleteme.doc2
07/30/2003 09:42p 13 deleteme.doc3

That doesn't seem correct. If this logic is to hold, then a search spec of
"Dir *.do" should return the same result: It does not, as I expect it not
do. It kind of seems like there is some confusion with Windows/DOS
traditional 3 letter extensions in the internal masking logic. (Oh btw,
this is Windows 2000/PRO with NTFS drives)

So why would *.DOC work but not *.DO ??? Why is *.DOC working in the
first place?

I tested this as well with a simple C/C++ directory lister with the same
result:

void DirectList(const char *spec)
{
WIN32_FIND_DATA fd;
DWORD nTotal = 0;
HANDLE ff = FindFirstFile(spec, &fd);
if (ff != INVALID_HANDLE_VALUE) {
do {
printf("%08X %s %s\n",fd.dwFileAttributes,fd.cFileName);
nTotal++;
if ((nTotal % 25) == 0) getch();
} while (FindNextFile(ff, &fd));
CloseHandle(ff);
}
printf("total : %d\n",nTotal);
}

DirectList("*.DOC");
DirectList("*.DO");

etc, with the same results.

Bug or Explanation Please?

Thanks

----

Nick Ryan

unread,
Jul 30, 2003, 10:31:10 PM7/30/03
to
You're seeing this behavior because the filesytem is doing a short-name
comparison as well. Since short-names have at most a 3-character
extension, all of the extensions in your example (.doc1, .doc2, etc.)
will be truncated to .DOC in their short-name form, and thus will match
a wildcard search on *.doc.

Hector Santos wrote:

--
- Nick Ryan (MVP for DDK)

Carl Daniel [VC++ MVP]

unread,
Jul 30, 2003, 11:05:25 PM7/30/03
to
It's a "feature", or at least I've always believed it to be so. Presumably
the ide was to make long file names less confusing to befuddled DOS users
years back when NTFS first appeared. If you type a wildcard spec with
exactly three letters after a single period, it's treated as-if you'd
appended * after it. As far as I can recall, NTFS has always behaved this
way.

-cd

Hector Santos

unread,
Jul 31, 2003, 4:16:36 AM7/31/03
to
Thanks for your response....

"Carl Daniel [VC++ MVP]" <cpda...@nospam.mvps.org> wrote in message
news:O0EsZCxV...@tk2msftngp13.phx.gbl...


> It's a "feature", or at least I've always believed it to be so.
Presumably
> the ide was to make long file names less confusing to befuddled DOS users
> years back when NTFS first appeared.

ughhhhhhhhhhhhhhhhhhhhhhhh! Oh Brother! Compromising computer logic for
END USERS!? Thats totally un-american! <g>

well, I view it as a bug because it BREAKS the wildcard specification system
in MODERN times! Geez, Microsoft is embarking on a new ".NET Frontier" and
its still has a broken Directory Search System without providing a "Advanced
Extended function" for true 100% accurate long file name support?

I can accept the short name comparison reason, but even then, a
SPECIFICATION, is a SPECIFICATION, is a SPECIFICATION. <g>

> If you type a wildcard spec with
> exactly three letters after a single period, it's treated as-if you'd
> appended * after it. As far as I can recall, NTFS has always behaved this
> way.

Then you are saying the following two are equivalent?

dir *.doc
dir *.doc*

That is not what I am seeing.

Atleast, I think appending a period the end of your spec should signified
there is no extension:

dir *.doc. << period in the end

or this:

dir *doc. << no beginning period, with ending period

This should ATLEAST tell Win32 that there is NO extension Yet, it
continues as if there was. I can see why, because of the short file name.

Anyway, Microsoft should moderning its logic to view a specification that is
EXACT, atleast with a EX version of FindFirstFile(). Now I have to go on
living that you can't TRUST what you program!! :-)

--
Hector Santos
WINSERVER "Wildcat! Interactive Net Server"
support: http://www.winserver.com
sales: http://www.santronics.com

Hector Santos

unread,
Jul 31, 2003, 4:32:36 AM7/31/03
to

"Nick Ryan" <nr...@nryan.com> wrote in message
news:Ob%Va.16749$It4....@rwcrnsc51.ops.asp.att.net...

> You're seeing this behavior because the filesytem is doing a short-name
> comparison as well. Since short-names have at most a 3-character
> extension, all of the extensions in your example (.doc1, .doc2, etc.)
> will be truncated to .DOC in their short-name form, and thus will match
> a wildcard search on *.doc.

Thanks Ryan, I see what you are saying. Its stupid! Because what this is
saying that Microsoft lacks true 100% long file name support! What this
says is that you can't trust your system programming. It should atleast
take your input into consideration.

I created the following:

file1.exp
file2.exp.expired
file3.exp.expired.foobar

A DIR /X shows:

file.exp
FILEEX~1.EXP file.exp.expired
FILEEX~1.FOO file.exp.expired.foobar

If the following:

DIR FILE*.EXP*

is going to return all 3 files, and it does, then so should:

DIR FILE*1.EXP*

But it does not.

By the rules of Wildcard specification, the two specifications are the same
because anything after of the * is ignored, regardless of what is exactually
in storage. I can see why it doesn't work, but even the KLUDGE is
incorrect.

Anyway, thanks.

Carl Daniel [VC++ MVP]

unread,
Jul 31, 2003, 10:09:43 AM7/31/03
to
Hector Santos wrote:

> By the rules of Wildcard specification, the two specifications are
> the same because anything after of the * is ignored, regardless of
> what is exactually in storage. I can see why it doesn't work, but
> even the KLUDGE is incorrect.

That isn't true - it was for DOS, but not for NT. You can write a wildcard
of foo*bar*baz and it will match only those files that contain foo, bar &
baz substrings, in that order, with any intervening text.

-cd


Carl Daniel [VC++ MVP]

unread,
Jul 31, 2003, 10:45:14 AM7/31/03
to
Hector Santos wrote:
> Thanks for your response....

I think Nick Ryan's reply is closer to the truth: the filesystem is
searching both the short name and long-name spaces for matches.

>
> "Carl Daniel [VC++ MVP]" <cpda...@nospam.mvps.org> wrote in message
> news:O0EsZCxV...@tk2msftngp13.phx.gbl...
>> It's a "feature", or at least I've always believed it to be so.
> Presumably
>> the ide was to make long file names less confusing to befuddled DOS
>> users years back when NTFS first appeared.
>
> ughhhhhhhhhhhhhhhhhhhhhhhh! Oh Brother! Compromising computer logic
> for END USERS!? Thats totally un-american! <g>
>
> well, I view it as a bug because it BREAKS the wildcard specification
> system in MODERN times! Geez, Microsoft is embarking on a new ".NET
> Frontier" and its still has a broken Directory Search System without
> providing a "Advanced Extended function" for true 100% accurate long
> file name support?

You can turn off short-name support, although at the moment I don't recall
how. IMO, MS should have short-name support turned off by default in the
next version of Windows (I'd prefer if it was off by default in Windows 2000
and XP, but oh well).

>
> I can accept the short name comparison reason, but even then, a
> SPECIFICATION, is a SPECIFICATION, is a SPECIFICATION. <g>
>
>> If you type a wildcard spec with
>> exactly three letters after a single period, it's treated as-if you'd
>> appended * after it. As far as I can recall, NTFS has always
>> behaved this way.

This statement is wrong, although one might conclude that it's right by some
observed behaviors.

>
> Then you are saying the following two are equivalent?
>
> dir *.doc
> dir *.doc*

The sometimes behave as if they're equivalent, but it depends on what comes
after the '.doc'. If that 'tail' contains no additional periods, then the
above two will return the same items, but it's as a result of short-name
matching, not any special rule for a "-dot3" wildcard.

>
> That is not what I am seeing.
>
> Atleast, I think appending a period the end of your spec should
> signified there is no extension:
>
> dir *.doc. << period in the end
>
> or this:
>
> dir *doc. << no beginning period, with ending period
>
> This should ATLEAST tell Win32 that there is NO extension Yet, it
> continues as if there was. I can see why, because of the short file
> name.

Certain character combinations appear to be given special meaning in
wildcard specifications:

*.* is mapped to * - match anything, regardless of how many periods it
contains (even 0).

? matches any single character, or if at the end of the name or at a period,
casues all subsequent, consequetive ? to also match. (So foo??.bar will
match foo.bar, foo1.bar and foo2.bar).

.? will match a period followed by any character and will also match at end
of name (so foo.? will match foo and foo.1).

.* will match a period followed by any characteres, and will also match at
end of name (so foo.* will match foo and foo.1 and foo.bar).

*. will match all characters up to and including the last period in the
name. Names that contain no periods are treated as if they end with a
period (soo 'foo' and 'foo.' are the same file).

If none of the above patterns holds true, then * matches any sequence of
characters.

Any character other than . ? * matches only intself (possibly case
insensitively).

These rules are applied to both the long and short names - any file that
matches either name will be returned by FindFirstFileExW (and all the other
FindFile APIs).

>
> Anyway, Microsoft should moderning its logic to view a specification
> that is EXACT, atleast with a EX version of FindFirstFile(). Now I
> have to go on living that you can't TRUST what you program!! :-)

It is somewhat counter-intuitive. I think at the time it was written, it
probably did what people expected. Now that users are used to long file
names, with multiple periods, the DOS compatibility behaviors are somewhat
of a nuisance.

Since FindFirstFileExW takes a "flags" parameter, a flag to inhibit all the
special processing and simply treat *, ? and . in their most natural way
would be nice :-)

-cd

Hector Santos

unread,
Jul 31, 2003, 10:59:14 AM7/31/03
to
W"Carl Daniel [VC++ MVP]" <cpda...@nospam.mvps.org> wrote in message
news:O8zLn12V...@TK2MSFTNGP12.phx.gbl...

> Hector Santos wrote:
>
> > By the rules of Wildcard specification, the two specifications are
> > the same because anything after of the * is ignored, regardless of
> > what is exactually in storage. I can see why it doesn't work, but
> > even the KLUDGE is incorrect.
>
> That isn't true - it was for DOS, but not for NT.

What do you mean that? and what do you mean it was for dos, but not for NT?

Of course its true if a FILE*.EXP* produces a result that includes two files
with a short name specification having a 1 in the spec, then a FILE*1.EXP*
should produce the same two files. It does not.

It seems the kludge in the logic attempts to be "smarter" taken into account
the input specification but its broken.

> You can write a wildcard
> of foo*bar*baz and it will match only those files that contain foo, bar &
> baz substrings, in that order, with any intervening text.

Of course, that is something you expect. But by the same token, a FOO*
should produce thea bigger set of possible files, but all the same files
that foo*bar*baz will produce. That is not what I am seeing. For example:

d:\wc5beta>dir foo*
Volume in drive D is DRIVED
Volume Serial Number is FC76-DC90

Directory of d:\wc5beta

07/31/2003 12:01a 1,891 foo
07/11/2003 10:47p 2,335 foo1
07/31/2003 10:30a 13 foo123bar123baz1
07/11/2003 10:31p 2,335 foo2
07/11/2003 10:48p 2,331 foo3
07/18/2003 04:24a 16,384 foobar.exe
07/31/2003 10:30a 13 foobarbaz1
7 File(s) 25,302 bytes
0 Dir(s) 1,468,264,448 bytes free

d:\wc5beta>dir foo*bar*
Volume in drive D is DRIVED
Volume Serial Number is FC76-DC90

Directory of d:\wc5beta

07/31/2003 10:30a 13 foo123bar123baz1
07/18/2003 04:24a 16,384 foobar.exe
07/31/2003 10:30a 13 foobarbaz1
3 File(s) 16,410 bytes
0 Dir(s) 1,468,264,448 bytes free

d:\wc5beta>dir foo*bar*baz
Volume in drive D is DRIVED
Volume Serial Number is FC76-DC90

Directory of d:\wc5beta

File Not Found

Explain that?

To me, it is broken, its kludgy and Microsoft should fix it. All the
advanced technology MS is producing is all watered down with this minor, but
yet broken fundamental concept at the file system. You can't true the
results. Thats not cool. If I'm looking for *.DAT files in a queue, I
don't want *.DATAWhatHaveyou coming back. Sure, I can fix it myself with my
own file filter/masking. I'm not going to get bent of shape of this, but
it does TAKE away from the art of programming.

Incidently, if you look at MSDN, it seems Microsoft "started" to begin an
extended version with FindFirstFirstEx(), but they never finished it.

Hector Santos

unread,
Jul 31, 2003, 11:57:41 AM7/31/03
to
> I think Nick Ryan's reply is closer to the truth: the filesystem is
> searching both the short name and long-name spaces for matches.

Yep, so it seems. But even then, it seems to be inconsistent. It seems the
internal file masking is limited to 8.3 so a FOO* and FOO*BAR*BAZ do not
produce consistent results because of the second spec exceeds the 8.3 spec.

> You can turn off short-name support, although at the moment I don't recall
> how.

I seem to recall this somewhere too.

> IMO, MS should have short-name support turned off by default in the
> next version of Windows (I'd prefer if it was off by default in Windows
2000
> and XP, but oh well).

At a minimum, I think they should atleast relook at enhancing the file
masking logic to include more intelligence based on the provided input. A
simple extension to FindFirstFileEx() based on the file masking of the long
file name FIRST, and if not found, the short name should do the trick.

> >> If you type a wildcard spec with
> >> exactly three letters after a single period, it's treated as-if you'd
> >> appended * after it. As far as I can recall, NTFS has always
> >> behaved this way.
>
> This statement is wrong, although one might conclude that it's right by
some
> observed behaviors.

Yep. There is no consistency to it from the expected results standpoint.

> It is somewhat counter-intuitive. I think at the time it was written, it
> probably did what people expected. Now that users are used to long file
> names, with multiple periods, the DOS compatibility behaviors are somewhat
> of a nuisance.

I agree, and I include myself who was stuck in the 8.3 days for a long time
because of product support.

> Since FindFirstFileExW takes a "flags" parameter, a flag to inhibit all
the
> special processing and simply treat *, ? and . in their most natural way
> would be nice :-)

Now you are talking :-)

Slava M. Usov

unread,
Jul 31, 2003, 1:29:29 PM7/31/03
to
"Hector Santos" <em...@junk.com> wrote in message
news:uxk8By3V...@TK2MSFTNGP10.phx.gbl...

[...]

> > Since FindFirstFileExW takes a "flags" parameter, a flag to inhibit all
> > the special processing and simply treat *, ? and . in their most natural
> > way would be nice :-)
>
> Now you are talking :-)

You can get that if you use the underlying undocumented routine. You'll
essentially have to do filename matching yourself [the way you like it],
because the routine gives you the full directory listing.

S


Luc Kumps

unread,
Jul 31, 2003, 4:32:05 PM7/31/03
to

"Slava M. Usov" <stripit...@gmx.net> wrote in message
news:e06QPl4V...@TK2MSFTNGP12.phx.gbl...

See http://www.sysinternals.com/ntw2k/info/tips.shtml for a working example
with source code of the NtQueryDirectoryFile routine...
(of course you'll need to open a directory instead of \\.\Pipe in
CreateFile...)

Luc K


Alexander Grigoriev

unread,
Jul 31, 2003, 11:27:41 PM7/31/03
to
Well, if you use "*" pattern (as I do), you can get all the files with the
plain FindFile* routines. Then you can use your matching routine or
PathMatchSpec.

"Slava M. Usov" <stripit...@gmx.net> wrote in message
news:e06QPl4V...@TK2MSFTNGP12.phx.gbl...

Alexander Grigoriev

unread,
Jul 31, 2003, 11:31:26 PM7/31/03
to
Don't know what's wrong with your system, but this is what I get:

C:\DOCUME~1\alegr\LOCALS~1\Temp>dir FOO*BAR*BAZ
Volume in drive C is WD120
Volume Serial Number is FC35-66A0

Directory of C:\DOCUME~1\alegr\LOCALS~1\Temp

07/31/2003 08:28 PM 0 FOOBARBAZ
1 File(s) 0 bytes
0 Dir(s) 1,393,680,384 bytes free

Are you sure you use CMD.EXE as your command shell?

"Hector Santos" <em...@junk.com> wrote in message
news:uxk8By3V...@TK2MSFTNGP10.phx.gbl...

Hector Santos

unread,
Aug 1, 2003, 8:43:37 AM8/1/03
to
"Alexander Grigoriev" <al...@earthlink.net> wrote in message
news:O9kVm19V...@TK2MSFTNGP12.phx.gbl...

> Don't know what's wrong with your system, but this is what I get:
>
> C:\DOCUME~1\alegr\LOCALS~1\Temp>dir FOO*BAR*BAZ
> Volume in drive C is WD120
> Volume Serial Number is FC35-66A0
>
> Directory of C:\DOCUME~1\alegr\LOCALS~1\Temp
>
> 07/31/2003 08:28 PM 0 FOOBARBAZ
> 1 File(s) 0 bytes
> 0 Dir(s) 1,393,680,384 bytes free
>
> Are you sure you use CMD.EXE as your command shell?

As the proverbial saying goes, "Does a bear poop in the forest?" :-) It
was tested with the shell and and the Win32 API. Same result.

Rename that file to FOOBARBAZ1 and try again.

I renamed my file to FOOBARBAZ and it worked. But as you can see, it is
broken. :-)

Alexander Grigoriev

unread,
Aug 1, 2003, 10:16:37 AM8/1/03
to
I think we would all appreciate is someone from MS did document existing
behavior of FindFile API and any version differences (and PathMatchSpec,
too).

What I saw, for example, that OpenFile dialog also assumes * after the file
extension. If one specifies *.c filter, it would show *.c, *.cpp, etc.

"Hector Santos" <em...@junk.com> wrote in message

news:uPAdNqCW...@TK2MSFTNGP11.phx.gbl...

Carl Daniel [VC++ MVP]

unread,
Aug 1, 2003, 10:26:40 AM8/1/03
to
Alexander Grigoriev wrote:
> I think we would all appreciate is someone from MS did document
> existing behavior of FindFile API and any version differences (and
> PathMatchSpec, too).

Have you observed any behavior from FindFirstFile (and family) that's
inconsistent with my description a few messages up in this thread?

-cd


Hector Santos

unread,
Aug 1, 2003, 5:02:19 PM8/1/03
to

"Alexander Grigoriev" <al...@earthlink.net> wrote in message
news:%23ALJIeD...@TK2MSFTNGP12.phx.gbl...

> I think we would all appreciate is someone from MS did document existing
> behavior of FindFile API and any version differences (and PathMatchSpec,
> too).
>
> What I saw, for example, that OpenFile dialog also assumes * after the
file
> extension. If one specifies *.c filter, it would show *.c, *.cpp, etc.

Kind takes away the fun of programming, huh? :-)

0 new messages