Using FindFirst/FindNext to recurse directories in Vista/Windows 7? [Edit]

Having never been satisfied with commercial backup programs that stored backed up files in some proprietary format, I wrote my own years ago not long after Windows XP was released. As you would expect without some modifications it won't work properly on Windows Vista or Windows 7.

The problem that I'm having is that when recursing  the Documents directory I run into the new "My Music", "My Pictures" etc links/directories. Looking at the attribute information shows that it does have a Directory attribute but there is no actual directory "X:\Users\<user name>\Documents\My Music" directory and it is rather a link to "X:\Users\<user name>\My Music".

Is there some kind of extended file attributes that allow you to detect that it's not a standard directory? How would I determine the actual location is that it points to?

Thanks,

- Chris

Edited by: Chris LeFebvre on Apr 9, 2012 7:12 AM
0
Chris
4/9/2012 2:12:57 PM
embarcadero.delphi.win32 2183 articles. 0 followers. Follow

6 Replies
1350 Views

Similar Articles

[PageSpeed] 41

Chris wrote:

> The problem that I'm having is that when recursing  the Documents
> directory I run into the new "My Music", "My Pictures" etc
> links/directories. Looking at the attribute information shows that it
> does have a Directory attribute but there is no actual directory
> "X:\Users\<user name>\Documents\My Music" directory
> and it is rather a link to "X:\Users\<user name>\My Music".

They are called Junction Points, which are implemented using Reparse Points:

http://msdn.microsoft.com/en-us/library/windows/desktop/bb968829.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365503.aspx

> Is there some kind of extended file attributes that allow you to
> detect that it's not a standard directory?

FindFirst() and FindNext() do not expose everything in the TSearchRec record 
members.  You would have to use the TSearchRec.FindData member to access 
the low-level data returned by the Win32 API FindFirstFile() and FindNextFile() 
functions.  You can check the TSearchRec.FindData.dwFileAttributes field 
for the FILE_ATTRIBUTE_REPARSE_POINT flag.  If present, then the TSearchRec.FindData.dwReserved0 
field will contain the value of the Reparse Tag, which you will need in order 
to determine know to access the contents of the reparse point.

> How would I determine the actual location is that it points to?

Use DeviceIoControl() with the FSCTL_GET_REPARSE_POINT control code to read 
the data for the reparse point.

--
Remy Lebeau (TeamB)
0
Remy
4/9/2012 5:46:47 PM
Remy,

> FindFirst() and FindNext() do not expose everything in the TSearchRec record
> members.

Does IOUtils with TDirectory help?

-- 
Roman
0
Roman
4/10/2012 7:35:30 AM
Hi Remy:

Thanks for the information, this was really useful and I'm sure it'll solve the problem.

- Chris
0
Chris
4/10/2012 1:33:31 PM
Remy:

Doing some research I found that the JCL (which I already use for a number of things) has a unit JclNTFS which seems to contain some functions and procedures for handling reparse points. The function NTFSGetReparsePoint seems to be the appropriate function to use, it takes a file name and a record of type TReparseGuidDataBuffer. Looking in the Jcl source code the record layout for TReparseGuidDataBuffer is as follows:  
{code}
_REPARSE_GUID_DATA_BUFFER = record
    ReparseTag: DWORD;
    ReparseDataLength: WORD;
    Reserved: WORD;
    ReparseGuid: TGUID;
    GenericReparseBuffer: TGenericReparseBuffer;
  end;
{code}

I'm still at a loss as to how to get the location that the reparse point points to from the information contained in this record. Could you elaborate on this.

Thanks,

- Chris
0
Chris
4/11/2012 12:30:04 PM
Chris,

> I'm still at a loss as to how to get the location that the reparse point points to from the information contained in this record. Could you elaborate on this.

