is possible to view if a file or folder is a junction or a symbolic link
and show the reparse_point information path,typ
Read:
Code: Select all
; Author: jpd
; Date: 30.11.2007
;Read junction and symbolic link
;PureBasic-Port 2007 by jpd
;Info-Source and Description: http://www.flexhex.com/docs/articles/hard-links.phtml#junctions and one link to mklink http://www.zdnet.de/downloads/prg/l/e/de3NLE-wc.html
; with c++ source code from Christoph@Hochstaetter.org
;
Procedure.l IsReparsePoint(Attr.l)
reparse.l
If Attr & #FILE_ATTRIBUTE_REPARSE_POINT
reparse=1
Else
reparse=0
EndIf
ProcedureReturn reparse
EndProcedure
Declare.l CTL_CODE(DeviceType, Function, Method, Access)
#FILE_DEVICE_FILE_SYSTEM = 9
#METHOD_BUFFERED = 0
#FILE_ANY_ACCESS = 0
#MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 2 * 1024; orig 16* problem with procedure ...
;-ReparseTag values...
#IO_REPARSE_TAG_MOUNT_POINT = 2684354563
#IO_REPARSE_TAG_SYMLINK = 2684354572
Structure REPARSE_DATA_BUFFER;private struct REPARSE_DATA_BUFFER
;{
ReparseTag.l;public uint ReparseTag;
ReparseDataLength.w;public short ReparseDataLength;
Reserved.w;public short Reserved;
EndStructure
Structure SymbolicLinkReparseBuffer Extends REPARSE_DATA_BUFFER
SubsNameOffset.w;public short SubsNameOffset;
SubsNameLength.w;public short SubsNameLength;
PrintNameOffset.w;public short PrintNameOffset;
PrintNameLength.w;public short PrintNameLength;
Type.l; //Vermute ich mal, ist nicht dokumentiert (1=relativer Link)
PathBuffer.w[#MAXIMUM_REPARSE_DATA_BUFFER_SIZE-20] ; PathBuffer.l[1]
EndStructure
Structure MountPointReparseBuffer Extends REPARSE_DATA_BUFFER
SubsNameOffset.w;public short SubsNameOffset;
SubsNameLength.w;public short SubsNameLength;
PrintNameOffset.w;public short PrintNameOffset;
PrintNameLength.w;public short PrintNameLength;
PathBuffer.w[#MAXIMUM_REPARSE_DATA_BUFFER_SIZE-16];PathBuffer.l[1]
EndStructure
;Structure GenericReparseBuffer Extends REPARSE_DATA_BUFFER
; DataBuffer.w[#MAXIMUM_REPARSE_DATA_BUFFER_SIZE-8]
;EndStructure
Structure _REPARSE_DATA_BUFFER;private struct REPARSE_DATA_BUFFER
;{
ReparseTag.l;public uint ReparseTag;
ReparseDataLength.w;public short ReparseDataLength;
Reserved.w;public short Reserved;
StructureUnion
SubsNameOffset.w;public short SubsNameOffset;
SubsNameLength.w;public short SubsNameLength;
PrintNameOffset.w;public short PrintNameOffset;
PrintNameLength.w;public short PrintNameLength;
PathBuffer.w[#MAXIMUM_REPARSE_DATA_BUFFER_SIZE]
EndStructureUnion
EndStructure
#GetFileExInfoStandard = 0 ;used by GetFileAttributesEx_
Declare.s GetFinalPathNameByHandle(Handle.l)
Structure _WIN32_FIND_DATA ;used by GetFileAttributesEx_
dwFileAttributes.l
ftCreationTime.FILETIME
ftLastAccessTime.FILETIME
ftLastWriteTime.FILETIME
nFileSizeLow.l
nFileSizeHigh.l
dwReserved0.l
dwReserved1.l
cFileName.s{#MAX_PATH}
cAlternate.s{14}
dummy.w
EndStructure
Structure Atrrib_Ex
FileIn.b
FileOut.b
type.l
valid.l
EndStructure
;------ used by GetFinalPathNameByHandleW
#FILE_NAME_NORMALIZED =0
#VOLUME_NAME_DOS = 0
#VOLUME_NAME_GUID =1
#VOLUME_NAME_NT=2
#VOLUME_NAME_NONE =4
#FILE_NAME_OPENED = 8
Procedure ReparseType(FileIn.s,FileOut.s,checkfile.l,typ.l)
Debug "---------------------------------"
Debug FileIn
Debug FileOut
Debug checkfile
Debug typ
pos= FindString(filein,":\",1)
driveletter.s= Mid(filein,pos-1,3)
Select GetDriveType_(driveletter)
Case 4
; Debug "Network Drive: " +driveletter
Default
; Debug "Local Drive: "+driveletter
EndSelect
;GetDriveType_(Parameter)
If checkfile <> -2 ;And typ=1 Or typ=0
pos= FindString(FileOut,"\??\",1)
reparse_path.s= Mid(FileOut,1,pos-1)
If typ=0
Debug "Reparse type: File --> ReparsePoint: " +reparse_path
EndIf
If typ=1
Debug "Reparse type: File --> symbolic Link: " +reparse_path
EndIf
EndIf
If checkfile = -2 ;And typ=1 Or typ=0
pos= FindString(FileOut,"\??\",1)
reparse_path.s= Mid(FileOut,pos+4,Len(fileOut)-4)
search_unc= FindString(FileOut,"\??\UNC\",1)
If search_unc >0
reparse_path=Mid(FileOut,1, search_unc-1)
EndIf
search_vol= FindString(FileOut,"\??\VOLUME",1)
If search_vol >0
reparse_path=Mid(FileOut,1, search_vol-1)
EndIf
;reparse_path.s=
If typ=0
Debug "Reparse type: Directory --> ReparsePoint: " +reparse_path
EndIf
If typ=1
Debug "Reparse type: Directory --> junction: " +reparse_path;value 4
EndIf
EndIf
EndProcedure
Procedure Dir_file_Handle(file_in.s,typ.l)
;----- used by createfile
#FILE_LIST_DIRECTORY = 1
#FILE_SHARE_READ = 1
#FILE_SHARE_DELETE = 4
#OPEN_EXISTING = 3
#FILE_FLAG_BACKUP_SEMANTICS = 33554432; $02000000
#FILE_SHARE_DELETE = 4
#FILE_FLAG_OPEN_REPARSE_POINT=2097152
Protected flag.l
If typ=-2
flag=#FILE_LIST_DIRECTORY
Else
flag=#GENERIC_READ
EndIf
hDir = CreateFile_(file_in, flag,#FILE_SHARE_READ, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS|#FILE_FLAG_OPEN_REPARSE_POINT, #Null)
ret= GetLastError_()
; GetLastError(ret )
ProcedureReturn hDir
EndProcedure
Procedure.l CTL_CODE(DeviceType, Function, Method, Access)
ProcedureReturn ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)
EndProcedure
Procedure.b IncreasePrivileges()
Protected hToken, Buff
Protected mLUID.LUID
Protected mPriv.TOKEN_PRIVILEGES
Protected mNewPriv.TOKEN_PRIVILEGES
Protected CurrentProcess = GetCurrentProcess_()
#TOKEN_ADJUST_PRIVILEGES = $20
#TOKEN_QUERY = $8
mPriv\PrivilegeCount = 1
mPriv\Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED
If CurrentProcess = 0
ProcedureReturn #False
EndIf
If OpenProcessToken_(CurrentProcess, #TOKEN_ADJUST_PRIVILEGES | #TOKEN_QUERY, @hToken) = 0
ProcedureReturn #False
EndIf
If LookupPrivilegeValue_(#Null, "SeBackupPrivilege", @mLUID) = 0
CloseHandle_(hToken)
ProcedureReturn #False
EndIf
If IsBadWritePtr_(@mPriv\Privileges[0]\Luid, SizeOf(LUID)) <> 0
CloseHandle_(hToken)
ProcedureReturn #False
EndIf
CopyMemory(@mLUID, @mPriv\Privileges[0]\Luid, SizeOf(LUID))
If AdjustTokenPrivileges_(hToken, #False, @mPriv, SizeOf(TOKEN_PRIVILEGES), @mNewPriv, @Buff) = 0
CloseHandle_(hToken)
ProcedureReturn #False
EndIf
If GetLastError_() <> #ERROR_SUCCESS
CloseHandle_(hToken)
ProcedureReturn #False
EndIf
; If we get here, then it worked. Returns TRUE
CloseHandle_(hToken)
ProcedureReturn #True
EndProcedure
;EndProcedure
Procedure GetReparse_Point(filein.s)
Protected FSCTL_GET_REPARSE_POINT.l
checkfile.l = FileSize(filein)
If checkfile <> -1
attribute.WIN32_FIND_DATA
GetFileAttributesEx_(filein ,#GetFileExInfoStandard,@attribute)
If IsReparsePoint(attribute\dwFileAttributes) ;check if the file or dir containing a
handle.l=Dir_file_Handle(filein,checkfile)
;Debug "handle: "+Str(handle)
FSCTL_GET_REPARSE_POINT =CTL_CODE(#FILE_DEVICE_FILE_SYSTEM, 42, #METHOD_BUFFERED, #FILE_ANY_ACCESS)
Protected rdb._REPARSE_DATA_BUFFER
DeviceIoControl_(handle, FSCTL_GET_REPARSE_POINT,0,0,@rdb,SizeOf(_REPARSE_DATA_BUFFER),@retbytes,0)
val= rdb\ReparseTag
If Hex(val)=Hex(#IO_REPARSE_TAG_MOUNT_POINT) ;And checkfile= -2
Protected trs_2.MountPointReparseBuffer
CopyMemory(@rdb,@trs_2,SizeOf(MountPointReparseBuffer))
junctionname.s=PeekS(@trs_2\PathBuffer,SizeOf(MountPointReparseBuffer),#PB_Unicode)
ReparseType( filein,junctionname,checkfile,0)
;CloseHandle_(handle)
trs_2\PathBuffer=0
EndIf
If Hex(val)=Hex(#IO_REPARSE_TAG_SYMLINK); = 2684354572
Protected trs_1.SymbolicLinkReparseBuffer
CopyMemory(@rdb,@trs_1,SizeOf(SymbolicLinkReparseBuffer))
junctionname.s= PeekS(@trs_1\PathBuffer,SizeOf(MountPointReparseBuffer),#PB_Unicode)
ReparseType(filein, junctionname,checkfile,1)
;CloseHandle_(handle)
trs_1\PathBuffer=0
EndIf
Else
Debug "next file"
EndIf
Else
Debug "file not found"
EndIf
CloseHandle_(handle)
EndProcedure
;-start
Select OSVersion()
Case #PB_OS_Windows_Vista
Default
Debug "Link Manager running only on Vista!"
End
EndSelect
If IncreasePrivileges() = #False
MessageBox_(0, "Could not retrieve all privileges.", "Error :", #MB_ICONEXCLAMATION)
End
EndIf
GetReparse_Point("c:\programme")
the write code can generate the junction but write this not properly on disk,
my opinion is that I give false info to structure.
I hope that someone can give me the right hint.
Thanks
jpd
Write
Code: Select all
#FILE_DEVICE_FILE_SYSTEM = 9
#METHOD_BUFFERED = 0
#FILE_ANY_ACCESS = 0
#MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024; orig 16* problem with procedure ...
;-ReparseTag values...
#IO_REPARSE_TAG_MOUNT_POINT = 2684354563
#IO_REPARSE_TAG_SYMLINK = 2684354572
#GetFileExInfoStandard=0
Structure REPARSE_DATA_BUFFER;private struct REPARSE_DATA_BUFFER
;{
ReparseTag.l;public uint ReparseTag;
ReparseDataLength.w;public short ReparseDataLength;
Reserved.w;public short Reserved;
StructureUnion
SubstituteNameOffset.w;
SubstituteNameLength.w;
PrintNameOffset.w;
PrintNameLength.w;
PathBuffer.b[#MAXIMUM_REPARSE_DATA_BUFFER_SIZE]
EndStructureUnion
EndStructure
Structure _REPARSE_DATA_BUFFER;private struct REPARSE_DATA_BUFFER
;{
ReparseTag.l;public uint ReparseTag;
ReparseDataLength.w;public short ReparseDataLength;
Reserved.w;public short Reserved;
EndStructure
;Structure AllLinks Extends REPARSE_DATA_BUFFER
; SubstituteNameOffset.w;
; SubstituteNameLength.w;
; PrintNameOffset.w;
; PrintNameLength.w;
; EndStructure
Structure SymbolicLinkReparseBuffer Extends _REPARSE_DATA_BUFFER
SubstituteNameOffset.w;
SubstituteNameLength.w;
PrintNameOffset.w;
PrintNameLength.w;
Type.l; //Vermute ich mal, ist nicht dokumentiert (1=relativer Link)
PathBuffer.b[#MAXIMUM_REPARSE_DATA_BUFFER_SIZE-20] ; PathBuffer.l[1]
EndStructure
Structure MountPointReparseBuffer Extends _REPARSE_DATA_BUFFER
SubstituteNameOffset.w;
SubstituteNameLength.w;
PrintNameOffset.w;
PrintNameLength.w;
PathBuffer.b[#MAXIMUM_REPARSE_DATA_BUFFER_SIZE-16];PathBuffer.l[1]
EndStructure
Structure GenericReparseBuffer Extends _REPARSE_DATA_BUFFER
DataBuffer.b[#MAXIMUM_REPARSE_DATA_BUFFER_SIZE-8]
EndStructure
#REPARSE_DATA_BUFFER_HEADER_SIZE = OffsetOf(GenericReparseBuffer\DataBuffer)
;#REPARSE_DATA_BUFFER_HEADER_SIZE = OffsetOf(MountPointReparseBuffer\PathBuffer)
;#MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024
Procedure.l CTL_CODE(DeviceType, Function, Method, Access)
ProcedureReturn ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)
EndProcedure
Procedure.l IsReparsePoint(Attr.l)
reparse.l
If Attr & #FILE_ATTRIBUTE_REPARSE_POINT
reparse=1
Else
reparse=0
EndIf
ProcedureReturn reparse
EndProcedure
Procedure Dir_Handle(DirIn.s)
;----- used by createfile
#FILE_LIST_DIRECTORY = 1
#FILE_SHARE_READ = 1
#FILE_SHARE_DELETE = 4
#OPEN_EXISTING = 3
#FILE_FLAG_BACKUP_SEMANTICS = 33554432; $02000000
#FILE_SHARE_DELETE = 4
#FILE_FLAG_OPEN_REPARSE_POINT=2097152
;Protected flag.l
; flag=
hDir = CreateFile_(DirIn, #GENERIC_WRITE | #GENERIC_READ ,#FILE_SHARE_READ, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS|#FILE_FLAG_OPEN_REPARSE_POINT, #Null)
ret= GetLastError_()
Debug "hDir: "+Str(ret)
;If err=1
;GetLastError(ret,file_in )
;EndIf
ProcedureReturn hDir
EndProcedure
Procedure.b IncreasePrivileges()
Protected hToken, Buff
Protected mLUID.LUID
Protected mPriv.TOKEN_PRIVILEGES
Protected mNewPriv.TOKEN_PRIVILEGES
Protected CurrentProcess = GetCurrentProcess_()
#TOKEN_ADJUST_PRIVILEGES = $20
#TOKEN_QUERY = $8
mPriv\PrivilegeCount = 1
mPriv\Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED
#SE_RESTORE_NAME = "SeRestorePrivilege"
#SE_BACKUP_NAME="SeBackupPrivilege"
#SE_PRIVILEGE_ENABLED1="SeCreateSymbolicLinkPrivilege"
If CurrentProcess = 0
ProcedureReturn #False
EndIf
If OpenProcessToken_(CurrentProcess, #TOKEN_ADJUST_PRIVILEGES | #TOKEN_QUERY, @hToken) = 0
ProcedureReturn #False
EndIf
If LookupPrivilegeValue_(#Null,#SE_PRIVILEGE_ENABLED1, @mLUID) = 0
CloseHandle_(hToken)
ProcedureReturn #False
EndIf
If IsBadWritePtr_(@mPriv\Privileges[0]\Luid, SizeOf(LUID)) <> 0
CloseHandle_(hToken)
ProcedureReturn #False
EndIf
CopyMemory(@mLUID, @mPriv\Privileges[0]\Luid, SizeOf(LUID))
If AdjustTokenPrivileges_(hToken, #False, @mPriv, SizeOf(TOKEN_PRIVILEGES), @mNewPriv, @Buff) = 0
CloseHandle_(hToken)
ProcedureReturn #False
EndIf
If GetLastError_() <> #ERROR_SUCCESS
CloseHandle_(hToken)
ProcedureReturn #False
EndIf
; If we get here, then it worked. Returns TRUE
CloseHandle_(hToken)
ProcedureReturn #True
EndProcedure
;-start
If IncreasePrivileges() = #False
MessageBox_(0, "Could not retrieve all privileges.", "Error :", #MB_ICONEXCLAMATION)
End
EndIf
;-start
DirIn.s="c:\test113"
DirOut.s="\\\??\c:\empty"; right is normaly \??\c:\empty...but will be troncated using \\\??\c:\empty the generate parsepoint is right but cannot access on it.
size.w=Len(DirIn)
sizePN.w=Len(DirOut)*SizeOf(character)
checkDir.l = FileSize(DirIn)
If checkDir=-1
Ergebnis = CreateDirectory(DirIn)
checkDir.l = FileSize(DirIn)
EndIf
If checkDir = -2
Debug "IsDir: " +DirIn
If PathIsDirectoryEmpty_(DirIn)
Debug "IsEmpty"
attribute.WIN32_FIND_DATA
GetFileAttributesEx_(DirIn ,#GetFileExInfoStandard,@attribute)
If Not IsReparsePoint(attribute\dwFileAttributes) ;check if the file or dir containing a
handle.l=Dir_Handle(DirIn)
FSCTL_SET_REPARSE_POINT =CTL_CODE(#FILE_DEVICE_FILE_SYSTEM, 41, #METHOD_BUFFERED, #FILE_ANY_ACCESS)
junction.MountPointReparseBuffer
With junction
\ReparseTag=#IO_REPARSE_TAG_MOUNT_POINT
\Reserved=0
\SubstituteNameOffset=0
\SubstituteNameLength=size
\PrintNameOffset=size+SizeOf(character)
\PrintNameLength=sizePN
EndWith
; gen.GenericReparseBuffer
PokeS(@junction\PathBuffer,DirOut,Len(DirOut),#PB_Unicode)
dummy.w=0
junction\ReparseDataLength =size+sizePN+12
Debug #REPARSE_DATA_BUFFER_HEADER_SIZE
ret=DeviceIoControl_(handle, FSCTL_SET_REPARSE_POINT,@junction,junction\ReparseDataLength+#REPARSE_DATA_BUFFER_HEADER_SIZE ,#Null,0,@dummy,#Null)
ret= GetLastError_()
Debug ret
EndIf
EndIf
EndIf