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 5package windows 6 7import ( 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 14const ( 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 27type 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. 35type 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 45type 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. 66func (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 72type 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. 90func (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