1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package windows 6 7 import ( 8 "syscall" 9 "unsafe" 10 ) 11 12 // Reparse tag values are taken from 13 // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/c8e77b37-3909-4fe6-a4ea-2b9d423b1ee4 14 const ( 15 FSCTL_SET_REPARSE_POINT = 0x000900A4 16 IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 17 IO_REPARSE_TAG_DEDUP = 0x80000013 18 IO_REPARSE_TAG_AF_UNIX = 0x80000023 19 20 SYMLINK_FLAG_RELATIVE = 1 21 ) 22 23 // These structures are described 24 // in https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/ca069dad-ed16-42aa-b057-b6b207f447cc 25 // and https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/b41f1cbf-10df-4a47-98d4-1c52a833d913. 26 27 type REPARSE_DATA_BUFFER struct { 28 ReparseTag uint32 29 ReparseDataLength uint16 30 Reserved uint16 31 DUMMYUNIONNAME byte 32 } 33 34 // REPARSE_DATA_BUFFER_HEADER is a common part of REPARSE_DATA_BUFFER structure. 35 type REPARSE_DATA_BUFFER_HEADER struct { 36 ReparseTag uint32 37 // The size, in bytes, of the reparse data that follows 38 // the common portion of the REPARSE_DATA_BUFFER element. 39 // This value is the length of the data starting at the 40 // SubstituteNameOffset field. 41 ReparseDataLength uint16 42 Reserved uint16 43 } 44 45 type SymbolicLinkReparseBuffer struct { 46 // The integer that contains the offset, in bytes, 47 // of the substitute name string in the PathBuffer array, 48 // computed as an offset from byte 0 of PathBuffer. Note that 49 // this offset must be divided by 2 to get the array index. 50 SubstituteNameOffset uint16 51 // The integer that contains the length, in bytes, of the 52 // substitute name string. If this string is null-terminated, 53 // SubstituteNameLength does not include the Unicode null character. 54 SubstituteNameLength uint16 55 // PrintNameOffset is similar to SubstituteNameOffset. 56 PrintNameOffset uint16 57 // PrintNameLength is similar to SubstituteNameLength. 58 PrintNameLength uint16 59 // Flags specifies whether the substitute name is a full path name or 60 // a path name relative to the directory containing the symbolic link. 61 Flags uint32 62 PathBuffer [1]uint16 63 } 64 65 // Path returns path stored in rb. 66 func (rb *SymbolicLinkReparseBuffer) Path() string { 67 n1 := rb.SubstituteNameOffset / 2 68 n2 := (rb.SubstituteNameOffset + rb.SubstituteNameLength) / 2 69 return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))[n1:n2:n2]) 70 } 71 72 type MountPointReparseBuffer struct { 73 // The integer that contains the offset, in bytes, 74 // of the substitute name string in the PathBuffer array, 75 // computed as an offset from byte 0 of PathBuffer. Note that 76 // this offset must be divided by 2 to get the array index. 77 SubstituteNameOffset uint16 78 // The integer that contains the length, in bytes, of the 79 // substitute name string. If this string is null-terminated, 80 // SubstituteNameLength does not include the Unicode null character. 81 SubstituteNameLength uint16 82 // PrintNameOffset is similar to SubstituteNameOffset. 83 PrintNameOffset uint16 84 // PrintNameLength is similar to SubstituteNameLength. 85 PrintNameLength uint16 86 PathBuffer [1]uint16 87 } 88 89 // Path returns path stored in rb. 90 func (rb *MountPointReparseBuffer) Path() string { 91 n1 := rb.SubstituteNameOffset / 2 92 n2 := (rb.SubstituteNameOffset + rb.SubstituteNameLength) / 2 93 return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))[n1:n2:n2]) 94 } 95