Discussion:
A very simple question: How to check if a path spec is pointing at a file ?
(too old to reply)
R.Wieser
2017-09-14 12:29:06 UTC
Permalink
Hello all,

As in the subject line, a rather very simple question: How to I check if a
path spec is pointing at a file ?

PathFileExists doesn't cut it, as it not only returns true for folders, but
also devices like PRN, COM1 and alike.

GetFileAttributes doesn't work either, as it does not return any difference
between files and devices.

SHFileExists (exported by ordinal only) appears to be problematic, as I
could not entice it to return anything else than False ...

Anything other I can try ? Preferrably something that is based on
detecting if its a file, as opposed to trying to exclude everything else ...

Regards,
Rudy Wieser
Auric__
2017-09-14 16:44:58 UTC
Permalink
Post by R.Wieser
Hello all,
As in the subject line, a rather very simple question: How to I check if a
path spec is pointing at a file ?
PathFileExists doesn't cut it, as it not only returns true for folders, but
also devices like PRN, COM1 and alike.
GetFileAttributes doesn't work either, as it does not return any difference
between files and devices.
SHFileExists (exported by ordinal only) appears to be problematic, as I
could not entice it to return anything else than False ...
Anything other I can try ? Preferrably something that is based on
detecting if its a file, as opposed to trying to exclude everything else...
Unfortunately, eliminating non-files really does seem to me the easiest way
to do it: GetFileAttributes(file), then check it against the non-file
attributes on this page:

https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117.aspx

If you can eliminate everything else, it's a file.
--
I can't read minds. Trust me, if I could, would I be working here?
R.Wieser
2017-09-14 17:00:07 UTC
Permalink
Auric,
Post by Auric__
Unfortunately, eliminating non-files really does seem to me the easiest
way to do it: GetFileAttributes(file), then check it against the non-file
attributes
Not really. On my system (XP) GetFileAttributes(file) returns 0x20 when I
feed it, for example, the name "prn". And as thats the "archive" bit, its
not helpfull at all. :-(

Also, eliminating everything stands a good chance of causing me to get
bitten in the behind, as only one forgotten something (or some
non-documented behaviour) will cause such an approach to return a true when
it *should* have returned a false ...

But yes, if I can't find a method to do a "is it a file?" check than I will
(be forced to) do it by elimination.

And did I already mention pipes ? :-)

Regards,
Rudy Wieser
Post by Auric__
Post by R.Wieser
Hello all,
As in the subject line, a rather very simple question: How to I check if a
path spec is pointing at a file ?
PathFileExists doesn't cut it, as it not only returns true for folders, but
also devices like PRN, COM1 and alike.
GetFileAttributes doesn't work either, as it does not return any difference
between files and devices.
SHFileExists (exported by ordinal only) appears to be problematic, as I
could not entice it to return anything else than False ...
Anything other I can try ? Preferrably something that is based on
detecting if its a file, as opposed to trying to exclude everything else...
Unfortunately, eliminating non-files really does seem to me the easiest way
to do it: GetFileAttributes(file), then check it against the non-file
https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117.aspx
If you can eliminate everything else, it's a file.
--
I can't read minds. Trust me, if I could, would I be working here?
Auric__
2017-09-14 19:25:51 UTC
Permalink
Post by R.Wieser
Auric,
Post by Auric__
Unfortunately, eliminating non-files really does seem to me the easiest
way to do it: GetFileAttributes(file), then check it against the
non-file attributes
Not really. On my system (XP) GetFileAttributes(file) returns 0x20 when
I feed it, for example, the name "prn". And as thats the "archive"
bit, its not helpfull at all. :-(
So keep an internal list of DOS devices (PRN, COM[1..n], LPT[1..n], NUL,
maybe some others I forgot) and check against that before calling
GetFileAttributes. If it's in that list, you know that it's not a file.
Post by R.Wieser
Also, eliminating everything stands a good chance of causing me to get
bitten in the behind, as only one forgotten something (or some
non-documented behaviour) will cause such an approach to return a true
when it *should* have returned a false ...
But yes, if I can't find a method to do a "is it a file?" check than I
will (be forced to) do it by elimination.
And did I already mention pipes ? :-)
Here's some code from stackoverflow that might do what you want:

struct stat s;
if( stat(path,&s) == 0 )
{
if( s.st_mode & S_IFDIR )
{
//it's a directory
}
else if( s.st_mode & S_IFREG )
{
//it's a file
}
else
{
//something else
}
}
else
{
//error
}

