Gelöst! Wie "echte Verzeichnisse" von "Links" unterscheiden?
Gelöst! Wie "echte Verzeichnisse" von "Links" unterscheiden?
Guude Morsche aus Hessen!
Folgendes Problem:ExplorerTreeGadget zeigt u. a. im User-Verzeichnis das Verzeichnis "Startmenü" an. Mit ExamineDirectory finde ich darin keine Einträge. Meine laienhafte Vermutung: Richtig so, denn das ist gar kein Verzeichnis, sondern ein Link zu einem Verzeichnis, nämlich User\Appdata\Microsoft\usw. Leider zeigt aber auch Filesize mit "-2", dass das ein Verzeichnis ist.
Kann man mit Purebasic "echte Verzeichnisse" von "Link auf Verzeichnis" unterscheiden und wenn ja, wie findet man das Zielverzeichnis?
Nachtrag: Auf DOS-Ebene geht das mit "dir /al" - irgendwie muss es also gehen.
Folgendes Problem:ExplorerTreeGadget zeigt u. a. im User-Verzeichnis das Verzeichnis "Startmenü" an. Mit ExamineDirectory finde ich darin keine Einträge. Meine laienhafte Vermutung: Richtig so, denn das ist gar kein Verzeichnis, sondern ein Link zu einem Verzeichnis, nämlich User\Appdata\Microsoft\usw. Leider zeigt aber auch Filesize mit "-2", dass das ein Verzeichnis ist.
Kann man mit Purebasic "echte Verzeichnisse" von "Link auf Verzeichnis" unterscheiden und wenn ja, wie findet man das Zielverzeichnis?
Nachtrag: Auf DOS-Ebene geht das mit "dir /al" - irgendwie muss es also gehen.
Zuletzt geändert von EmmJott am 15.05.2025 16:55, insgesamt 1-mal geändert.
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?
das sind dann die sogenannten "Systemverzeichnisse"... es gibt hier im Forum diverse Möglichkeiten die richtigen Pfade zu ermitteln... wie z.B. im englischen Forum https://www.purebasic.fr/english/viewtopic.php?t=82092 weiter unten von Jan2004 oder das was ich grad nicht wiederfinde was TassyJim dort meint.
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom
Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?
Hi,
vielen Dank für den Hinweis! Ja, das geht wohl in diese Richtung. Schaue mir gerade das hier an:
https://www.purebasic.fr/english/viewto ... 70#p604570
Das würde schon mal meine 2. Frage beantworten, nämlich die nach dem Zielverzeichnis. Habe aber noch das Problem: Wie unterscheide ich ein "echtes Verzeichnis" (mir fehlt der Fachbegriff) von einem Link, für den das Zielverzeichnis erst noch ermittelt werden muss (mittels Code von Jan2004).
vielen Dank für den Hinweis! Ja, das geht wohl in diese Richtung. Schaue mir gerade das hier an:
https://www.purebasic.fr/english/viewto ... 70#p604570
Das würde schon mal meine 2. Frage beantworten, nämlich die nach dem Zielverzeichnis. Habe aber noch das Problem: Wie unterscheide ich ein "echtes Verzeichnis" (mir fehlt der Fachbegriff) von einem Link, für den das Zielverzeichnis erst noch ermittelt werden muss (mittels Code von Jan2004).
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?
Ich wüsste nicht, dass es dafür eine Möglichkeit gibt, es per Programm zu "erkennen".EmmJott hat geschrieben: 14.05.2025 22:09 ... Habe aber noch das Problem: Wie unterscheide ich ein "echtes Verzeichnis" (mir fehlt der Fachbegriff) von einem Link, für den das Zielverzeichnis erst noch ermittelt werden muss (mittels Code von Jan2004).
Die Frage hat sich mir nie gestellt, eher die Frage, wie krieg ich den Pfad raus...
Im Grunde kannst du davon ausgehen, das ALLES, was von Windows kommt, mit solchen "relativen" Pfaden arbeitet,
Window kann ja schliesslich auf jedem Laufwerk installiert werden... nicht nur C:
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom
Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?
Bin da ja vielleicht auf dem Holzweg, habe aber mal mit den Konstanten aus
https://learn.microsoft.com/de-de/windo ... -constants
rumgespielt.
Bei den Verzeichnissen, die offenbar nur Symlinks sind und auf ein Zielverzeichnis verweisen, tauchen die Attribute
#FILE_ATTRIBUTE_REPARSE_POINT und #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED auf. Hiermit ermittelt:
Meine Frage: Bin ich da komplett auf der falschen Fährte oder kann jemand bestätigen, dass mit #FILE_ATTRIBUTE_REPARSE_POINT und / oder #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED ein Symlink sicher erkannt und eine Unterscheidung zu einem "echten " Verzeichnis sicher funktioniert? Reicht eines der beiden Attribute (welches?) oder müssen beide vorhanden sein?
https://learn.microsoft.com/de-de/windo ... -constants
rumgespielt.
Bei den Verzeichnissen, die offenbar nur Symlinks sind und auf ein Zielverzeichnis verweisen, tauchen die Attribute
#FILE_ATTRIBUTE_REPARSE_POINT und #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED auf. Hiermit ermittelt:
Code: Alles auswählen
Enumeration
#parent
#parentstatusbar
#parentmenu
#parentfont_1
#escape
#etg
EndEnumeration
;- Konstanten
#FILE_ATTRIBUTE_READONLY = $00000001 ;#PB_FileSystem_ReadOnly
#FILE_ATTRIBUTE_HIDDEN = $00000002 ;#PB_FileSystem_Hidden
#FILE_ATTRIBUTE_SYSTEM = $00000004 ;#PB_FileSystem_System
#FILE_ATTRIBUTE_DIRECTORY = $00000010
#FILE_ATTRIBUTE_ARCHIVE = $00000020 ;#PB_FileSystem_Archive
#FILE_ATTRIBUTE_DEVICE = $00000040
#FILE_ATTRIBUTE_NORMAL = $00000080 ;#PB_FileSystem_Normal
#FILE_ATTRIBUTE_TEMPORARY = $00000100
#FILE_ATTRIBUTE_SPARSE_FILE = $00000200
#FILE_ATTRIBUTE_REPARSE_POINT = $00000400
#FILE_ATTRIBUTE_COMPRESSED = $00000800 ;#PB_FileSystem_Compressed
#FILE_ATTRIBUTE_OFFLINE = $00001000
#FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = $00002000
#FILE_ATTRIBUTE_ENCRYPTED = $00004000
#FILE_ATTRIBUTE_INTEGRITY_STREAM = $00008000
#FILE_ATTRIBUTE_VIRTUAL = $00010000
#FILE_ATTRIBUTE_NO_SCRUB_DATA = $00020000
#FILE_ATTRIBUTE_EA = $00040000
#FILE_ATTRIBUTE_RECALL_ON_OPEN = $00040000 ;gleicher Wert wie #FILE_ATTRIBUTE_EA ?
#FILE_ATTRIBUTE_PINNED = $00080000
#FILE_ATTRIBUTE_UNPINNED = $00100000
#FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = $00400000
Procedure checkDirAttr(dir$)
Value = GetFileAttributes(dir$)
Debug dir$
If Value = -1
Debug "Fehler beim Lesen der Attribute!"
Else
If Value & #FILE_ATTRIBUTE_READONLY : Debug "#FILE_ATTRIBUTE_READONLY" : EndIf
If Value & #FILE_ATTRIBUTE_HIDDEN : Debug "#FILE_ATTRIBUTE_HIDDEN" : EndIf
If Value & #FILE_ATTRIBUTE_SYSTEM : Debug "#FILE_ATTRIBUTE_SYSTEM" : EndIf
If Value & #FILE_ATTRIBUTE_DIRECTORY : Debug "#FILE_ATTRIBUTE_DIRECTORY" : EndIf
If Value & #FILE_ATTRIBUTE_ARCHIVE : Debug "#FILE_ATTRIBUTE_ARCHIVE" : EndIf
If Value & #FILE_ATTRIBUTE_DEVICE : Debug "#FILE_ATTRIBUTE_DEVICE" : EndIf
If Value & #FILE_ATTRIBUTE_NORMAL : Debug "#FILE_ATTRIBUTE_NORMAL" : EndIf
If Value & #FILE_ATTRIBUTE_TEMPORARY : Debug "#FILE_ATTRIBUTE_TEMPORARY" : EndIf
If Value & #FILE_ATTRIBUTE_SPARSE_FILE : Debug "#FILE_ATTRIBUTE_SPARSE_FILE" : EndIf
If Value & #FILE_ATTRIBUTE_REPARSE_POINT : Debug "#FILE_ATTRIBUTE_REPARSE_POINT" : EndIf
If Value & #FILE_ATTRIBUTE_COMPRESSED : Debug "#FILE_ATTRIBUTE_COMPRESSED" : EndIf
If Value & #FILE_ATTRIBUTE_OFFLINE : Debug "#FILE_ATTRIBUTE_OFFLINE" : EndIf
If Value & #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED : Debug "#FILE_ATTRIBUTE_NOT_CONTENT_INDEXED" : EndIf
If Value & #FILE_ATTRIBUTE_ENCRYPTED : Debug "#FILE_ATTRIBUTE_ENCRYPTED" : EndIf
If Value & #FILE_ATTRIBUTE_INTEGRITY_STREAM : Debug "#FILE_ATTRIBUTE_INTEGRITY_STREAM" : EndIf
If Value & #FILE_ATTRIBUTE_VIRTUAL : Debug "#FILE_ATTRIBUTE_VIRTUAL" : EndIf
If Value & #FILE_ATTRIBUTE_NO_SCRUB_DATA : Debug "#FILE_ATTRIBUTE_NO_SCRUB_DATA" : EndIf
If Value & #FILE_ATTRIBUTE_EA : Debug "#FILE_ATTRIBUTE_EA" : EndIf
If Value & #FILE_ATTRIBUTE_RECALL_ON_OPEN : Debug "#FILE_ATTRIBUTE_RECALL_ON_OPEN" : EndIf
If Value & #FILE_ATTRIBUTE_PINNED : Debug "#FILE_ATTRIBUTE_PINNED" : EndIf
If Value & #FILE_ATTRIBUTE_UNPINNED : Debug "#FILE_ATTRIBUTE_UNPINNED" : EndIf
If Value & #FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS : Debug "#FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS" : EndIf
EndIf
Debug "----------------------"
Debug " "
; Werte aus: https://learn.microsoft.com/de-de/windows/win32/fileio/file-attribute-constants
EndProcedure
;GetParentWinMetrics
Global winwidth, winheight
Procedure GetParentWinMetrics()
winwidth = WindowWidth(#parent)
winheight = WindowHeight(#parent)
If IsMenu(#parentmenu) : winheight - MenuHeight() : EndIf
If IsStatusBar(#parentstatusbar) : winheight - StatusBarHeight(#parentstatusbar) : EndIf
EndProcedure
Procedure UpdateGadgets()
GetParentWinMetrics()
ResizeGadget(#etg,0,0,winwidth,winheight)
EndProcedure
Procedure UpdateWindow()
dx = WindowWidth(#parent)
dy = WindowHeight(#parent)
If dx % 2 : dx + 1 : EndIf
If dy % 2 : dy + 1 : EndIf
ResizeWindow(#parent,#PB_Ignore,#PB_Ignore,dx,dy)
UpdateGadgets()
EndProcedure
;- openwindow
#parentflags = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered
OpenWindow(#parent, 0, 0, 1000, 700, "", #parentflags)
LoadFont(#parentfont_1, "Calibri", 11) : SetGadgetFont(#PB_Default, FontID(#parentfont_1))
;- Shortcuts
AddKeyboardShortcut(0, #PB_Shortcut_Escape, #escape)
;- Statusbar
If CreateStatusBar(#parentstatusbar, WindowID(#parent))
AddStatusBarField(#PB_Ignore)
EndIf
If IsMenu(#parentmenu)
WindowBounds(#parent, 220, MenuHeight(), #PB_Ignore, #PB_Ignore)
Else
WindowBounds(#parent, 220, 0, #PB_Ignore, #PB_Ignore)
EndIf
;- Programmcode -----------------------------------
;winwidth, winheight
GetParentWinMetrics()
ExplorerTreeGadget(#etg,0,0,winwidth,winheight,GetUserDirectory(#PB_Directory_Documents))
; BindEvents
BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #parent)
;- Eventschleife
Repeat
Event = WindowEvent()
Gadget = EventGadget()
Select Event
Case #PB_Event_CloseWindow
Select EventWindow()
Case #parent
Break
EndSelect
EndSelect
Select Gadget
Case #etg
Select EventType()
Case #PB_EventType_Change
checkDirAttr(GetGadgetText(Gadget))
Case #PB_EventType_LeftClick
Case #PB_EventType_LeftDoubleClick
Case #PB_EventType_RightClick
Case #PB_EventType_RightDoubleClick
EndSelect
EndSelect
ForEver
End
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
- HeX0R
- Beiträge: 3040
- Registriert: 10.09.2004 09:59
- Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3 - Kontaktdaten:
Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?
Laut MSDN ist #FILE_ATTRIBUTE_REPARSE_POINT zumindest ein Teil der Lösung.
{Home}.:|:.{Codes}.:|:.{Downloads}.:|:.{History Viewer Online}.:|:.{Bier spendieren}
Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?
Noch kurz, bevor ich mich auf's Fahrrad schwinge, um das schöne Wetter auszunutzen:
Ja, sieht so aus, dass mit dem Attribut #FILE_ATTRIBUTE_REPARSE_POINT ein "echtes Verzeichnis" von einem Link zu unterscheiden ist. Um das eigentliche Zielverzeichnis zu finden, gibt es zwei Wege:
a) eine Procedure zu entwickeln, die mittels API-Funktionen und Strukturen und sonstigen Betriebssysteminterna den Pfad ausspuckt - bei Weitem zu hoch für mich
b) FSUTIL verwenden, z. B. so:ohne abschließenden "\".
Wenn mir jemand so eine elegante procedure schreiben könnte, wäre traumhaft, ansonsten würde ich mit runprogram eine Temp-Datei erzeugen, die entsprechende Zeile auslesen und die Temp-Datei wieder löschen.
Ja, sieht so aus, dass mit dem Attribut #FILE_ATTRIBUTE_REPARSE_POINT ein "echtes Verzeichnis" von einem Link zu unterscheiden ist. Um das eigentliche Zielverzeichnis zu finden, gibt es zwei Wege:
a) eine Procedure zu entwickeln, die mittels API-Funktionen und Strukturen und sonstigen Betriebssysteminterna den Pfad ausspuckt - bei Weitem zu hoch für mich
b) FSUTIL verwenden, z. B. so:
Code: Alles auswählen
fsutil reparsepoint query "C:\Users\{username}\Startmenü"
Wenn mir jemand so eine elegante procedure schreiben könnte, wäre traumhaft, ansonsten würde ich mit runprogram eine Temp-Datei erzeugen, die entsprechende Zeile auslesen und die Temp-Datei wieder löschen.
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?
Es gibt hier einen alten Code von freak der passen könnte:
https://www.purebasic.fr/english/viewto ... 2&t=370284
Edit: Der Code funktioniert ohne Änderung unter Windows 7 mit PB v6.21b9 32/64.
Peter
https://www.purebasic.fr/english/viewto ... 2&t=370284
Edit: Der Code funktioniert ohne Änderung unter Windows 7 mit PB v6.21b9 32/64.
Peter
Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?
@DePe, der Link scheint nicht zu funktionieren.....
@EmmJott, du kannst mit RunProgram() das Ergebnis von "dir /a [C:\...]" auswerten. Bevor man sich mit API quält. Anbei noch ein Blog-Beitrag für eine Lösung in C. (Sorry, aber ich habe keine Zeit (Lust) das umzuschreiben.)
Weitere Suche ergab das hier. Nicht getestet.
@EmmJott, du kannst mit RunProgram() das Ergebnis von "dir /a [C:\...]" auswerten. Bevor man sich mit API quält. Anbei noch ein Blog-Beitrag für eine Lösung in C. (Sorry, aber ich habe keine Zeit (Lust) das umzuschreiben.)
Weitere Suche ergab das hier. Nicht getestet.
Using PureBasic latest stable version and current alpha/beta (x64) on Windows 11 Home
Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?
Hallo Axolotl,
vielleicht funktioniert der Link so:
https://www.purebasic.fr/english/viewtopic.php?p=282633
Peter
Anbei der unveränderte Code von freak:
vielleicht funktioniert der Link so:
https://www.purebasic.fr/english/viewtopic.php?p=282633
Peter
Anbei der unveränderte Code von freak:
Code: Alles auswählen
; WinIoCtl.h
;
#FILE_DEVICE_FILE_SYSTEM = $00000009
#METHOD_BUFFERED = 0
#FILE_ANY_ACCESS = 0
#FILE_SPECIAL_ACCESS = (#FILE_ANY_ACCESS)
Macro CTL_CODE( DeviceType, Function, Method, Access )
(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
EndMacro
#FSCTL_SET_REPARSE_POINT = CTL_CODE(#FILE_DEVICE_FILE_SYSTEM, 41, #METHOD_BUFFERED, #FILE_SPECIAL_ACCESS)
#FSCTL_GET_REPARSE_POINT = CTL_CODE(#FILE_DEVICE_FILE_SYSTEM, 42, #METHOD_BUFFERED, #FILE_ANY_ACCESS)
#FSCTL_DELETE_REPARSE_POINT = CTL_CODE(#FILE_DEVICE_FILE_SYSTEM, 43, #METHOD_BUFFERED, #FILE_SPECIAL_ACCESS)
; Winbase.h
;
#FILE_FLAG_OPEN_REPARSE_POINT = $00200000
; WinNT.h
;
#IO_REPARSE_TAG_MOUNT_POINT = $A0000003
#IO_REPARSE_TAG_HSM = $C0000004
#IO_REPARSE_TAG_HSM2 = $80000006
#IO_REPARSE_TAG_SIS = $80000007
#IO_REPARSE_TAG_DFS = $8000000A
#IO_REPARSE_TAG_SYMLINK = $A000000C
#IO_REPARSE_TAG_DFSR = $80000012
; From Windows Driver Kit.
; http://msdn.microsoft.com/en-us/library/ms791514.aspx
;
Structure SymbolicLinkReparseBuffer
SubstituteNameOffset.w
SubstituteNameLength.w
PrintNameOffset.w
PrintNameLength.w
Flags.l
PathBuffer.w[1]
EndStructure
Structure MountPointReparseBuffer
SubstituteNameOffset.w
SubstituteNameLength.w
PrintNameOffset.w
PrintNameLength.w
PathBuffer.w[1]
EndStructure
Structure GenericReparseBuffer
DataBuffer.b[1]
EndStructure
Structure REPARSE_DATA_BUFFER
ReparseTag.l
ReparseDataLength.w
Reserved.w
StructureUnion
SymbolicLinkReparseBuffer.SymbolicLinkReparseBuffer
MountPointReparseBuffer.MountPointReparseBuffer
GenericReparseBuffer.GenericReparseBuffer
EndStructureUnion
EndStructure
; Tries to follow a directory link on Windows Vista (should also work for files)
;
; - If the directory is no link, the result is the original directory
; - If the target cannot be read, the result is ""
;
Procedure.s GetDirectoryTarget(Directory$)
Protected TokenHandle, BufferSize, hDirectory, BytesReturned.l
Protected Privileges.TOKEN_PRIVILEGES
Protected *Buffer.REPARSE_DATA_BUFFER
Protected Result$ = ""
; Check if the directory is a reparse point (link or mount point)
;
If GetFileAttributes_(@Directory$) & #FILE_ATTRIBUTE_REPARSE_POINT
; The backup privilege is required to open a directory for io queries
; So try to set it on our process token. (usually it should be set already)
;
If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_ADJUST_PRIVILEGES, @TokenHandle)
Privileges\PrivilegeCount = 1
Privileges\Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED
If LookupPrivilegeValue_(#Null, @"SeBackupPrivilege", @Privileges\Privileges[0]\Luid)
AdjustTokenPrivileges_(TokenHandle, #False, @Privileges, SizeOf(TOKEN_PRIVILEGES), #Null, #Null)
EndIf
CloseHandle_(TokenHandle)
EndIf
; Open the directory
; Have to pass 0 as access right (not #GENERIC_READ), as it fails otherwise
; http://www.codeproject.com/KB/vista/Windows_Vista.aspx
;
hDirectory = CreateFile_(@Directory$, 0, #FILE_SHARE_READ|#FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, #FILE_FLAG_OPEN_REPARSE_POINT | #FILE_FLAG_BACKUP_SEMANTICS, #Null)
If hDirectory <> #INVALID_HANDLE_VALUE
; Allocate a buffer for the io query. 1000 bytes should be enough for the real path (in unicode)
;
BufferSize = SizeOf(REPARSE_DATA_BUFFER) + 1000
*Buffer = AllocateMemory(BufferSize)
If *Buffer
; Query the directory for reparse point information
;
If DeviceIoControl_(hDirectory, #FSCTL_GET_REPARSE_POINT, #Null, 0, *Buffer, BufferSize, @BytesReturned, #Null) <> 0
; Check the kind of reparse point (device drivers can create their own tags, so this is important)
; The "& $FFFFFFFF" is for 64bit, as the tags are negative when interpreted as quads
;
If *Buffer\ReparseTag & $FFFFFFFF = #IO_REPARSE_TAG_MOUNT_POINT
; Read the result. The offset and length are in bytes. PeekS needs length in characters
;
Result$ = PeekS(@*Buffer\MountPointReparseBuffer\PathBuffer[0] + *Buffer\MountPointReparseBuffer\SubstituteNameOffset, *Buffer\MountPointReparseBuffer\SubstituteNameLength / 2, #PB_Unicode)
ElseIf *Buffer\ReparseTag & $FFFFFFFF = #IO_REPARSE_TAG_SYMLINK
Result$ = PeekS(@*Buffer\SymbolicLinkReparseBuffer\PathBuffer[0] + *Buffer\SymbolicLinkReparseBuffer\SubstituteNameOffset, *Buffer\SymbolicLinkReparseBuffer\SubstituteNameLength / 2, #PB_Unicode)
EndIf
EndIf
FreeMemory(*Buffer)
EndIf
CloseHandle_(hDirectory)
EndIf
Else
; It is not a reparse point, so return the original path
;
Result$ = Directory$
EndIf
; Since the result is a unicode directory name, it can have the "\??\" prefix which allows a length of 32767 characters.
;
If Left(Result$, 4) = "\??\"
Result$ = Right(Result$, Len(Result$)-4)
EndIf
ProcedureReturn Result$
EndProcedure
; ----------------------------------------------------------------------------
Directory$ = "C:\Documents and Settings\"
Debug "Testing: " + Directory$
Debug "Target: " + GetDirectoryTarget(Directory$)