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

FindFirstFile on a reparse point

212 views
Skip to first unread message

Gernot Frisch

unread,
Jul 13, 2010, 10:24:13 AM7/13/10
to
Hi,

when I try to do:
FindFirstFile(_T("C:\\Users\\gf\\Anwendungsdaten\\*.*", &fnd)
it returns NULL (Last error yields "access denied").

"C:\Users\gf\Anwendungsdaten" is a reparse point targeting "C:\Users\gf\Roaming".

OK, I can find the target and all. Fine.

BUT!!!
FindFirstFile(_T("C:\\Users\\gf\\Anwendungsdaten\\Adobe\\*.*", &fnd)

works perfeclty and it's no reparse point, although it is accessed trough such.

My code works flawlessly, but I'm a bit unsure if this behaviour is correct now.

Thank you for sheding light.

--
------------------------------------
Gernot Frisch
http://www.glbasic.com

Dee Earley

unread,
Jul 13, 2010, 11:24:55 AM7/13/10
to
On 13/07/2010 15:24, Gernot Frisch wrote:
> Hi,
>
> when I try to do:
> FindFirstFile(_T("C:\\Users\\gf\\Anwendungsdaten\\*.*", &fnd)
> it returns NULL (Last error yields "access denied").
>
> "C:\Users\gf\Anwendungsdaten" is a reparse point targeting
> "C:\Users\gf\Roaming".
>
> OK, I can find the target and all. Fine.
>
> BUT!!!
> FindFirstFile(_T("C:\\Users\\gf\\Anwendungsdaten\\Adobe\\*.*", &fnd)
>
> works perfeclty and it's no reparse point, although it is accessed
> trough such.
>
> My code works flawlessly, but I'm a bit unsure if this behaviour is
> correct now.
>
> Thank you for sheding light.

That is "correct" and the same way explorer behaves.
Access is denied to listing sub folders, but you can access those
subfolders by name for compatibility.

--
Dee Earley (dee.e...@icode.co.uk)
i-Catcher Development Team

iCode Systems

(Replies direct to my email address will be ignored.
Please reply to the group.)

Leo Davidson

unread,
Jul 13, 2010, 12:52:05 PM7/13/10
to
On Jul 13, 3:24 pm, "Gernot Frisch" <m...@privacy.net> wrote:

> when I try to do:
> FindFirstFile(_T("C:\\Users\\gf\\Anwendungsdaten\\*.*", &fnd)
> it returns NULL (Last error yields "access denied").
>
> "C:\Users\gf\Anwendungsdaten" is a reparse point targeting "C:\Users\gf\Roaming".


Those reparse points exist for compatibility with programs which use
hard-coded paths instead of asking the OS for the appropriate paths
via an API.

They deny access to listings at their top level on purpose in order to
block tools which don't know any better from recursing into them.
(e.g. A naive backup tool which does not understand reparse points may
store two copies of the same data, then later restore two separate
copies which then go out of sync with each other.)

The error you are seeing is not because of reparse points; it's
because of how those particular reparse points are permissioned. (It's
possible to create reparse points which don't deny list access to
their top level, just as it's possible to create normal folders which
deny access.)

If you want to find files in the user's AppData folder, you should ask
the OS for the correct path to it. (Even if you're not running as that
user, there is an API which you can give a username to and the OS will
return the correct path.)

On the other hand, if you need to be able to handle those legacy paths
(e.g. because they are passed to you by something else) and you know
that it makes sense to recurse into them, then you can detect that the
path given to you is a reparse points, lookup the path it points to
and then perform your operation on that path instead of the original.

Gernot Frisch

unread,
Jul 14, 2010, 3:33:54 AM7/14/10
to

>> "C:\Users\gf\Anwendungsdaten" is a reparse point targeting "C:\Users\gf\Roaming".

> you should ask the OS for the correct path to it.

The problem I had was with a self-written file explorer dialog. It displayed these legacy folders, but was unable to iterate
into them.
I think I'll leave the code as is now.


Ulrich Eckhardt

unread,
Jul 14, 2010, 6:38:28 AM7/14/10
to

For iterating, you have to use GetFileAttributes() anyway to distinguish
between directory and file, and there you also have a bit for reparse
points. The only thing you need to do is to read the reparse point's
content.

Uli


--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932

io_x

unread,
Jul 21, 2010, 4:44:58 AM7/21/10
to

"Gernot Frisch" <m...@privacy.net> ha scritto nel messaggio
news:8a3b85...@mid.individual.net...

> Hi,
>
> when I try to do:
> FindFirstFile(_T("C:\\Users\\gf\\Anwendungsdaten\\*.*", &fnd)
> it returns NULL (Last error yields "access denied").
>
> "C:\Users\gf\Anwendungsdaten" is a reparse point targeting
> "C:\Users\gf\Roaming".
>
> OK, I can find the target and all. Fine.
>
> BUT!!!
> FindFirstFile(_T("C:\\Users\\gf\\Anwendungsdaten\\Adobe\\*.*", &fnd)
>
> works perfeclty and it's no reparse point, although it is accessed trough
> such.
>
> My code works flawlessly, but I'm a bit unsure if this behaviour is correct
> now.
>
> Thank you for sheding light.

so in win32 what is the way for parse the content of one directory?
i have to call FindFirstFileA("C:\\Users\\gf\\Anwendungsdaten\\*.*", &fnd)
and that function return the sub-directory name too?

or can CreateFile(name of dirctory) return one handle that allow
to read the content of that directory?

thank you

Jackie

unread,
Jul 21, 2010, 5:44:42 AM7/21/10
to

I read somewhere before that you get "access denied" errors to prevent
going over the exact same files more than one time. These reparse points
allow access to sub-directories for backwards compatibility with older
applications which uses hardcoded paths.

"Determining Whether a Directory Is a Mounted Folder" on MSDN:
http://msdn.microsoft.com/en-us/library/aa363940(v=VS.85).aspx

--
Regards,
Jackie

Jackie

unread,
Jul 21, 2010, 5:48:54 AM7/21/10
to
Jackie wrote:
> "Determining Whether a Directory Is a Mounted Folder" on MSDN:
> http://msdn.microsoft.com/en-us/library/aa363940(v=VS.85).aspx
>

This is an article on mounted folders but reparse points are used to
implement mounted folders.

Some more on reparse points:
http://msdn.microsoft.com/en-us/library/aa365503(v=VS.85).aspx

--
Regards,
Jackie

io_x

unread,
Jul 22, 2010, 10:19:03 AM7/22/10
to

"io_x" <a...@b.c.invalid> ha scritto nel messaggio
news:4c46b11d$0$40287$4faf...@reader2.news.tin.it...

>
> "Gernot Frisch" <m...@privacy.net> ha scritto nel messaggio
> news:8a3b85...@mid.individual.net...
>> Hi,
>>
>> when I try to do:
>> FindFirstFile(_T("C:\\Users\\gf\\Anwendungsdaten\\*.*", &fnd)
>> it returns NULL (Last error yields "access denied").
>>
>> "C:\Users\gf\Anwendungsdaten" is a reparse point targeting
>> "C:\Users\gf\Roaming".
>>
>> OK, I can find the target and all. Fine.
>>
>> BUT!!!
>> FindFirstFile(_T("C:\\Users\\gf\\Anwendungsdaten\\Adobe\\*.*", &fnd)
>>
>> works perfeclty and it's no reparse point, although it is accessed trough
>> such.
>>
>> My code works flawlessly, but I'm a bit unsure if this behaviour is correct
>> now.
>>
>> Thank you for sheding light.
>
> so in win32 what is the way for parse the content of one directory?
> i have to call FindFirstFileA("C:\\Users\\gf\\Anwendungsdaten\\*.*", &fnd)
> and that function return the sub-directory name too?

yes FindFirstFileA(), FindNextFileA() FindClose()
as the example in the win32.hlp

WIN32_FIND_DATA FileData;
HANDLE hSearch;
DWORD dwAttrs;
char szDirPath[] = "c:\\TEXTRO\\";
char szNewPath[MAX_PATH];
char szHome[MAX_PATH];

BOOL fFinished = FALSE;

// Create a new directory.

if (!CreateDirectory(szDirPath, NULL))
{
ErrorHandler("Couldn't create new directory.");
}

// Start searching for .TXT files in the current directory.

hSearch = FindFirstFile("*.txt", &FileData);
if (hSearch == INVALID_HANDLE_VALUE)
{

ErrorHandler("No .TXT files found.");
}

// Copy each .TXT file to the new directory
// and change it to read only, if not already.

while (!fFinished)
{
lstrcpy(szNewPath, szDirPath);
lstrcat(szNewPath, FileData.cFileName);
if (CopyFile(FileData.cFileName, szNewPath, FALSE))
{
dwAttrs = GetFileAttributes(FileData.cFileName);
if (!(dwAttrs & FILE_ATTRIBUTE_READONLY))
{
SetFileAttributes(szNewPath,

dwAttrs | FILE_ATTRIBUTE_READONLY);
}
}
else
{
ErrorHandler("Couldn't copy file.");
}

if (!FindNextFile(hSearch, &FileData))
if (GetLastError() == ERROR_NO_MORE_FILES)
{
MessageBox(hwnd, "No more .TXT files.",
"Search completed.", MB_OK);
fFinished = TRUE;
}
else
{
ErrorHandler("Couldn't find next file.");

}
}

// Close the search handle.

if (!FindClose(hSearch))
{
ErrorHandler("Couldn't close search handle.");

0 new messages