...but I don't know nearly enough about C to say how well that would work.
You could also try googling something like "windows isfile" (without
quotes). Add "-python -java" to the search to eliminate those languages
(which fill the first few pages of results for me) unless you're using one
of those.
--
- And knowing is half the battle!
- Then what's the other half?
Kaz Kylheku
2017-09-14 20:01:40 UTC
Permalink
Post by Auric__
Post by R.Wieser
Auric,
Post by Auric__
Unfortunately, eliminating non-files really does seem to me the easiest
way to do it: GetFileAttributes(file), then check it against the
non-file attributes
Not really. On my system (XP) GetFileAttributes(file) returns 0x20 when
I feed it, for example, the name "prn". And as thats the "archive"
bit, its not helpfull at all. :-(
So keep an internal list of DOS devices (PRN, COM[1..n], LPT[1..n], NUL,
maybe some others I forgot) and check against that before calling
GetFileAttributes. If it's in that list, you know that it's not a file.
Windows 13 is going to double the numnber of special entries in
that list just to spite you for having touched an iPhone once.
R.Wieser
2017-09-15 08:29:43 UTC
Permalink
Auric,
Post by Auric__
So keep an internal list of DOS devices (PRN, COM[1..n], LPT[1..n],
NUL, maybe some others I forgot) and check against that before calling
GetFileAttributes.
Thats exactly what I'm trying *not* to do. Its too easy to have something
slip thru the cracks that way. :-(
Post by Auric__
struct stat s;
if( stat(path,&s) == 0 )
Do you (still) have a link to that stackoverflow page ? You see, I do not
program C{anything} either, and have absolutily no idea what that "stat"
function translates to in regard to standard Windows API calls. But maybe I
can glean that from the other info on that page ...
Post by Auric__
You could also try googling something like "windows isfile" (without
quotes)
:-D You do not want to know how many keyword combinations I already tried,
and how much time I spend on it. I would not be surprised if it already
added up to more than half a day (4 hours).

By the way: SHGetFileInfo (shell32) looks to be promising for checking an
existing file (read mode): It at least fails when a device is fed to it. I
still have to see what it does with a pipe though, and have no real idea how
to use it for a file I've yet have to create (write mode)

Regards,
Rudy Wieser
Post by Auric__
Post by R.Wieser
Auric,
Post by Auric__
Unfortunately, eliminating non-files really does seem to me the easiest
way to do it: GetFileAttributes(file), then check it against the
non-file attributes
Not really. On my system (XP) GetFileAttributes(file) returns 0x20 when
I feed it, for example, the name "prn". And as thats the "archive"
bit, its not helpfull at all. :-(
So keep an internal list of DOS devices (PRN, COM[1..n], LPT[1..n], NUL,
maybe some others I forgot) and check against that before calling
GetFileAttributes. If it's in that list, you know that it's not a file.
Post by R.Wieser
Also, eliminating everything stands a good chance of causing me to get
bitten in the behind, as only one forgotten something (or some
non-documented behaviour) will cause such an approach to return a true
when it *should* have returned a false ...
But yes, if I can't find a method to do a "is it a file?" check than I
will (be forced to) do it by elimination.
And did I already mention pipes ? :-)
struct stat s;
if( stat(path,&s) == 0 )
{
if( s.st_mode & S_IFDIR )
{
//it's a directory
}
else if( s.st_mode & S_IFREG )
{
//it's a file
}
else
{
//something else
}
}
else
{
//error
}
...but I don't know nearly enough about C to say how well that would work.
You could also try googling something like "windows isfile" (without
quotes). Add "-python -java" to the search to eliminate those languages
(which fill the first few pages of results for me) unless you're using one
of those.
--
- And knowing is half the battle!
- Then what's the other half?
Ant
2017-09-15 10:37:55 UTC
Permalink
Post by R.Wieser
Auric,
Post by Auric__
So keep an internal list of DOS devices (PRN, COM[1..n], LPT[1..n],
NUL, maybe some others I forgot) and check against that before calling
GetFileAttributes.
Thats exactly what I'm trying *not* to do. Its too easy to have something
slip thru the cracks that way. :-(
I don't know but QueryDosDevice may help in this case.
Post by R.Wieser
Post by Auric__
struct stat s;
if( stat(path,&s) == 0 )
Do you (still) have a link to that stackoverflow page ? You see, I do not
program C{anything} either, and have absolutily no idea what that "stat"
function translates to in regard to standard Windows API calls.
It's unix specific. Implemented on Windows as _stat and exported by
msvcrt.dll (MS Visual C++ Runtime Library). internally it calls
FindFirstFile and GetDriveType.

See if you have any luck with these:
FindFirstFile, FindFirstFileEx, GetDriveType, SearchPath.
R.Wieser
2017-09-15 11:08:32 UTC
Permalink
Hey Ant,
Post by Ant
I don't know but QueryDosDevice may help in this case.
I was also considering it, but as a last/later resort. As I would like to
make the test as generic as possible (thinking of something like files on a
network share here).
Post by Ant
It's unix specific. Implemented on Windows as _stat and exported by
msvcrt.dll (MS Visual C++ Runtime Library). internally it calls
FindFirstFile and GetDriveType.
Ah, thataway. Well, I'll see if I can find it, and maybe even disassemble
it to see how it uses those two functions.
Post by Ant
FindFirstFile, FindFirstFileEx, GetDriveType, SearchPath.
I already tried the first, but it returned a valid result on a device (like
"prn"). And although every field but the name was Zero, I'm not at all
sure if this is a described (read: dependable upon) situation. I'll take
as look at the other ones.


But after I wrote to Uwe that I would get into a chatch-22 with his
GetFileType suggestion I remembered that its possible to "open" a file for
meta-data access only, simply by not specifying an access mode (keeping it
zero). The result looks very promising, as I think it can be used for both
reading as well as writing mode (in the first case it should return a
disk-based type, in the second case either that or a "can't open" status).

Thanks for your help (all of you).

Regards,
Rudy Wieser
Post by Ant
Post by R.Wieser
Auric,
Post by Auric__
So keep an internal list of DOS devices (PRN, COM[1..n], LPT[1..n],
NUL, maybe some others I forgot) and check against that before calling
GetFileAttributes.
Thats exactly what I'm trying *not* to do. Its too easy to have something
slip thru the cracks that way. :-(
I don't know but QueryDosDevice may help in this case.
Post by R.Wieser
Post by Auric__
struct stat s;
if( stat(path,&s) == 0 )
Do you (still) have a link to that stackoverflow page ? You see, I do not
program C{anything} either, and have absolutily no idea what that "stat"
function translates to in regard to standard Windows API calls.
It's unix specific. Implemented on Windows as _stat and exported by
msvcrt.dll (MS Visual C++ Runtime Library). internally it calls
FindFirstFile and GetDriveType.
FindFirstFile, FindFirstFileEx, GetDriveType, SearchPath.
Ant
2017-09-14 16:50:04 UTC
Permalink
Post by R.Wieser
As in the subject line, a rather very simple question: How to I check if a
path spec is pointing at a file ?
PathFileExists doesn't cut it, as it not only returns true for folders, but
also devices like PRN, COM1 and alike.
GetFileAttributes doesn't work either, as it does not return any difference
between files and devices.
SHFileExists (exported by ordinal only) appears to be problematic, as I
could not entice it to return anything else than False ...
Anything other I can try ? Preferrably something that is based on
detecting if its a file, as opposed to trying to exclude everything else ...
How about CreateFile (read only and OPEN_EXISTING)?
R.Wieser
2017-09-14 17:09:00 UTC
Permalink
Ant,
Post by Ant
How about CreateFile (read only and OPEN_EXISTING)?
*I thought about the same thing, but as I happen to know you can even open a
disk partition that way (for raw access) there is a good chance that it will
be able to open *lots* of things, besides regular disk files.

I Just tried it on "c:\prn", and its gets opened :-\ It will most likely
do the same for named pipes ....

Did I already say it was an easy question ? :-D

Regards,
Rudy Wieser
Post by Ant
Post by R.Wieser
As in the subject line, a rather very simple question: How to I check if a
path spec is pointing at a file ?
PathFileExists doesn't cut it, as it not only returns true for folders, but
also devices like PRN, COM1 and alike.
GetFileAttributes doesn't work either, as it does not return any difference
between files and devices.
SHFileExists (exported by ordinal only) appears to be problematic, as I
could not entice it to return anything else than False ...
Anything other I can try ? Preferrably something that is based on
detecting if its a file, as opposed to trying to exclude everything else ...
How about CreateFile (read only and OPEN_EXISTING)?
Uwe Sieber
2017-09-15 07:11:54 UTC
Permalink
GetFileType returns FILE_TYPE_DISK for files and
storage devices. GetFileAttributes fails on storage
devices.

Uwe
Post by R.Wieser
Hello all,
As in the subject line, a rather very simple question: How to I check if a
path spec is pointing at a file ?
PathFileExists doesn't cut it, as it not only returns true for folders, but
also devices like PRN, COM1 and alike.
GetFileAttributes doesn't work either, as it does not return any difference
between files and devices.
SHFileExists (exported by ordinal only) appears to be problematic, as I
could not entice it to return anything else than False ...
Anything other I can try ? Preferrably something that is based on
detecting if its a file, as opposed to trying to exclude everything else ...
Regards,
Rudy Wieser
R.Wieser
2017-09-15 08:33:28 UTC
Permalink
Uwe,
Post by Uwe Sieber
GetFileType returns FILE_TYPE_DISK for files and
storage devices.
Thanks for that hint. :-)
Post by Uwe Sieber
GetFileAttributes fails on storage devices.
Its not what it fails on that worries me, but what it *doesn't* fail on
(false positives) ...

Regards,
Rudy Wieser
Post by Uwe Sieber
GetFileType returns FILE_TYPE_DISK for files and
storage devices. GetFileAttributes fails on storage
devices.
Uwe
Post by R.Wieser
Hello all,
As in the subject line, a rather very simple question: How to I check if
a path spec is pointing at a file ?
PathFileExists doesn't cut it, as it not only returns true for folders,
but also devices like PRN, COM1 and alike.
GetFileAttributes doesn't work either, as it does not return any
difference between files and devices.
SHFileExists (exported by ordinal only) appears to be problematic, as I
could not entice it to return anything else than False ...
Anything other I can try ? Preferrably something that is based on
detecting if its a file, as opposed to trying to exclude everything else ...
Regards,
Rudy Wieser
R.Wieser
2017-09-15 08:48:54 UTC
Permalink
Uwe,
Post by R.Wieser
Post by Uwe Sieber
GetFileType returns FILE_TYPE_DISK for files and
storage devices.
Thanks for that hint. :-)
Blast! To be able to use that function I first need to open that file
before I can check if I should actually be opening that file ... A bit of a
catch22 :-)

Regards,
Rudy Wieser
R.Wieser
2017-09-15 11:05:16 UTC
Permalink
Post by R.Wieser
Blast! To be able to use that function I first need to open that file
before I can check if I should actually be opening that file ... A bit of
a catch22 :-)
Scratch that. I just remembered its possible to open a file for meta-data
acces only, simply by not specifying an access mode. :-)