Here's our (non-JCL) code for reading symlink targets.  It returns the
path as stored in the junction point.  If you need the fully qualified
final target, XE2's SysUtils includes a FileGetSymLinkTarget function.
{code}
const
  // Reparse point tags
  IO_REPARSE_TAG_MOUNT_POINT = $A0000003;
  IO_REPARSE_TAG_SYMLINK = $A000000C;

type
  TReparsePathBuffer = array[0..16367] of Byte;

  TReparseType = (rtSymbolicLink, rtMountPoint, rtUnknown);

  REPARSE_DATA_BUFFER = packed record
    ReparseTag: Longword;
    ReparseDataLength: Word;
    Reserved: Word;
    SubstituteNameOffset: Word;
    SubstituteNameLength: Word;
    PrintNameOffset: Word;
    PrintNameLength: Word;
    case TReparseType of
      rtSymbolicLink:
        (Flags: Longword;
         SymLinkPathBuffer: TReparsePathBuffer);
      rtMountPoint:
        (MountPointPathBuffer: TReparsePathBuffer);
      rtUnknown:
        (DataBuffer: array[0..0] of Byte);
  end;

function SsGetReparseData(const AFilename: string;
  out ABuf: REPARSE_DATA_BUFFER; out ABytesRead: DWORD): Boolean;
var
  H: THandle;
begin
  Result := False;
  H := CreateFile(AFilename, 0, 0, nil, OPEN_EXISTING,
    FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OPEN_REPARSE_POINT, 0);
  if H = INVALID_HANDLE_VALUE then
    Exit;
  try
    Result := DeviceIoControl(H, FSCTL_GET_REPARSE_POINT, nil, 0, @ABuf,
      SizeOf(ABuf), ABytesRead, nil);
  finally
    CloseHandle(H);
  end;
end;

function SsGetSymLinkTarget(const AFilename: string): string;
var
  BytesRead: DWORD;
  Buf: REPARSE_DATA_BUFFER;
  PathBuf: ^TReparsePathBuffer;
