...

Source file src/github.com/Microsoft/go-winio/internal/fs/fs.go

Documentation: github.com/Microsoft/go-winio/internal/fs

     1  //go:build windows
     2  
     3  package fs
     4  
     5  import (
     6  	"golang.org/x/sys/windows"
     7  
     8  	"github.com/Microsoft/go-winio/internal/stringbuffer"
     9  )
    10  
    11  //go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go fs.go
    12  
    13  // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
    14  //sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW
    15  
    16  const NullHandle windows.Handle = 0
    17  
    18  // AccessMask defines standard, specific, and generic rights.
    19  //
    20  //	Bitmask:
    21  //	 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
    22  //	 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
    23  //	+---------------+---------------+-------------------------------+
    24  //	|G|G|G|G|Resvd|A| StandardRights|         SpecificRights        |
    25  //	|R|W|E|A|     |S|               |                               |
    26  //	+-+-------------+---------------+-------------------------------+
    27  //
    28  //	GR     Generic Read
    29  //	GW     Generic Write
    30  //	GE     Generic Exectue
    31  //	GA     Generic All
    32  //	Resvd  Reserved
    33  //	AS     Access Security System
    34  //
    35  // https://learn.microsoft.com/en-us/windows/win32/secauthz/access-mask
    36  //
    37  // https://learn.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
    38  //
    39  // https://learn.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants
    40  type AccessMask = windows.ACCESS_MASK
    41  
    42  //nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
    43  const (
    44  	// Not actually any.
    45  	//
    46  	// For CreateFile: "query certain metadata such as file, directory, or device attributes without accessing that file or device"
    47  	// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew#parameters
    48  	FILE_ANY_ACCESS AccessMask = 0
    49  
    50  	// Specific Object Access
    51  	// from ntioapi.h
    52  
    53  	FILE_READ_DATA      AccessMask = (0x0001) // file & pipe
    54  	FILE_LIST_DIRECTORY AccessMask = (0x0001) // directory
    55  
    56  	FILE_WRITE_DATA AccessMask = (0x0002) // file & pipe
    57  	FILE_ADD_FILE   AccessMask = (0x0002) // directory
    58  
    59  	FILE_APPEND_DATA          AccessMask = (0x0004) // file
    60  	FILE_ADD_SUBDIRECTORY     AccessMask = (0x0004) // directory
    61  	FILE_CREATE_PIPE_INSTANCE AccessMask = (0x0004) // named pipe
    62  
    63  	FILE_READ_EA         AccessMask = (0x0008) // file & directory
    64  	FILE_READ_PROPERTIES AccessMask = FILE_READ_EA
    65  
    66  	FILE_WRITE_EA         AccessMask = (0x0010) // file & directory
    67  	FILE_WRITE_PROPERTIES AccessMask = FILE_WRITE_EA
    68  
    69  	FILE_EXECUTE  AccessMask = (0x0020) // file
    70  	FILE_TRAVERSE AccessMask = (0x0020) // directory
    71  
    72  	FILE_DELETE_CHILD AccessMask = (0x0040) // directory
    73  
    74  	FILE_READ_ATTRIBUTES AccessMask = (0x0080) // all
    75  
    76  	FILE_WRITE_ATTRIBUTES AccessMask = (0x0100) // all
    77  
    78  	FILE_ALL_ACCESS      AccessMask = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF)
    79  	FILE_GENERIC_READ    AccessMask = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE)
    80  	FILE_GENERIC_WRITE   AccessMask = (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE)
    81  	FILE_GENERIC_EXECUTE AccessMask = (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE)
    82  
    83  	SPECIFIC_RIGHTS_ALL AccessMask = 0x0000FFFF
    84  
    85  	// Standard Access
    86  	// from ntseapi.h
    87  
    88  	DELETE       AccessMask = 0x0001_0000
    89  	READ_CONTROL AccessMask = 0x0002_0000
    90  	WRITE_DAC    AccessMask = 0x0004_0000
    91  	WRITE_OWNER  AccessMask = 0x0008_0000
    92  	SYNCHRONIZE  AccessMask = 0x0010_0000
    93  
    94  	STANDARD_RIGHTS_REQUIRED AccessMask = 0x000F_0000
    95  
    96  	STANDARD_RIGHTS_READ    AccessMask = READ_CONTROL
    97  	STANDARD_RIGHTS_WRITE   AccessMask = READ_CONTROL
    98  	STANDARD_RIGHTS_EXECUTE AccessMask = READ_CONTROL
    99  
   100  	STANDARD_RIGHTS_ALL AccessMask = 0x001F_0000
   101  )
   102  
   103  type FileShareMode uint32
   104  
   105  //nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
   106  const (
   107  	FILE_SHARE_NONE        FileShareMode = 0x00
   108  	FILE_SHARE_READ        FileShareMode = 0x01
   109  	FILE_SHARE_WRITE       FileShareMode = 0x02
   110  	FILE_SHARE_DELETE      FileShareMode = 0x04
   111  	FILE_SHARE_VALID_FLAGS FileShareMode = 0x07
   112  )
   113  
   114  type FileCreationDisposition uint32
   115  
   116  //nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
   117  const (
   118  	// from winbase.h
   119  
   120  	CREATE_NEW        FileCreationDisposition = 0x01
   121  	CREATE_ALWAYS     FileCreationDisposition = 0x02
   122  	OPEN_EXISTING     FileCreationDisposition = 0x03
   123  	OPEN_ALWAYS       FileCreationDisposition = 0x04
   124  	TRUNCATE_EXISTING FileCreationDisposition = 0x05
   125  )
   126  
   127  // CreateFile and co. take flags or attributes together as one parameter.
   128  // Define alias until we can use generics to allow both
   129  
   130  // https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
   131  type FileFlagOrAttribute uint32
   132  
   133  //nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
   134  const ( // from winnt.h
   135  	FILE_FLAG_WRITE_THROUGH       FileFlagOrAttribute = 0x8000_0000
   136  	FILE_FLAG_OVERLAPPED          FileFlagOrAttribute = 0x4000_0000
   137  	FILE_FLAG_NO_BUFFERING        FileFlagOrAttribute = 0x2000_0000
   138  	FILE_FLAG_RANDOM_ACCESS       FileFlagOrAttribute = 0x1000_0000
   139  	FILE_FLAG_SEQUENTIAL_SCAN     FileFlagOrAttribute = 0x0800_0000
   140  	FILE_FLAG_DELETE_ON_CLOSE     FileFlagOrAttribute = 0x0400_0000
   141  	FILE_FLAG_BACKUP_SEMANTICS    FileFlagOrAttribute = 0x0200_0000
   142  	FILE_FLAG_POSIX_SEMANTICS     FileFlagOrAttribute = 0x0100_0000
   143  	FILE_FLAG_OPEN_REPARSE_POINT  FileFlagOrAttribute = 0x0020_0000
   144  	FILE_FLAG_OPEN_NO_RECALL      FileFlagOrAttribute = 0x0010_0000
   145  	FILE_FLAG_FIRST_PIPE_INSTANCE FileFlagOrAttribute = 0x0008_0000
   146  )
   147  
   148  type FileSQSFlag = FileFlagOrAttribute
   149  
   150  //nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
   151  const ( // from winbase.h
   152  	SECURITY_ANONYMOUS      FileSQSFlag = FileSQSFlag(SecurityAnonymous << 16)
   153  	SECURITY_IDENTIFICATION FileSQSFlag = FileSQSFlag(SecurityIdentification << 16)
   154  	SECURITY_IMPERSONATION  FileSQSFlag = FileSQSFlag(SecurityImpersonation << 16)
   155  	SECURITY_DELEGATION     FileSQSFlag = FileSQSFlag(SecurityDelegation << 16)
   156  
   157  	SECURITY_SQOS_PRESENT     FileSQSFlag = 0x00100000
   158  	SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F0000
   159  )
   160  
   161  // GetFinalPathNameByHandle flags
   162  //
   163  // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew#parameters
   164  type GetFinalPathFlag uint32
   165  
   166  //nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
   167  const (
   168  	GetFinalPathDefaultFlag GetFinalPathFlag = 0x0
   169  
   170  	FILE_NAME_NORMALIZED GetFinalPathFlag = 0x0
   171  	FILE_NAME_OPENED     GetFinalPathFlag = 0x8
   172  
   173  	VOLUME_NAME_DOS  GetFinalPathFlag = 0x0
   174  	VOLUME_NAME_GUID GetFinalPathFlag = 0x1
   175  	VOLUME_NAME_NT   GetFinalPathFlag = 0x2
   176  	VOLUME_NAME_NONE GetFinalPathFlag = 0x4
   177  )
   178  
   179  // getFinalPathNameByHandle facilitates calling the Windows API GetFinalPathNameByHandle
   180  // with the given handle and flags. It transparently takes care of creating a buffer of the
   181  // correct size for the call.
   182  //
   183  // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
   184  func GetFinalPathNameByHandle(h windows.Handle, flags GetFinalPathFlag) (string, error) {
   185  	b := stringbuffer.NewWString()
   186  	//TODO: can loop infinitely if Win32 keeps returning the same (or a larger) n?
   187  	for {
   188  		n, err := windows.GetFinalPathNameByHandle(h, b.Pointer(), b.Cap(), uint32(flags))
   189  		if err != nil {
   190  			return "", err
   191  		}
   192  		// If the buffer wasn't large enough, n will be the total size needed (including null terminator).
   193  		// Resize and try again.
   194  		if n > b.Cap() {
   195  			b.ResizeTo(n)
   196  			continue
   197  		}
   198  		// If the buffer is large enough, n will be the size not including the null terminator.
   199  		// Convert to a Go string and return.
   200  		return b.String(), nil
   201  	}
   202  }
   203  

View as plain text