So Uwe, thanks. It looks like using that one might be the simpelest
solution.

Regards,
Rudy Wieser.
Christian Astor
2017-09-15 10:28:04 UTC
Permalink
Post by R.Wieser
Hello all,
As in the subject line, a rather very simple question: How to I check if a path spec is pointing at a file ?
For example (tested on Windows 10, should not work on OS < Vista) :

typedef BOOL(__stdcall *PIFP)(LPCWSTR lpszPath);
PIFP PathIsFilePath;
HMODULE hdll = LoadLibrary(L"IEFrame.dll");
PathIsFilePath = (PIFP)GetProcAddress(hdll, (LPCSTR)MAKEINTRESOURCE(137));
WCHAR wsFile[MAX_PATH] = L"C:\\test.jpg";
if (PathIsFilePath != NULL)
{
BOOL bReturn = PathIsFilePath(wsFile) && PathFileExists(wsFile);
//...
}
R.Wieser
2017-09-16 12:49:10 UTC
Permalink
Christian,

My apologies for the late reply. I read you reply, but somehow I forgot to
asnwer it. :-\
Post by Christian Astor
HMODULE hdll = LoadLibrary(L"IEFrame.dll");
Alas, XP does not seem to have that (or something like it) DLL
Post by Christian Astor
BOOL bReturn = PathIsFilePath(wsFile) && PathFileExists(wsFile);
PathFileExists is present in shlwapi.dll, and returns a true on a device
(not tested on a pipe).