begin
  { Read target path for NTFS symbolic links, directory symlinks, and
    junction points.  This is simpler than Delphi's FileGetSymLinkTarget
    because it isn't trying to resolve the link. }
  Result := '';
  if SsGetReparseData(AFilename, Buf, BytesRead) then
    if Buf.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT then
      PathBuf := @Buf.MountPointPathBuffer
    else if Buf.ReparseTag = IO_REPARSE_TAG_SYMLINK then
      PathBuf := @Buf.SymLinkPathBuffer
    else
      Exit
  else
    Exit;
  SetString(Result, PChar(@PathBuf[Buf.SubstituteNameOffset]),
    Buf.SubstituteNameLength div SizeOf(Char));
  { Junctions use the \??\ prefix instead of the usual \\?\ for
    non-parsed paths }
  if Copy(Result, 1, 4) = '\??\' then
    Delete(Result, 1, 4)
end;
{code}
-- 
Craig Peterson
Scooter Softawre

Edited by: Craig Peterson on Apr 11, 2012 8:16 AM
0
Craig
4/11/2012 3:17:05 PM
Hi Craig:

I got stuck on another project for a week or so but I just gave your code a try and it works great. 

Thanks so much for the help!

- Chris
0
Chris
4/25/2012 11:36:21 AM
Reply:

Similar Artilces:

Problem using Delphi 6 with Windows 7 [Edit]
I have had all kind of problems with Delphi 6 and Windows 7. For example, when I try to open a TStringList file over a network drive I get the following error message (MyList.LoadFromFile(s:\info\tables\table.doc);): "--------------------------- Debugger Exception Notification -------------------------------------------------------------------------------- Project Tools_CREG.exe raised exception class EFOpenError with message 'Cannot open file ...\table.doc'. Process stopped. Use Step or Run to continue. --------------------------------------------------------------...

Using Delphi 7 in Windows 7
I have recently upgraded my system to Windows 7. I have Delphi 7 working to some extent - it will open my projects and display my units and allow me to edit the code then compiles the *.exe file - BUT it will not display my forms. View/Forms - shows the list of forms and will open the associated unit but neither this nor F12 will display the form itself. Consequently I am unable to edit the form itself or its properties. Any ideas about what might be preventing these from displaying? > {quote:title=Ian BASIRE wrote:}{quote} > I have recently upgraded my system to Windows 7. I h...

Registry issues with Delphi Win32 app on Vista and Windows 7
Can anyone direct me to a reasonably explicit treatment of registry issues with Delphi Win32 app on Vista and Windows 7? -- Bill William Meyer wrote: > Can anyone direct me to a reasonably explicit treatment of registry > issues with Delphi Win32 app on Vista and Windows 7? What do you consider "registry issues"? The only one i'm aware of has existed on XP for limited user accounts as well: you cannot write to keys outside the HKEY_CURRENT_USER branch of the registry. That already affects the way you open a key: for keys outside the HKCU branch you have...

Delphi 7 won't start up anymore on Windows 7 (except in Windows safe mode) [Edit]
I'm using Delphi 7 PE under Windows 7 Home Edition. Since four days Delphi will not start anymore. When I start, I see an entry "delph32.exe" in the Windows Task Manager (process tab, not application tab) but this will disappear sillently after some seconds. No error or warning message is given. I tried several things already, after searching the internet for a solution: - start delphi in comptability mode - start delphi as administrator - give full right on the installation directory of delphi - disable UAC - restore windows to the previous restore point None of ...

Delphi 7 TFontDialog and Windows 7 [Edit]
When using the TFontDialog on a Windows 7 box, it will not list the device fonts (printer fonts). If I launch M$ Word on that same machine, Word will list them fine. This works fine on an XP box. Any ideas? Edited by: Tim Muenstermann on Apr 29, 2010 9:05 AM > {quote:title=Tim Muenstermann wrote:}{quote} > When using the TFontDialog on a Windows 7 box, it will not list the device fonts (printer fonts). If I launch M$ Word on that same machine, Word will list them fine. > What Word does (BTW, M$ went out about a decade ago) makes absolutely no difference. Office ...

Lock Time Out
A D7 BDE/Paradox application that has been problem free on a W2k platform has started throwing "Lock time out" errors having been moved to a Windows 7 platform. Multiple instances of a front end application run on workstations in a Windows Server 2008 R2 domain, with the database hosted on a shared folder on the server. The applications run OK interactively and only appear to raise the "Lock time out" error if left unattended overnight when all instances apepar to hit the same problem at some point. "Lock time out" is clearly a prevalent problem judging ...

Delphi 7 & Windows 7
win7 also have language problems. I used to fix the code below. But it did not work. I tried to indicate in the images. Thanks for your help. // initialization SetThreadLocale(LANG_TURKISH); GetFormatSettings; // [url=www.resimupload.com/ds144165673_screenhunter_01may.html][img=http://pic1.resimupload.com/r3/thumb_144165673.jpg[/url] [url=www.resimupload.com/ds116050513_screenhunter_02may.html][img=http://pic1.resimupload.com/r7/thumb_116050513.jpg[/url] [url=www.resimupload.com/ds501028062_screenhunter_03may.html][img=http://pic1.resimupload.com/r8/thumb_501028062.jpg[/url] ...

How to hide a window create using CreateProcess under Windows Vista/7 ?
Hi Guys, I hope somebody can help me with this matter. I spawned a child process using CreateProcess win api. The child process is successfully created but I want to run it silently....in hidden mode. I have research online for answers and I found that I should set some flags in the STARTINFO structure I have done this but I still can not get the window hide... I always get the window visible. My code snippet is as follow : STARTUPINFOW si; PROCESS_INFORMATION pi; memset(&si, 0, sizeof(si)); // Set up memory block memset(&pi, 0, sizeof(pi)); // Set up memory bloc...

Delphi 7 & Windows 7
win7 also have language problems. I used to fix the code below. But it did not work. I tried to indicate in the images. Thanks for your help. // initialization SetThreadLocale(LANG_TURKISH); GetFormatSettings; // http://www.resimupload.com/ds144165673_screenhunter_01may.html http://www.resimupload.com/ds116050513_screenhunter_02may.html http://www.resimupload.com/ds501028062_screenhunter_03may.html Edited by: Mesut Yaz�l�m User on May 14, 2010 3:26 AM I suspect the TDateTimePicker component was initialized before the launch of the code overriding the current date ant time. U...

Problem using InstallAware 7 CodeGear Special Edition with Delphi 2010 [Edit]
Hi Everyone, I am trying to create an installation disk for my delphi 2010 application using the installAware that kind of comes with Delphi 2010. When I try to built it, it keeps giving me the error message:- No files matching pattern "C:\Windows\system32\\*120.bpl" and when I look into my windows\system32 folder, there the files with extension *.bpl end with *140.bpl and not *120.bpl like it was expected. Can anyone tell me if I am doing something wrong or how I can get around this. Thanks in advance. Edited by: Tat Hon Chu on Dec 3, 2009 12:55 AM > {quo...

Will Windows 7 install over Windows 7 Trial Edition
A couple new systems were shipped with Windows 7 Trial Edition, timebombed to stop working after so many months Can a retail version of Windows 7 be installed over the Trial Edition ? "mgwmp" <p.zie@cnn.com> wrote in message news:ha4jid$2lmg$1@news.grc.com... >A couple new systems were shipped with Windows 7 Trial Edition, timebombed >to stop working after so many months > > Can a retail version of Windows 7 be installed over the Trial Edition ? > It depends on which "trial edition." If it was the RTM, then this is identical to th...

ANN: The free to use kbmMW 3.51.00 CodeGear Edition and kbmMemTable v. 7.00.01 Beta 1 CodeGear Edition for Delphi XE, has been released!
We are happy to announce the immediate availability of the free to use kbmMW v. 3.51.00 CodeGear Edition and kbmMemTable v. 7.00.01 CodeGear Edition for Delphi XE! The keywords for this release are: - Delphi XE support - Highly optimized performance in master/detail and ranges in kbmMemTable. - New GroupBy function in kbmMemTable. - Improved support for fielddefinitions with data, even in master/detail relations - Performance enhancements - Multithreading enhancements - Dataset enhancements - Stability enhancements and bugfixes Remember the free kbmMemTable CodeGear Edition ...

I wrote an application and used cracked delphi 7, after i bought delphi 7
I wrote an application and used cracked delphi 7, I sold it, after i bought delphi 7 and recompiled application, is now my application legal or? > {quote:title=Ivan Ivanov wrote:}{quote} > I wrote an application and used cracked delphi 7, I sold it, after i bought delphi 7 and recompiled application, is now my application legal or? "I embezzled some money from my employer, returned the funds, and then got it back as a bonus. Can I still be arrested?" Uhhh .... didn't you just confess to a crime? > {quote:title=Ivan Ivanov wrote:}{quote} > I wrote an appli...

Windows 7 ... Delphi 7
The new Windows 7 reminds me very strong of Delphi 7 ... a good feeling! > {quote:title=Ralf Stocker wrote:}{quote} > The new Windows 7 reminds me very strong of Delphi 7 ... a good feeling! Me too, from what I've heard so far. They are releasing it as a public beta tommorrow (the first 2.5 million in line only): Windows 7 page http://www.microsoft.com/windows/windows-7/ Information on Downloading and Installing Windows 7 Beta http://windowsteamblog.com/blogs/windows7/archive/2009/01/07/information-on-downloading-and-installing-windows-7-beta.aspx How to Get in on th...

Web resources about - Using FindFirst/FindNext to recurse directories in Vista/Windows 7? [Edit] - embarcadero.delphi.win32

Resources last updated: 11/22/2015 7:53:13 PM