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