PathIsFileSpec, the closest I could find (also in shlwapi) only cares about
the string, not the actual file. Moreover, it only looks at if the filename
(or anything else!) is prefixed by a path or driveletter (contains a ":" or
"\" somewhere).

In short, not really usable. :-\

Regards,
Rudy Wieser
Post by Christian Astor
Post by R.Wieser
Hello all,
As in the subject line, a rather very simple question: How to I check if
a path spec is pointing at a file ?
typedef BOOL(__stdcall *PIFP)(LPCWSTR lpszPath);
PIFP PathIsFilePath; HMODULE hdll = LoadLibrary(L"IEFrame.dll");
PathIsFilePath = (PIFP)GetProcAddress(hdll, (LPCSTR)MAKEINTRESOURCE(137));
WCHAR wsFile[MAX_PATH] = L"C:\\test.jpg"; if (PathIsFilePath != NULL)
{
BOOL bReturn = PathIsFilePath(wsFile) && PathFileExists(wsFile);
//...
}
Christian Astor
2017-09-17 08:51:49 UTC
Permalink
Post by R.Wieser
Post by Christian Astor
HMODULE hdll = LoadLibrary(L"IEFrame.dll");
Alas, XP does not seem to have that (or something like it) DLL
Post by Christian Astor
BOOL bReturn = PathIsFilePath(wsFile) && PathFileExists(wsFile);
PathFileExists is present in shlwapi.dll, and returns a true on a device
(not tested on a pipe).
Yes, as I said, this only works on OS >= Vista (but XP is no supported
anymore by MS, even Vista since april 2017)
PathFileExists() is only useful if PathIsFilePath() returns TRUE

Loading...