Merge pull request #117306 from marosset/update-go-winio-dep
updating microsft/go-winio package to latest version
This commit is contained in:
		
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@@ -15,7 +15,7 @@ require (
 | 
				
			|||||||
	github.com/Azure/go-autorest/autorest/adal v0.9.23
 | 
						github.com/Azure/go-autorest/autorest/adal v0.9.23
 | 
				
			||||||
	github.com/GoogleCloudPlatform/k8s-cloud-provider v1.18.1-0.20220218231025-f11817397a1b
 | 
						github.com/GoogleCloudPlatform/k8s-cloud-provider v1.18.1-0.20220218231025-f11817397a1b
 | 
				
			||||||
	github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab
 | 
						github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab
 | 
				
			||||||
	github.com/Microsoft/go-winio v0.4.17
 | 
						github.com/Microsoft/go-winio v0.6.0
 | 
				
			||||||
	github.com/Microsoft/hcsshim v0.8.25
 | 
						github.com/Microsoft/hcsshim v0.8.25
 | 
				
			||||||
	github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e
 | 
						github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e
 | 
				
			||||||
	github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
 | 
						github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.sum
									
									
									
									
									
								
							@@ -82,8 +82,9 @@ github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5
 | 
				
			|||||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
 | 
					github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
 | 
				
			||||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
 | 
					github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
 | 
				
			||||||
github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
 | 
					github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
 | 
				
			||||||
github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w=
 | 
					 | 
				
			||||||
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
 | 
					github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
 | 
				
			||||||
 | 
					github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
 | 
				
			||||||
 | 
					github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
 | 
				
			||||||
github.com/Microsoft/hcsshim v0.8.25 h1:fRMwXiwk3qDwc0P05eHnh+y2v07JdtsfQ1fuAc69m9g=
 | 
					github.com/Microsoft/hcsshim v0.8.25 h1:fRMwXiwk3qDwc0P05eHnh+y2v07JdtsfQ1fuAc69m9g=
 | 
				
			||||||
github.com/Microsoft/hcsshim v0.8.25/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
 | 
					github.com/Microsoft/hcsshim v0.8.25/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
 | 
				
			||||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
 | 
					github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,7 +83,6 @@
 | 
				
			|||||||
        "sigs.k8s.io/structured-merge-diff/v4"
 | 
					        "sigs.k8s.io/structured-merge-diff/v4"
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "github.com/pkg/errors": [
 | 
					      "github.com/pkg/errors": [
 | 
				
			||||||
        "github.com/Microsoft/go-winio",
 | 
					 | 
				
			||||||
        "github.com/Microsoft/hcsshim",
 | 
					        "github.com/Microsoft/hcsshim",
 | 
				
			||||||
        "github.com/aws/aws-sdk-go",
 | 
					        "github.com/aws/aws-sdk-go",
 | 
				
			||||||
        "github.com/containerd/cgroups",
 | 
					        "github.com/containerd/cgroups",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								vendor/github.com/Microsoft/go-winio/.gitattributes
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/Microsoft/go-winio/.gitattributes
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					* text=auto eol=lf
 | 
				
			||||||
							
								
								
									
										9
									
								
								vendor/github.com/Microsoft/go-winio/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/Microsoft/go-winio/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1 +1,10 @@
 | 
				
			|||||||
 | 
					.vscode/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
*.exe
 | 
					*.exe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# testing
 | 
				
			||||||
 | 
					testdata
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# go workspaces
 | 
				
			||||||
 | 
					go.work
 | 
				
			||||||
 | 
					go.work.sum
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										144
									
								
								vendor/github.com/Microsoft/go-winio/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								vendor/github.com/Microsoft/go-winio/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					run:
 | 
				
			||||||
 | 
					  skip-dirs:
 | 
				
			||||||
 | 
					    - pkg/etw/sample
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					linters:
 | 
				
			||||||
 | 
					  enable:
 | 
				
			||||||
 | 
					    # style
 | 
				
			||||||
 | 
					    - containedctx # struct contains a context
 | 
				
			||||||
 | 
					    - dupl # duplicate code
 | 
				
			||||||
 | 
					    - errname # erorrs are named correctly
 | 
				
			||||||
 | 
					    - goconst # strings that should be constants
 | 
				
			||||||
 | 
					    - godot # comments end in a period
 | 
				
			||||||
 | 
					    - misspell
 | 
				
			||||||
 | 
					    - nolintlint # "//nolint" directives are properly explained
 | 
				
			||||||
 | 
					    - revive # golint replacement
 | 
				
			||||||
 | 
					    - stylecheck # golint replacement, less configurable than revive
 | 
				
			||||||
 | 
					    - unconvert # unnecessary conversions
 | 
				
			||||||
 | 
					    - wastedassign
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # bugs, performance, unused, etc ...
 | 
				
			||||||
 | 
					    - contextcheck # function uses a non-inherited context
 | 
				
			||||||
 | 
					    - errorlint # errors not wrapped for 1.13
 | 
				
			||||||
 | 
					    - exhaustive # check exhaustiveness of enum switch statements
 | 
				
			||||||
 | 
					    - gofmt # files are gofmt'ed
 | 
				
			||||||
 | 
					    - gosec # security
 | 
				
			||||||
 | 
					    - nestif # deeply nested ifs
 | 
				
			||||||
 | 
					    - nilerr # returns nil even with non-nil error
 | 
				
			||||||
 | 
					    - prealloc # slices that can be pre-allocated
 | 
				
			||||||
 | 
					    - structcheck # unused struct fields
 | 
				
			||||||
 | 
					    - unparam # unused function params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					issues:
 | 
				
			||||||
 | 
					  exclude-rules:
 | 
				
			||||||
 | 
					    # err is very often shadowed in nested scopes
 | 
				
			||||||
 | 
					    - linters:
 | 
				
			||||||
 | 
					        - govet
 | 
				
			||||||
 | 
					      text: '^shadow: declaration of "err" shadows declaration'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # ignore long lines for skip autogen directives
 | 
				
			||||||
 | 
					    - linters:
 | 
				
			||||||
 | 
					        - revive
 | 
				
			||||||
 | 
					      text: "^line-length-limit: "
 | 
				
			||||||
 | 
					      source: "^//(go:generate|sys) "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # allow unjustified ignores of error checks in defer statements
 | 
				
			||||||
 | 
					    - linters:
 | 
				
			||||||
 | 
					        - nolintlint
 | 
				
			||||||
 | 
					      text: "^directive `//nolint:errcheck` should provide explanation"
 | 
				
			||||||
 | 
					      source: '^\s*defer '
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # allow unjustified ignores of error lints for io.EOF
 | 
				
			||||||
 | 
					    - linters:
 | 
				
			||||||
 | 
					        - nolintlint
 | 
				
			||||||
 | 
					      text: "^directive `//nolint:errorlint` should provide explanation"
 | 
				
			||||||
 | 
					      source: '[=|!]= io.EOF'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					linters-settings:
 | 
				
			||||||
 | 
					  govet:
 | 
				
			||||||
 | 
					    enable-all: true
 | 
				
			||||||
 | 
					    disable:
 | 
				
			||||||
 | 
					      # struct order is often for Win32 compat
 | 
				
			||||||
 | 
					      # also, ignore pointer bytes/GC issues for now until performance becomes an issue
 | 
				
			||||||
 | 
					      - fieldalignment
 | 
				
			||||||
 | 
					    check-shadowing: true
 | 
				
			||||||
 | 
					  nolintlint:
 | 
				
			||||||
 | 
					    allow-leading-space: false
 | 
				
			||||||
 | 
					    require-explanation: true
 | 
				
			||||||
 | 
					    require-specific: true
 | 
				
			||||||
 | 
					  revive:
 | 
				
			||||||
 | 
					    # revive is more configurable than static check, so likely the preferred alternative to static-check
 | 
				
			||||||
 | 
					    # (once the perf issue is solved: https://github.com/golangci/golangci-lint/issues/2997)
 | 
				
			||||||
 | 
					    enable-all-rules:
 | 
				
			||||||
 | 
					      true
 | 
				
			||||||
 | 
					      # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
 | 
				
			||||||
 | 
					    rules:
 | 
				
			||||||
 | 
					      # rules with required arguments
 | 
				
			||||||
 | 
					      - name: argument-limit
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      - name: banned-characters
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      - name: cognitive-complexity
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      - name: cyclomatic
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      - name: file-header
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      - name: function-length
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      - name: function-result-limit
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      - name: max-public-structs
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      # geneally annoying rules
 | 
				
			||||||
 | 
					      - name: add-constant # complains about any and all strings and integers
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      - name: confusing-naming # we frequently use "Foo()" and "foo()" together
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      - name: flag-parameter # excessive, and a common idiom we use
 | 
				
			||||||
 | 
					        disabled: true
 | 
				
			||||||
 | 
					      # general config
 | 
				
			||||||
 | 
					      - name: line-length-limit
 | 
				
			||||||
 | 
					        arguments:
 | 
				
			||||||
 | 
					          - 140
 | 
				
			||||||
 | 
					      - name: var-naming
 | 
				
			||||||
 | 
					        arguments:
 | 
				
			||||||
 | 
					          - []
 | 
				
			||||||
 | 
					          - - CID
 | 
				
			||||||
 | 
					            - CRI
 | 
				
			||||||
 | 
					            - CTRD
 | 
				
			||||||
 | 
					            - DACL
 | 
				
			||||||
 | 
					            - DLL
 | 
				
			||||||
 | 
					            - DOS
 | 
				
			||||||
 | 
					            - ETW
 | 
				
			||||||
 | 
					            - FSCTL
 | 
				
			||||||
 | 
					            - GCS
 | 
				
			||||||
 | 
					            - GMSA
 | 
				
			||||||
 | 
					            - HCS
 | 
				
			||||||
 | 
					            - HV
 | 
				
			||||||
 | 
					            - IO
 | 
				
			||||||
 | 
					            - LCOW
 | 
				
			||||||
 | 
					            - LDAP
 | 
				
			||||||
 | 
					            - LPAC
 | 
				
			||||||
 | 
					            - LTSC
 | 
				
			||||||
 | 
					            - MMIO
 | 
				
			||||||
 | 
					            - NT
 | 
				
			||||||
 | 
					            - OCI
 | 
				
			||||||
 | 
					            - PMEM
 | 
				
			||||||
 | 
					            - PWSH
 | 
				
			||||||
 | 
					            - RX
 | 
				
			||||||
 | 
					            - SACl
 | 
				
			||||||
 | 
					            - SID
 | 
				
			||||||
 | 
					            - SMB
 | 
				
			||||||
 | 
					            - TX
 | 
				
			||||||
 | 
					            - VHD
 | 
				
			||||||
 | 
					            - VHDX
 | 
				
			||||||
 | 
					            - VMID
 | 
				
			||||||
 | 
					            - VPCI
 | 
				
			||||||
 | 
					            - WCOW
 | 
				
			||||||
 | 
					            - WIM
 | 
				
			||||||
 | 
					  stylecheck:
 | 
				
			||||||
 | 
					    checks:
 | 
				
			||||||
 | 
					      - "all"
 | 
				
			||||||
 | 
					      - "-ST1003" # use revive's var naming
 | 
				
			||||||
							
								
								
									
										85
									
								
								vendor/github.com/Microsoft/go-winio/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										85
									
								
								vendor/github.com/Microsoft/go-winio/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
# go-winio
 | 
					# go-winio [](https://github.com/microsoft/go-winio/actions/workflows/ci.yml)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This repository contains utilities for efficiently performing Win32 IO operations in
 | 
					This repository contains utilities for efficiently performing Win32 IO operations in
 | 
				
			||||||
Go. Currently, this is focused on accessing named pipes and other file handles, and
 | 
					Go. Currently, this is focused on accessing named pipes and other file handles, and
 | 
				
			||||||
@@ -11,12 +11,79 @@ package.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Please see the LICENSE file for licensing information.
 | 
					Please see the LICENSE file for licensing information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This project has adopted the [Microsoft Open Source Code of
 | 
					## Contributing
 | 
				
			||||||
Conduct](https://opensource.microsoft.com/codeofconduct/). For more information
 | 
					 | 
				
			||||||
see the [Code of Conduct
 | 
					 | 
				
			||||||
FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact
 | 
					 | 
				
			||||||
[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional
 | 
					 | 
				
			||||||
questions or comments.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe
 | 
					This project welcomes contributions and suggestions.
 | 
				
			||||||
for another named pipe implementation.
 | 
					Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that
 | 
				
			||||||
 | 
					you have the right to, and actually do, grant us the rights to use your contribution.
 | 
				
			||||||
 | 
					For details, visit [Microsoft CLA](https://cla.microsoft.com).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When you submit a pull request, a CLA-bot will automatically determine whether you need to
 | 
				
			||||||
 | 
					provide a CLA and decorate the PR appropriately (e.g., label, comment).
 | 
				
			||||||
 | 
					Simply follow the instructions provided by the bot.
 | 
				
			||||||
 | 
					You will only need to do this once across all repos using our CLA.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Additionally, the pull request pipeline requires the following steps to be performed before
 | 
				
			||||||
 | 
					mergining.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Code Sign-Off
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We require that contributors sign their commits using [`git commit --signoff`][git-commit-s]
 | 
				
			||||||
 | 
					to certify they either authored the work themselves or otherwise have permission to use it in this project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A range of commits can be signed off using [`git rebase --signoff`][git-rebase-s].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please see [the developer certificate](https://developercertificate.org) for more info,
 | 
				
			||||||
 | 
					as well as to make sure that you can attest to the rules listed.
 | 
				
			||||||
 | 
					Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Linting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Code must pass a linting stage, which uses [`golangci-lint`][lint].
 | 
				
			||||||
 | 
					The linting settings are stored in [`.golangci.yaml`](./.golangci.yaml), and can be run
 | 
				
			||||||
 | 
					automatically with VSCode by adding the following to your workspace or folder settings:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					    "go.lintTool": "golangci-lint",
 | 
				
			||||||
 | 
					    "go.lintOnSave": "package",
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Additional editor [integrations options are also available][lint-ide].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Alternatively, `golangci-lint` can be [installed locally][lint-install] and run from the repo root:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					# use . or specify a path to only lint a package
 | 
				
			||||||
 | 
					# to show all lint errors, use flags "--max-issues-per-linter=0 --max-same-issues=0"
 | 
				
			||||||
 | 
					> golangci-lint run ./...
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Go Generate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The pipeline checks that auto-generated code, via `go generate`, are up to date.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This can be done for the entire repo:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					> go generate ./...
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Code of Conduct
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
 | 
				
			||||||
 | 
					For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
 | 
				
			||||||
 | 
					contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Special Thanks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thanks to [natefinch][natefinch] for the inspiration for this library.
 | 
				
			||||||
 | 
					See [npipe](https://github.com/natefinch/npipe) for another named pipe implementation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[lint]: https://golangci-lint.run/
 | 
				
			||||||
 | 
					[lint-ide]: https://golangci-lint.run/usage/integrations/#editor-integration
 | 
				
			||||||
 | 
					[lint-install]: https://golangci-lint.run/usage/install/#local-installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[git-commit-s]: https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s
 | 
				
			||||||
 | 
					[git-rebase-s]: https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---signoff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[natefinch]: https://github.com/natefinch
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								vendor/github.com/Microsoft/go-winio/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/Microsoft/go-winio/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Security
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Reporting Security Issues
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Please do not report security vulnerabilities through public GitHub issues.**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com).  If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
 | 
				
			||||||
 | 
					  * Full paths of source file(s) related to the manifestation of the issue
 | 
				
			||||||
 | 
					  * The location of the affected source code (tag/branch/commit or direct URL)
 | 
				
			||||||
 | 
					  * Any special configuration required to reproduce the issue
 | 
				
			||||||
 | 
					  * Step-by-step instructions to reproduce the issue
 | 
				
			||||||
 | 
					  * Proof-of-concept or exploit code (if possible)
 | 
				
			||||||
 | 
					  * Impact of the issue, including how an attacker might exploit the issue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This information will help us triage your report more quickly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Preferred Languages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We prefer all communications to be in English.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Policy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- END MICROSOFT SECURITY.MD BLOCK -->
 | 
				
			||||||
							
								
								
									
										48
									
								
								vendor/github.com/Microsoft/go-winio/backup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/Microsoft/go-winio/backup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
@@ -7,11 +8,12 @@ import (
 | 
				
			|||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"io/ioutil"
 | 
					 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"unicode/utf16"
 | 
						"unicode/utf16"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
 | 
					//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
 | 
				
			||||||
@@ -24,7 +26,7 @@ const (
 | 
				
			|||||||
	BackupAlternateData
 | 
						BackupAlternateData
 | 
				
			||||||
	BackupLink
 | 
						BackupLink
 | 
				
			||||||
	BackupPropertyData
 | 
						BackupPropertyData
 | 
				
			||||||
	BackupObjectId
 | 
						BackupObjectId //revive:disable-line:var-naming ID, not Id
 | 
				
			||||||
	BackupReparseData
 | 
						BackupReparseData
 | 
				
			||||||
	BackupSparseBlock
 | 
						BackupSparseBlock
 | 
				
			||||||
	BackupTxfsData
 | 
						BackupTxfsData
 | 
				
			||||||
@@ -34,14 +36,16 @@ const (
 | 
				
			|||||||
	StreamSparseAttributes = uint32(8)
 | 
						StreamSparseAttributes = uint32(8)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//nolint:revive // var-naming: ALL_CAPS
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	WRITE_DAC              = 0x40000
 | 
						WRITE_DAC              = windows.WRITE_DAC
 | 
				
			||||||
	WRITE_OWNER            = 0x80000
 | 
						WRITE_OWNER            = windows.WRITE_OWNER
 | 
				
			||||||
	ACCESS_SYSTEM_SECURITY = 0x1000000
 | 
						ACCESS_SYSTEM_SECURITY = windows.ACCESS_SYSTEM_SECURITY
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BackupHeader represents a backup stream of a file.
 | 
					// BackupHeader represents a backup stream of a file.
 | 
				
			||||||
type BackupHeader struct {
 | 
					type BackupHeader struct {
 | 
				
			||||||
 | 
						//revive:disable-next-line:var-naming ID, not Id
 | 
				
			||||||
	Id         uint32 // The backup stream ID
 | 
						Id         uint32 // The backup stream ID
 | 
				
			||||||
	Attributes uint32 // Stream attributes
 | 
						Attributes uint32 // Stream attributes
 | 
				
			||||||
	Size       int64  // The size of the stream in bytes
 | 
						Size       int64  // The size of the stream in bytes
 | 
				
			||||||
@@ -49,8 +53,8 @@ type BackupHeader struct {
 | 
				
			|||||||
	Offset     int64  // The offset of the stream in the file (for BackupSparseBlock only).
 | 
						Offset     int64  // The offset of the stream in the file (for BackupSparseBlock only).
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type win32StreamId struct {
 | 
					type win32StreamID struct {
 | 
				
			||||||
	StreamId   uint32
 | 
						StreamID   uint32
 | 
				
			||||||
	Attributes uint32
 | 
						Attributes uint32
 | 
				
			||||||
	Size       uint64
 | 
						Size       uint64
 | 
				
			||||||
	NameSize   uint32
 | 
						NameSize   uint32
 | 
				
			||||||
@@ -71,7 +75,7 @@ func NewBackupStreamReader(r io.Reader) *BackupStreamReader {
 | 
				
			|||||||
// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
 | 
					// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
 | 
				
			||||||
// it was not completely read.
 | 
					// it was not completely read.
 | 
				
			||||||
func (r *BackupStreamReader) Next() (*BackupHeader, error) {
 | 
					func (r *BackupStreamReader) Next() (*BackupHeader, error) {
 | 
				
			||||||
	if r.bytesLeft > 0 {
 | 
						if r.bytesLeft > 0 { //nolint:nestif // todo: flatten this
 | 
				
			||||||
		if s, ok := r.r.(io.Seeker); ok {
 | 
							if s, ok := r.r.(io.Seeker); ok {
 | 
				
			||||||
			// Make sure Seek on io.SeekCurrent sometimes succeeds
 | 
								// Make sure Seek on io.SeekCurrent sometimes succeeds
 | 
				
			||||||
			// before trying the actual seek.
 | 
								// before trying the actual seek.
 | 
				
			||||||
@@ -82,16 +86,16 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) {
 | 
				
			|||||||
				r.bytesLeft = 0
 | 
									r.bytesLeft = 0
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if _, err := io.Copy(ioutil.Discard, r); err != nil {
 | 
							if _, err := io.Copy(io.Discard, r); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var wsi win32StreamId
 | 
						var wsi win32StreamID
 | 
				
			||||||
	if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
 | 
						if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	hdr := &BackupHeader{
 | 
						hdr := &BackupHeader{
 | 
				
			||||||
		Id:         wsi.StreamId,
 | 
							Id:         wsi.StreamID,
 | 
				
			||||||
		Attributes: wsi.Attributes,
 | 
							Attributes: wsi.Attributes,
 | 
				
			||||||
		Size:       int64(wsi.Size),
 | 
							Size:       int64(wsi.Size),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -102,7 +106,7 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		hdr.Name = syscall.UTF16ToString(name)
 | 
							hdr.Name = syscall.UTF16ToString(name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if wsi.StreamId == BackupSparseBlock {
 | 
						if wsi.StreamID == BackupSparseBlock {
 | 
				
			||||||
		if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
 | 
							if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -147,8 +151,8 @@ func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error {
 | 
				
			|||||||
		return fmt.Errorf("missing %d bytes", w.bytesLeft)
 | 
							return fmt.Errorf("missing %d bytes", w.bytesLeft)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	name := utf16.Encode([]rune(hdr.Name))
 | 
						name := utf16.Encode([]rune(hdr.Name))
 | 
				
			||||||
	wsi := win32StreamId{
 | 
						wsi := win32StreamID{
 | 
				
			||||||
		StreamId:   hdr.Id,
 | 
							StreamID:   hdr.Id,
 | 
				
			||||||
		Attributes: hdr.Attributes,
 | 
							Attributes: hdr.Attributes,
 | 
				
			||||||
		Size:       uint64(hdr.Size),
 | 
							Size:       uint64(hdr.Size),
 | 
				
			||||||
		NameSize:   uint32(len(name) * 2),
 | 
							NameSize:   uint32(len(name) * 2),
 | 
				
			||||||
@@ -203,7 +207,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) {
 | 
				
			|||||||
	var bytesRead uint32
 | 
						var bytesRead uint32
 | 
				
			||||||
	err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
 | 
						err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, &os.PathError{"BackupRead", r.f.Name(), err}
 | 
							return 0, &os.PathError{Op: "BackupRead", Path: r.f.Name(), Err: err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	runtime.KeepAlive(r.f)
 | 
						runtime.KeepAlive(r.f)
 | 
				
			||||||
	if bytesRead == 0 {
 | 
						if bytesRead == 0 {
 | 
				
			||||||
@@ -216,7 +220,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) {
 | 
				
			|||||||
// the underlying file.
 | 
					// the underlying file.
 | 
				
			||||||
func (r *BackupFileReader) Close() error {
 | 
					func (r *BackupFileReader) Close() error {
 | 
				
			||||||
	if r.ctx != 0 {
 | 
						if r.ctx != 0 {
 | 
				
			||||||
		backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
 | 
							_ = backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
 | 
				
			||||||
		runtime.KeepAlive(r.f)
 | 
							runtime.KeepAlive(r.f)
 | 
				
			||||||
		r.ctx = 0
 | 
							r.ctx = 0
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -242,7 +246,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) {
 | 
				
			|||||||
	var bytesWritten uint32
 | 
						var bytesWritten uint32
 | 
				
			||||||
	err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
 | 
						err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, &os.PathError{"BackupWrite", w.f.Name(), err}
 | 
							return 0, &os.PathError{Op: "BackupWrite", Path: w.f.Name(), Err: err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	runtime.KeepAlive(w.f)
 | 
						runtime.KeepAlive(w.f)
 | 
				
			||||||
	if int(bytesWritten) != len(b) {
 | 
						if int(bytesWritten) != len(b) {
 | 
				
			||||||
@@ -255,7 +259,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) {
 | 
				
			|||||||
// close the underlying file.
 | 
					// close the underlying file.
 | 
				
			||||||
func (w *BackupFileWriter) Close() error {
 | 
					func (w *BackupFileWriter) Close() error {
 | 
				
			||||||
	if w.ctx != 0 {
 | 
						if w.ctx != 0 {
 | 
				
			||||||
		backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
 | 
							_ = backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
 | 
				
			||||||
		runtime.KeepAlive(w.f)
 | 
							runtime.KeepAlive(w.f)
 | 
				
			||||||
		w.ctx = 0
 | 
							w.ctx = 0
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -271,7 +275,13 @@ func OpenForBackup(path string, access uint32, share uint32, createmode uint32)
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0)
 | 
						h, err := syscall.CreateFile(&winPath[0],
 | 
				
			||||||
 | 
							access,
 | 
				
			||||||
 | 
							share,
 | 
				
			||||||
 | 
							nil,
 | 
				
			||||||
 | 
							createmode,
 | 
				
			||||||
 | 
							syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT,
 | 
				
			||||||
 | 
							0)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		err = &os.PathError{Op: "open", Path: path, Err: err}
 | 
							err = &os.PathError{Op: "open", Path: path, Err: err}
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										22
									
								
								vendor/github.com/Microsoft/go-winio/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/Microsoft/go-winio/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					// This package provides utilities for efficiently performing Win32 IO operations in Go.
 | 
				
			||||||
 | 
					// Currently, this package is provides support for genreal IO and management of
 | 
				
			||||||
 | 
					//   - named pipes
 | 
				
			||||||
 | 
					//   - files
 | 
				
			||||||
 | 
					//   - [Hyper-V sockets]
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This code is similar to Go's [net] package, and uses IO completion ports to avoid
 | 
				
			||||||
 | 
					// blocking IO on system threads, allowing Go to reuse the thread to schedule other goroutines.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This limits support to Windows Vista and newer operating systems.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Additionally, this package provides support for:
 | 
				
			||||||
 | 
					//   - creating and managing GUIDs
 | 
				
			||||||
 | 
					//   - writing to [ETW]
 | 
				
			||||||
 | 
					//   - opening and manageing VHDs
 | 
				
			||||||
 | 
					//   - parsing [Windows Image files]
 | 
				
			||||||
 | 
					//   - auto-generating Win32 API code
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// [Hyper-V sockets]: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service
 | 
				
			||||||
 | 
					// [ETW]: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-
 | 
				
			||||||
 | 
					// [Windows Image files]: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/work-with-windows-images
 | 
				
			||||||
 | 
					package winio
 | 
				
			||||||
							
								
								
									
										8
									
								
								vendor/github.com/Microsoft/go-winio/ea.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/Microsoft/go-winio/ea.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -33,7 +33,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
 | 
				
			|||||||
	err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
 | 
						err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		err = errInvalidEaBuffer
 | 
							err = errInvalidEaBuffer
 | 
				
			||||||
		return
 | 
							return ea, nb, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nameOffset := fileFullEaInformationSize
 | 
						nameOffset := fileFullEaInformationSize
 | 
				
			||||||
@@ -43,7 +43,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
 | 
				
			|||||||
	nextOffset := int(info.NextEntryOffset)
 | 
						nextOffset := int(info.NextEntryOffset)
 | 
				
			||||||
	if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
 | 
						if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
 | 
				
			||||||
		err = errInvalidEaBuffer
 | 
							err = errInvalidEaBuffer
 | 
				
			||||||
		return
 | 
							return ea, nb, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ea.Name = string(b[nameOffset : nameOffset+nameLen])
 | 
						ea.Name = string(b[nameOffset : nameOffset+nameLen])
 | 
				
			||||||
@@ -52,7 +52,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
 | 
				
			|||||||
	if info.NextEntryOffset != 0 {
 | 
						if info.NextEntryOffset != 0 {
 | 
				
			||||||
		nb = b[info.NextEntryOffset:]
 | 
							nb = b[info.NextEntryOffset:]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return ea, nb, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
 | 
					// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
 | 
				
			||||||
@@ -67,7 +67,7 @@ func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
 | 
				
			|||||||
		eas = append(eas, ea)
 | 
							eas = append(eas, ea)
 | 
				
			||||||
		b = nb
 | 
							b = nb
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return eas, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
 | 
					func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										70
									
								
								vendor/github.com/Microsoft/go-winio/file.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								vendor/github.com/Microsoft/go-winio/file.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
@@ -10,6 +11,8 @@ import (
 | 
				
			|||||||
	"sync/atomic"
 | 
						"sync/atomic"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
 | 
					//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
 | 
				
			||||||
@@ -23,6 +26,8 @@ type atomicBool int32
 | 
				
			|||||||
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
 | 
					func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
 | 
				
			||||||
func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }
 | 
					func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }
 | 
				
			||||||
func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
 | 
					func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//revive:disable-next-line:predeclared Keep "new" to maintain consistency with "atomic" pkg
 | 
				
			||||||
func (b *atomicBool) swap(new bool) bool {
 | 
					func (b *atomicBool) swap(new bool) bool {
 | 
				
			||||||
	var newInt int32
 | 
						var newInt int32
 | 
				
			||||||
	if new {
 | 
						if new {
 | 
				
			||||||
@@ -31,11 +36,6 @@ func (b *atomicBool) swap(new bool) bool {
 | 
				
			|||||||
	return atomic.SwapInt32((*int32)(b), newInt) == 1
 | 
						return atomic.SwapInt32((*int32)(b), newInt) == 1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
 | 
					 | 
				
			||||||
	cFILE_SKIP_SET_EVENT_ON_HANDLE        = 2
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	ErrFileClosed = errors.New("file has already been closed")
 | 
						ErrFileClosed = errors.New("file has already been closed")
 | 
				
			||||||
	ErrTimeout    = &timeoutError{}
 | 
						ErrTimeout    = &timeoutError{}
 | 
				
			||||||
@@ -43,28 +43,28 @@ var (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type timeoutError struct{}
 | 
					type timeoutError struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *timeoutError) Error() string   { return "i/o timeout" }
 | 
					func (*timeoutError) Error() string   { return "i/o timeout" }
 | 
				
			||||||
func (e *timeoutError) Timeout() bool   { return true }
 | 
					func (*timeoutError) Timeout() bool   { return true }
 | 
				
			||||||
func (e *timeoutError) Temporary() bool { return true }
 | 
					func (*timeoutError) Temporary() bool { return true }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type timeoutChan chan struct{}
 | 
					type timeoutChan chan struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ioInitOnce sync.Once
 | 
					var ioInitOnce sync.Once
 | 
				
			||||||
var ioCompletionPort syscall.Handle
 | 
					var ioCompletionPort syscall.Handle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ioResult contains the result of an asynchronous IO operation
 | 
					// ioResult contains the result of an asynchronous IO operation.
 | 
				
			||||||
type ioResult struct {
 | 
					type ioResult struct {
 | 
				
			||||||
	bytes uint32
 | 
						bytes uint32
 | 
				
			||||||
	err   error
 | 
						err   error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ioOperation represents an outstanding asynchronous Win32 IO
 | 
					// ioOperation represents an outstanding asynchronous Win32 IO.
 | 
				
			||||||
type ioOperation struct {
 | 
					type ioOperation struct {
 | 
				
			||||||
	o  syscall.Overlapped
 | 
						o  syscall.Overlapped
 | 
				
			||||||
	ch chan ioResult
 | 
						ch chan ioResult
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func initIo() {
 | 
					func initIO() {
 | 
				
			||||||
	h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
 | 
						h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
@@ -93,15 +93,15 @@ type deadlineHandler struct {
 | 
				
			|||||||
	timedout    atomicBool
 | 
						timedout    atomicBool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// makeWin32File makes a new win32File from an existing file handle
 | 
					// makeWin32File makes a new win32File from an existing file handle.
 | 
				
			||||||
func makeWin32File(h syscall.Handle) (*win32File, error) {
 | 
					func makeWin32File(h syscall.Handle) (*win32File, error) {
 | 
				
			||||||
	f := &win32File{handle: h}
 | 
						f := &win32File{handle: h}
 | 
				
			||||||
	ioInitOnce.Do(initIo)
 | 
						ioInitOnce.Do(initIO)
 | 
				
			||||||
	_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
 | 
						_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE)
 | 
						err = setFileCompletionNotificationModes(h, windows.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS|windows.FILE_SKIP_SET_EVENT_ON_HANDLE)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -120,14 +120,14 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
 | 
				
			|||||||
	return f, nil
 | 
						return f, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// closeHandle closes the resources associated with a Win32 handle
 | 
					// closeHandle closes the resources associated with a Win32 handle.
 | 
				
			||||||
func (f *win32File) closeHandle() {
 | 
					func (f *win32File) closeHandle() {
 | 
				
			||||||
	f.wgLock.Lock()
 | 
						f.wgLock.Lock()
 | 
				
			||||||
	// Atomically set that we are closing, releasing the resources only once.
 | 
						// Atomically set that we are closing, releasing the resources only once.
 | 
				
			||||||
	if !f.closing.swap(true) {
 | 
						if !f.closing.swap(true) {
 | 
				
			||||||
		f.wgLock.Unlock()
 | 
							f.wgLock.Unlock()
 | 
				
			||||||
		// cancel all IO and wait for it to complete
 | 
							// cancel all IO and wait for it to complete
 | 
				
			||||||
		cancelIoEx(f.handle, nil)
 | 
							_ = cancelIoEx(f.handle, nil)
 | 
				
			||||||
		f.wg.Wait()
 | 
							f.wg.Wait()
 | 
				
			||||||
		// at this point, no new IO can start
 | 
							// at this point, no new IO can start
 | 
				
			||||||
		syscall.Close(f.handle)
 | 
							syscall.Close(f.handle)
 | 
				
			||||||
@@ -143,9 +143,14 @@ func (f *win32File) Close() error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// prepareIo prepares for a new IO operation.
 | 
					// IsClosed checks if the file has been closed.
 | 
				
			||||||
 | 
					func (f *win32File) IsClosed() bool {
 | 
				
			||||||
 | 
						return f.closing.isSet()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// prepareIO prepares for a new IO operation.
 | 
				
			||||||
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
 | 
					// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
 | 
				
			||||||
func (f *win32File) prepareIo() (*ioOperation, error) {
 | 
					func (f *win32File) prepareIO() (*ioOperation, error) {
 | 
				
			||||||
	f.wgLock.RLock()
 | 
						f.wgLock.RLock()
 | 
				
			||||||
	if f.closing.isSet() {
 | 
						if f.closing.isSet() {
 | 
				
			||||||
		f.wgLock.RUnlock()
 | 
							f.wgLock.RUnlock()
 | 
				
			||||||
@@ -158,7 +163,7 @@ func (f *win32File) prepareIo() (*ioOperation, error) {
 | 
				
			|||||||
	return c, nil
 | 
						return c, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ioCompletionProcessor processes completed async IOs forever
 | 
					// ioCompletionProcessor processes completed async IOs forever.
 | 
				
			||||||
func ioCompletionProcessor(h syscall.Handle) {
 | 
					func ioCompletionProcessor(h syscall.Handle) {
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		var bytes uint32
 | 
							var bytes uint32
 | 
				
			||||||
@@ -172,15 +177,17 @@ func ioCompletionProcessor(h syscall.Handle) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// asyncIo processes the return value from ReadFile or WriteFile, blocking until
 | 
					// todo: helsaawy - create an asyncIO version that takes a context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// asyncIO processes the return value from ReadFile or WriteFile, blocking until
 | 
				
			||||||
// the operation has actually completed.
 | 
					// the operation has actually completed.
 | 
				
			||||||
func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
 | 
					func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
 | 
				
			||||||
	if err != syscall.ERROR_IO_PENDING {
 | 
						if err != syscall.ERROR_IO_PENDING { //nolint:errorlint // err is Errno
 | 
				
			||||||
		return int(bytes), err
 | 
							return int(bytes), err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if f.closing.isSet() {
 | 
						if f.closing.isSet() {
 | 
				
			||||||
		cancelIoEx(f.handle, &c.o)
 | 
							_ = cancelIoEx(f.handle, &c.o)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var timeout timeoutChan
 | 
						var timeout timeoutChan
 | 
				
			||||||
@@ -194,7 +201,7 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
 | 
				
			|||||||
	select {
 | 
						select {
 | 
				
			||||||
	case r = <-c.ch:
 | 
						case r = <-c.ch:
 | 
				
			||||||
		err = r.err
 | 
							err = r.err
 | 
				
			||||||
		if err == syscall.ERROR_OPERATION_ABORTED {
 | 
							if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
 | 
				
			||||||
			if f.closing.isSet() {
 | 
								if f.closing.isSet() {
 | 
				
			||||||
				err = ErrFileClosed
 | 
									err = ErrFileClosed
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -204,10 +211,10 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
 | 
				
			|||||||
			err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
 | 
								err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case <-timeout:
 | 
						case <-timeout:
 | 
				
			||||||
		cancelIoEx(f.handle, &c.o)
 | 
							_ = cancelIoEx(f.handle, &c.o)
 | 
				
			||||||
		r = <-c.ch
 | 
							r = <-c.ch
 | 
				
			||||||
		err = r.err
 | 
							err = r.err
 | 
				
			||||||
		if err == syscall.ERROR_OPERATION_ABORTED {
 | 
							if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
 | 
				
			||||||
			err = ErrTimeout
 | 
								err = ErrTimeout
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -215,13 +222,14 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
 | 
				
			|||||||
	// runtime.KeepAlive is needed, as c is passed via native
 | 
						// runtime.KeepAlive is needed, as c is passed via native
 | 
				
			||||||
	// code to ioCompletionProcessor, c must remain alive
 | 
						// code to ioCompletionProcessor, c must remain alive
 | 
				
			||||||
	// until the channel read is complete.
 | 
						// until the channel read is complete.
 | 
				
			||||||
 | 
						// todo: (de)allocate *ioOperation via win32 heap functions, instead of needing to KeepAlive?
 | 
				
			||||||
	runtime.KeepAlive(c)
 | 
						runtime.KeepAlive(c)
 | 
				
			||||||
	return int(r.bytes), err
 | 
						return int(r.bytes), err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Read reads from a file handle.
 | 
					// Read reads from a file handle.
 | 
				
			||||||
func (f *win32File) Read(b []byte) (int, error) {
 | 
					func (f *win32File) Read(b []byte) (int, error) {
 | 
				
			||||||
	c, err := f.prepareIo()
 | 
						c, err := f.prepareIO()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, err
 | 
							return 0, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -233,13 +241,13 @@ func (f *win32File) Read(b []byte) (int, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var bytes uint32
 | 
						var bytes uint32
 | 
				
			||||||
	err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
 | 
						err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
 | 
				
			||||||
	n, err := f.asyncIo(c, &f.readDeadline, bytes, err)
 | 
						n, err := f.asyncIO(c, &f.readDeadline, bytes, err)
 | 
				
			||||||
	runtime.KeepAlive(b)
 | 
						runtime.KeepAlive(b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Handle EOF conditions.
 | 
						// Handle EOF conditions.
 | 
				
			||||||
	if err == nil && n == 0 && len(b) != 0 {
 | 
						if err == nil && n == 0 && len(b) != 0 {
 | 
				
			||||||
		return 0, io.EOF
 | 
							return 0, io.EOF
 | 
				
			||||||
	} else if err == syscall.ERROR_BROKEN_PIPE {
 | 
						} else if err == syscall.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno
 | 
				
			||||||
		return 0, io.EOF
 | 
							return 0, io.EOF
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return n, err
 | 
							return n, err
 | 
				
			||||||
@@ -248,7 +256,7 @@ func (f *win32File) Read(b []byte) (int, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Write writes to a file handle.
 | 
					// Write writes to a file handle.
 | 
				
			||||||
func (f *win32File) Write(b []byte) (int, error) {
 | 
					func (f *win32File) Write(b []byte) (int, error) {
 | 
				
			||||||
	c, err := f.prepareIo()
 | 
						c, err := f.prepareIO()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, err
 | 
							return 0, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -260,7 +268,7 @@ func (f *win32File) Write(b []byte) (int, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var bytes uint32
 | 
						var bytes uint32
 | 
				
			||||||
	err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
 | 
						err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
 | 
				
			||||||
	n, err := f.asyncIo(c, &f.writeDeadline, bytes, err)
 | 
						n, err := f.asyncIO(c, &f.writeDeadline, bytes, err)
 | 
				
			||||||
	runtime.KeepAlive(b)
 | 
						runtime.KeepAlive(b)
 | 
				
			||||||
	return n, err
 | 
						return n, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								vendor/github.com/Microsoft/go-winio/fileinfo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/Microsoft/go-winio/fileinfo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
@@ -14,13 +15,18 @@ import (
 | 
				
			|||||||
type FileBasicInfo struct {
 | 
					type FileBasicInfo struct {
 | 
				
			||||||
	CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
 | 
						CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
 | 
				
			||||||
	FileAttributes                                          uint32
 | 
						FileAttributes                                          uint32
 | 
				
			||||||
	pad                                                     uint32 // padding
 | 
						_                                                       uint32 // padding
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetFileBasicInfo retrieves times and attributes for a file.
 | 
					// GetFileBasicInfo retrieves times and attributes for a file.
 | 
				
			||||||
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
 | 
					func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
 | 
				
			||||||
	bi := &FileBasicInfo{}
 | 
						bi := &FileBasicInfo{}
 | 
				
			||||||
	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
 | 
						if err := windows.GetFileInformationByHandleEx(
 | 
				
			||||||
 | 
							windows.Handle(f.Fd()),
 | 
				
			||||||
 | 
							windows.FileBasicInfo,
 | 
				
			||||||
 | 
							(*byte)(unsafe.Pointer(bi)),
 | 
				
			||||||
 | 
							uint32(unsafe.Sizeof(*bi)),
 | 
				
			||||||
 | 
						); err != nil {
 | 
				
			||||||
		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
 | 
							return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	runtime.KeepAlive(f)
 | 
						runtime.KeepAlive(f)
 | 
				
			||||||
@@ -29,7 +35,12 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// SetFileBasicInfo sets times and attributes for a file.
 | 
					// SetFileBasicInfo sets times and attributes for a file.
 | 
				
			||||||
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
 | 
					func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
 | 
				
			||||||
	if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
 | 
						if err := windows.SetFileInformationByHandle(
 | 
				
			||||||
 | 
							windows.Handle(f.Fd()),
 | 
				
			||||||
 | 
							windows.FileBasicInfo,
 | 
				
			||||||
 | 
							(*byte)(unsafe.Pointer(bi)),
 | 
				
			||||||
 | 
							uint32(unsafe.Sizeof(*bi)),
 | 
				
			||||||
 | 
						); err != nil {
 | 
				
			||||||
		return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
 | 
							return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	runtime.KeepAlive(f)
 | 
						runtime.KeepAlive(f)
 | 
				
			||||||
@@ -48,7 +59,10 @@ type FileStandardInfo struct {
 | 
				
			|||||||
// GetFileStandardInfo retrieves ended information for the file.
 | 
					// GetFileStandardInfo retrieves ended information for the file.
 | 
				
			||||||
func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
 | 
					func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
 | 
				
			||||||
	si := &FileStandardInfo{}
 | 
						si := &FileStandardInfo{}
 | 
				
			||||||
	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil {
 | 
						if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()),
 | 
				
			||||||
 | 
							windows.FileStandardInfo,
 | 
				
			||||||
 | 
							(*byte)(unsafe.Pointer(si)),
 | 
				
			||||||
 | 
							uint32(unsafe.Sizeof(*si))); err != nil {
 | 
				
			||||||
		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
 | 
							return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	runtime.KeepAlive(f)
 | 
						runtime.KeepAlive(f)
 | 
				
			||||||
@@ -65,7 +79,12 @@ type FileIDInfo struct {
 | 
				
			|||||||
// GetFileID retrieves the unique (volume, file ID) pair for a file.
 | 
					// GetFileID retrieves the unique (volume, file ID) pair for a file.
 | 
				
			||||||
func GetFileID(f *os.File) (*FileIDInfo, error) {
 | 
					func GetFileID(f *os.File) (*FileIDInfo, error) {
 | 
				
			||||||
	fileID := &FileIDInfo{}
 | 
						fileID := &FileIDInfo{}
 | 
				
			||||||
	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
 | 
						if err := windows.GetFileInformationByHandleEx(
 | 
				
			||||||
 | 
							windows.Handle(f.Fd()),
 | 
				
			||||||
 | 
							windows.FileIdInfo,
 | 
				
			||||||
 | 
							(*byte)(unsafe.Pointer(fileID)),
 | 
				
			||||||
 | 
							uint32(unsafe.Sizeof(*fileID)),
 | 
				
			||||||
 | 
						); err != nil {
 | 
				
			||||||
		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
 | 
							return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	runtime.KeepAlive(f)
 | 
						runtime.KeepAlive(f)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										360
									
								
								vendor/github.com/Microsoft/go-winio/hvsock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										360
									
								
								vendor/github.com/Microsoft/go-winio/hvsock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,8 +1,11 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
@@ -11,16 +14,87 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
	"unsafe"
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/Microsoft/go-winio/internal/socket"
 | 
				
			||||||
	"github.com/Microsoft/go-winio/pkg/guid"
 | 
						"github.com/Microsoft/go-winio/pkg/guid"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
 | 
					const afHVSock = 34 // AF_HYPERV
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					// Well known Service and VM IDs
 | 
				
			||||||
	afHvSock = 34 // AF_HYPERV
 | 
					//https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service#vmid-wildcards
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	socketError = ^uintptr(0)
 | 
					// HvsockGUIDWildcard is the wildcard VmId for accepting connections from all partitions.
 | 
				
			||||||
)
 | 
					func HvsockGUIDWildcard() guid.GUID { // 00000000-0000-0000-0000-000000000000
 | 
				
			||||||
 | 
						return guid.GUID{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HvsockGUIDBroadcast is the wildcard VmId for broadcasting sends to all partitions.
 | 
				
			||||||
 | 
					func HvsockGUIDBroadcast() guid.GUID { //ffffffff-ffff-ffff-ffff-ffffffffffff
 | 
				
			||||||
 | 
						return guid.GUID{
 | 
				
			||||||
 | 
							Data1: 0xffffffff,
 | 
				
			||||||
 | 
							Data2: 0xffff,
 | 
				
			||||||
 | 
							Data3: 0xffff,
 | 
				
			||||||
 | 
							Data4: [8]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HvsockGUIDLoopback is the Loopback VmId for accepting connections to the same partition as the connector.
 | 
				
			||||||
 | 
					func HvsockGUIDLoopback() guid.GUID { // e0e16197-dd56-4a10-9195-5ee7a155a838
 | 
				
			||||||
 | 
						return guid.GUID{
 | 
				
			||||||
 | 
							Data1: 0xe0e16197,
 | 
				
			||||||
 | 
							Data2: 0xdd56,
 | 
				
			||||||
 | 
							Data3: 0x4a10,
 | 
				
			||||||
 | 
							Data4: [8]uint8{0x91, 0x95, 0x5e, 0xe7, 0xa1, 0x55, 0xa8, 0x38},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HvsockGUIDSiloHost is the address of a silo's host partition:
 | 
				
			||||||
 | 
					//   - The silo host of a hosted silo is the utility VM.
 | 
				
			||||||
 | 
					//   - The silo host of a silo on a physical host is the physical host.
 | 
				
			||||||
 | 
					func HvsockGUIDSiloHost() guid.GUID { // 36bd0c5c-7276-4223-88ba-7d03b654c568
 | 
				
			||||||
 | 
						return guid.GUID{
 | 
				
			||||||
 | 
							Data1: 0x36bd0c5c,
 | 
				
			||||||
 | 
							Data2: 0x7276,
 | 
				
			||||||
 | 
							Data3: 0x4223,
 | 
				
			||||||
 | 
							Data4: [8]byte{0x88, 0xba, 0x7d, 0x03, 0xb6, 0x54, 0xc5, 0x68},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HvsockGUIDChildren is the wildcard VmId for accepting connections from the connector's child partitions.
 | 
				
			||||||
 | 
					func HvsockGUIDChildren() guid.GUID { // 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd
 | 
				
			||||||
 | 
						return guid.GUID{
 | 
				
			||||||
 | 
							Data1: 0x90db8b89,
 | 
				
			||||||
 | 
							Data2: 0xd35,
 | 
				
			||||||
 | 
							Data3: 0x4f79,
 | 
				
			||||||
 | 
							Data4: [8]uint8{0x8c, 0xe9, 0x49, 0xea, 0xa, 0xc8, 0xb7, 0xcd},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HvsockGUIDParent is the wildcard VmId for accepting connections from the connector's parent partition.
 | 
				
			||||||
 | 
					// Listening on this VmId accepts connection from:
 | 
				
			||||||
 | 
					//   - Inside silos: silo host partition.
 | 
				
			||||||
 | 
					//   - Inside hosted silo: host of the VM.
 | 
				
			||||||
 | 
					//   - Inside VM: VM host.
 | 
				
			||||||
 | 
					//   - Physical host: Not supported.
 | 
				
			||||||
 | 
					func HvsockGUIDParent() guid.GUID { // a42e7cda-d03f-480c-9cc2-a4de20abb878
 | 
				
			||||||
 | 
						return guid.GUID{
 | 
				
			||||||
 | 
							Data1: 0xa42e7cda,
 | 
				
			||||||
 | 
							Data2: 0xd03f,
 | 
				
			||||||
 | 
							Data3: 0x480c,
 | 
				
			||||||
 | 
							Data4: [8]uint8{0x9c, 0xc2, 0xa4, 0xde, 0x20, 0xab, 0xb8, 0x78},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// hvsockVsockServiceTemplate is the Service GUID used for the VSOCK protocol.
 | 
				
			||||||
 | 
					func hvsockVsockServiceTemplate() guid.GUID { // 00000000-facb-11e6-bd58-64006a7986d3
 | 
				
			||||||
 | 
						return guid.GUID{
 | 
				
			||||||
 | 
							Data2: 0xfacb,
 | 
				
			||||||
 | 
							Data3: 0x11e6,
 | 
				
			||||||
 | 
							Data4: [8]uint8{0xbd, 0x58, 0x64, 0x00, 0x6a, 0x79, 0x86, 0xd3},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// An HvsockAddr is an address for a AF_HYPERV socket.
 | 
					// An HvsockAddr is an address for a AF_HYPERV socket.
 | 
				
			||||||
type HvsockAddr struct {
 | 
					type HvsockAddr struct {
 | 
				
			||||||
@@ -35,8 +109,10 @@ type rawHvsockAddr struct {
 | 
				
			|||||||
	ServiceID guid.GUID
 | 
						ServiceID guid.GUID
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ socket.RawSockaddr = &rawHvsockAddr{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Network returns the address's network name, "hvsock".
 | 
					// Network returns the address's network name, "hvsock".
 | 
				
			||||||
func (addr *HvsockAddr) Network() string {
 | 
					func (*HvsockAddr) Network() string {
 | 
				
			||||||
	return "hvsock"
 | 
						return "hvsock"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,14 +122,14 @@ func (addr *HvsockAddr) String() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
 | 
					// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
 | 
				
			||||||
func VsockServiceID(port uint32) guid.GUID {
 | 
					func VsockServiceID(port uint32) guid.GUID {
 | 
				
			||||||
	g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3")
 | 
						g := hvsockVsockServiceTemplate() // make a copy
 | 
				
			||||||
	g.Data1 = port
 | 
						g.Data1 = port
 | 
				
			||||||
	return g
 | 
						return g
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (addr *HvsockAddr) raw() rawHvsockAddr {
 | 
					func (addr *HvsockAddr) raw() rawHvsockAddr {
 | 
				
			||||||
	return rawHvsockAddr{
 | 
						return rawHvsockAddr{
 | 
				
			||||||
		Family:    afHvSock,
 | 
							Family:    afHVSock,
 | 
				
			||||||
		VMID:      addr.VMID,
 | 
							VMID:      addr.VMID,
 | 
				
			||||||
		ServiceID: addr.ServiceID,
 | 
							ServiceID: addr.ServiceID,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -64,20 +140,48 @@ func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) {
 | 
				
			|||||||
	addr.ServiceID = raw.ServiceID
 | 
						addr.ServiceID = raw.ServiceID
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sockaddr returns a pointer to and the size of this struct.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Implements the [socket.RawSockaddr] interface, and allows use in
 | 
				
			||||||
 | 
					// [socket.Bind] and [socket.ConnectEx].
 | 
				
			||||||
 | 
					func (r *rawHvsockAddr) Sockaddr() (unsafe.Pointer, int32, error) {
 | 
				
			||||||
 | 
						return unsafe.Pointer(r), int32(unsafe.Sizeof(rawHvsockAddr{})), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sockaddr interface allows use with `sockets.Bind()` and `.ConnectEx()`.
 | 
				
			||||||
 | 
					func (r *rawHvsockAddr) FromBytes(b []byte) error {
 | 
				
			||||||
 | 
						n := int(unsafe.Sizeof(rawHvsockAddr{}))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(b) < n {
 | 
				
			||||||
 | 
							return fmt.Errorf("got %d, want %d: %w", len(b), n, socket.ErrBufferSize)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						copy(unsafe.Slice((*byte)(unsafe.Pointer(r)), n), b[:n])
 | 
				
			||||||
 | 
						if r.Family != afHVSock {
 | 
				
			||||||
 | 
							return fmt.Errorf("got %d, want %d: %w", r.Family, afHVSock, socket.ErrAddrFamily)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HvsockListener is a socket listener for the AF_HYPERV address family.
 | 
					// HvsockListener is a socket listener for the AF_HYPERV address family.
 | 
				
			||||||
type HvsockListener struct {
 | 
					type HvsockListener struct {
 | 
				
			||||||
	sock *win32File
 | 
						sock *win32File
 | 
				
			||||||
	addr HvsockAddr
 | 
						addr HvsockAddr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ net.Listener = &HvsockListener{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HvsockConn is a connected socket of the AF_HYPERV address family.
 | 
					// HvsockConn is a connected socket of the AF_HYPERV address family.
 | 
				
			||||||
type HvsockConn struct {
 | 
					type HvsockConn struct {
 | 
				
			||||||
	sock          *win32File
 | 
						sock          *win32File
 | 
				
			||||||
	local, remote HvsockAddr
 | 
						local, remote HvsockAddr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newHvSocket() (*win32File, error) {
 | 
					var _ net.Conn = &HvsockConn{}
 | 
				
			||||||
	fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1)
 | 
					
 | 
				
			||||||
 | 
					func newHVSocket() (*win32File, error) {
 | 
				
			||||||
 | 
						fd, err := syscall.Socket(afHVSock, syscall.SOCK_STREAM, 1)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, os.NewSyscallError("socket", err)
 | 
							return nil, os.NewSyscallError("socket", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -93,12 +197,12 @@ func newHvSocket() (*win32File, error) {
 | 
				
			|||||||
// ListenHvsock listens for connections on the specified hvsock address.
 | 
					// ListenHvsock listens for connections on the specified hvsock address.
 | 
				
			||||||
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
 | 
					func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
 | 
				
			||||||
	l := &HvsockListener{addr: *addr}
 | 
						l := &HvsockListener{addr: *addr}
 | 
				
			||||||
	sock, err := newHvSocket()
 | 
						sock, err := newHVSocket()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, l.opErr("listen", err)
 | 
							return nil, l.opErr("listen", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sa := addr.raw()
 | 
						sa := addr.raw()
 | 
				
			||||||
	err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa)))
 | 
						err = socket.Bind(windows.Handle(sock.handle), &sa)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, l.opErr("listen", os.NewSyscallError("socket", err))
 | 
							return nil, l.opErr("listen", os.NewSyscallError("socket", err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -120,7 +224,7 @@ func (l *HvsockListener) Addr() net.Addr {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Accept waits for the next connection and returns it.
 | 
					// Accept waits for the next connection and returns it.
 | 
				
			||||||
func (l *HvsockListener) Accept() (_ net.Conn, err error) {
 | 
					func (l *HvsockListener) Accept() (_ net.Conn, err error) {
 | 
				
			||||||
	sock, err := newHvSocket()
 | 
						sock, err := newHVSocket()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, l.opErr("accept", err)
 | 
							return nil, l.opErr("accept", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -129,27 +233,42 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) {
 | 
				
			|||||||
			sock.Close()
 | 
								sock.Close()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
	c, err := l.sock.prepareIo()
 | 
						c, err := l.sock.prepareIO()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, l.opErr("accept", err)
 | 
							return nil, l.opErr("accept", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer l.sock.wg.Done()
 | 
						defer l.sock.wg.Done()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// AcceptEx, per documentation, requires an extra 16 bytes per address.
 | 
						// AcceptEx, per documentation, requires an extra 16 bytes per address.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex
 | 
				
			||||||
	const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
 | 
						const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
 | 
				
			||||||
	var addrbuf [addrlen * 2]byte
 | 
						var addrbuf [addrlen * 2]byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var bytes uint32
 | 
						var bytes uint32
 | 
				
			||||||
	err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o)
 | 
						err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /*rxdatalen*/, addrlen, addrlen, &bytes, &c.o)
 | 
				
			||||||
	_, err = l.sock.asyncIo(c, nil, bytes, err)
 | 
						if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil {
 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
 | 
							return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	conn := &HvsockConn{
 | 
						conn := &HvsockConn{
 | 
				
			||||||
		sock: sock,
 | 
							sock: sock,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// The local address returned in the AcceptEx buffer is the same as the Listener socket's
 | 
				
			||||||
 | 
						// address. However, the service GUID reported by GetSockName is different from the Listeners
 | 
				
			||||||
 | 
						// socket, and is sometimes the same as the local address of the socket that dialed the
 | 
				
			||||||
 | 
						// address, with the service GUID.Data1 incremented, but othertimes is different.
 | 
				
			||||||
 | 
						// todo: does the local address matter? is the listener's address or the actual address appropriate?
 | 
				
			||||||
	conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
 | 
						conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
 | 
				
			||||||
	conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
 | 
						conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// initialize the accepted socket and update its properties with those of the listening socket
 | 
				
			||||||
 | 
						if err = windows.Setsockopt(windows.Handle(sock.handle),
 | 
				
			||||||
 | 
							windows.SOL_SOCKET, windows.SO_UPDATE_ACCEPT_CONTEXT,
 | 
				
			||||||
 | 
							(*byte)(unsafe.Pointer(&l.sock.handle)), int32(unsafe.Sizeof(l.sock.handle))); err != nil {
 | 
				
			||||||
 | 
							return nil, conn.opErr("accept", os.NewSyscallError("setsockopt", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sock = nil
 | 
						sock = nil
 | 
				
			||||||
	return conn, nil
 | 
						return conn, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -159,43 +278,171 @@ func (l *HvsockListener) Close() error {
 | 
				
			|||||||
	return l.sock.Close()
 | 
						return l.sock.Close()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Need to finish ConnectEx handling
 | 
					// HvsockDialer configures and dials a Hyper-V Socket (ie, [HvsockConn]).
 | 
				
			||||||
func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) {
 | 
					type HvsockDialer struct {
 | 
				
			||||||
	sock, err := newHvSocket()
 | 
						// Deadline is the time the Dial operation must connect before erroring.
 | 
				
			||||||
 | 
						Deadline time.Time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Retries is the number of additional connects to try if the connection times out, is refused,
 | 
				
			||||||
 | 
						// or the host is unreachable
 | 
				
			||||||
 | 
						Retries uint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RetryWait is the time to wait after a connection error to retry
 | 
				
			||||||
 | 
						RetryWait time.Duration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rt *time.Timer // redial wait timer
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Dial the Hyper-V socket at addr.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See [HvsockDialer.Dial] for more information.
 | 
				
			||||||
 | 
					func Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) {
 | 
				
			||||||
 | 
						return (&HvsockDialer{}).Dial(ctx, addr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Dial attempts to connect to the Hyper-V socket at addr, and returns a connection if successful.
 | 
				
			||||||
 | 
					// Will attempt (HvsockDialer).Retries if dialing fails, waiting (HvsockDialer).RetryWait between
 | 
				
			||||||
 | 
					// retries.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Dialing can be cancelled either by providing (HvsockDialer).Deadline, or cancelling ctx.
 | 
				
			||||||
 | 
					func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) {
 | 
				
			||||||
 | 
						op := "dial"
 | 
				
			||||||
 | 
						// create the conn early to use opErr()
 | 
				
			||||||
 | 
						conn = &HvsockConn{
 | 
				
			||||||
 | 
							remote: *addr,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !d.Deadline.IsZero() {
 | 
				
			||||||
 | 
							var cancel context.CancelFunc
 | 
				
			||||||
 | 
							ctx, cancel = context.WithDeadline(ctx, d.Deadline)
 | 
				
			||||||
 | 
							defer cancel()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// preemptive timeout/cancellation check
 | 
				
			||||||
 | 
						if err = ctx.Err(); err != nil {
 | 
				
			||||||
 | 
							return nil, conn.opErr(op, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sock, err := newHVSocket()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, conn.opErr(op, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		if sock != nil {
 | 
							if sock != nil {
 | 
				
			||||||
			sock.Close()
 | 
								sock.Close()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
	c, err := sock.prepareIo()
 | 
					
 | 
				
			||||||
 | 
						sa := addr.raw()
 | 
				
			||||||
 | 
						err = socket.Bind(windows.Handle(sock.handle), &sa)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, conn.opErr(op, os.NewSyscallError("bind", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c, err := sock.prepareIO()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, conn.opErr(op, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer sock.wg.Done()
 | 
						defer sock.wg.Done()
 | 
				
			||||||
	var bytes uint32
 | 
						var bytes uint32
 | 
				
			||||||
	err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o)
 | 
						for i := uint(0); i <= d.Retries; i++ {
 | 
				
			||||||
	_, err = sock.asyncIo(ctx, c, nil, bytes, err)
 | 
							err = socket.ConnectEx(
 | 
				
			||||||
 | 
								windows.Handle(sock.handle),
 | 
				
			||||||
 | 
								&sa,
 | 
				
			||||||
 | 
								nil, // sendBuf
 | 
				
			||||||
 | 
								0,   // sendDataLen
 | 
				
			||||||
 | 
								&bytes,
 | 
				
			||||||
 | 
								(*windows.Overlapped)(unsafe.Pointer(&c.o)))
 | 
				
			||||||
 | 
							_, err = sock.asyncIO(c, nil, bytes, err)
 | 
				
			||||||
 | 
							if i < d.Retries && canRedial(err) {
 | 
				
			||||||
 | 
								if err = d.redialWait(ctx); err == nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, conn.opErr(op, os.NewSyscallError("connectex", err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	conn := &HvsockConn{
 | 
					
 | 
				
			||||||
		sock:   sock,
 | 
						// update the connection properties, so shutdown can be used
 | 
				
			||||||
		remote: *addr,
 | 
						if err = windows.Setsockopt(
 | 
				
			||||||
 | 
							windows.Handle(sock.handle),
 | 
				
			||||||
 | 
							windows.SOL_SOCKET,
 | 
				
			||||||
 | 
							windows.SO_UPDATE_CONNECT_CONTEXT,
 | 
				
			||||||
 | 
							nil, // optvalue
 | 
				
			||||||
 | 
							0,   // optlen
 | 
				
			||||||
 | 
						); err != nil {
 | 
				
			||||||
 | 
							return nil, conn.opErr(op, os.NewSyscallError("setsockopt", err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// get the local name
 | 
				
			||||||
 | 
						var sal rawHvsockAddr
 | 
				
			||||||
 | 
						err = socket.GetSockName(windows.Handle(sock.handle), &sal)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, conn.opErr(op, os.NewSyscallError("getsockname", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn.local.fromRaw(&sal)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// one last check for timeout, since asyncIO doesn't check the context
 | 
				
			||||||
 | 
						if err = ctx.Err(); err != nil {
 | 
				
			||||||
 | 
							return nil, conn.opErr(op, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						conn.sock = sock
 | 
				
			||||||
	sock = nil
 | 
						sock = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return conn, nil
 | 
						return conn, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					
 | 
				
			||||||
 | 
					// redialWait waits before attempting to redial, resetting the timer as appropriate.
 | 
				
			||||||
 | 
					func (d *HvsockDialer) redialWait(ctx context.Context) (err error) {
 | 
				
			||||||
 | 
						if d.RetryWait == 0 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if d.rt == nil {
 | 
				
			||||||
 | 
							d.rt = time.NewTimer(d.RetryWait)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// should already be stopped and drained
 | 
				
			||||||
 | 
							d.rt.Reset(d.RetryWait)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						select {
 | 
				
			||||||
 | 
						case <-ctx.Done():
 | 
				
			||||||
 | 
						case <-d.rt.C:
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// stop and drain the timer
 | 
				
			||||||
 | 
						if !d.rt.Stop() {
 | 
				
			||||||
 | 
							<-d.rt.C
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ctx.Err()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// assumes error is a plain, unwrapped syscall.Errno provided by direct syscall.
 | 
				
			||||||
 | 
					func canRedial(err error) bool {
 | 
				
			||||||
 | 
						//nolint:errorlint // guaranteed to be an Errno
 | 
				
			||||||
 | 
						switch err {
 | 
				
			||||||
 | 
						case windows.WSAECONNREFUSED, windows.WSAENETUNREACH, windows.WSAETIMEDOUT,
 | 
				
			||||||
 | 
							windows.ERROR_CONNECTION_REFUSED, windows.ERROR_CONNECTION_UNAVAIL:
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (conn *HvsockConn) opErr(op string, err error) error {
 | 
					func (conn *HvsockConn) opErr(op string, err error) error {
 | 
				
			||||||
 | 
						// translate from "file closed" to "socket closed"
 | 
				
			||||||
 | 
						if errors.Is(err, ErrFileClosed) {
 | 
				
			||||||
 | 
							err = socket.ErrSocketClosed
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
 | 
						return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (conn *HvsockConn) Read(b []byte) (int, error) {
 | 
					func (conn *HvsockConn) Read(b []byte) (int, error) {
 | 
				
			||||||
	c, err := conn.sock.prepareIo()
 | 
						c, err := conn.sock.prepareIO()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, conn.opErr("read", err)
 | 
							return 0, conn.opErr("read", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -203,10 +450,11 @@ func (conn *HvsockConn) Read(b []byte) (int, error) {
 | 
				
			|||||||
	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
 | 
						buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
 | 
				
			||||||
	var flags, bytes uint32
 | 
						var flags, bytes uint32
 | 
				
			||||||
	err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
 | 
						err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
 | 
				
			||||||
	n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err)
 | 
						n, err := conn.sock.asyncIO(c, &conn.sock.readDeadline, bytes, err)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if _, ok := err.(syscall.Errno); ok {
 | 
							var eno windows.Errno
 | 
				
			||||||
			err = os.NewSyscallError("wsarecv", err)
 | 
							if errors.As(err, &eno) {
 | 
				
			||||||
 | 
								err = os.NewSyscallError("wsarecv", eno)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return 0, conn.opErr("read", err)
 | 
							return 0, conn.opErr("read", err)
 | 
				
			||||||
	} else if n == 0 {
 | 
						} else if n == 0 {
 | 
				
			||||||
@@ -229,7 +477,7 @@ func (conn *HvsockConn) Write(b []byte) (int, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (conn *HvsockConn) write(b []byte) (int, error) {
 | 
					func (conn *HvsockConn) write(b []byte) (int, error) {
 | 
				
			||||||
	c, err := conn.sock.prepareIo()
 | 
						c, err := conn.sock.prepareIO()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, conn.opErr("write", err)
 | 
							return 0, conn.opErr("write", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -237,10 +485,11 @@ func (conn *HvsockConn) write(b []byte) (int, error) {
 | 
				
			|||||||
	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
 | 
						buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
 | 
				
			||||||
	var bytes uint32
 | 
						var bytes uint32
 | 
				
			||||||
	err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
 | 
						err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
 | 
				
			||||||
	n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err)
 | 
						n, err := conn.sock.asyncIO(c, &conn.sock.writeDeadline, bytes, err)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if _, ok := err.(syscall.Errno); ok {
 | 
							var eno windows.Errno
 | 
				
			||||||
			err = os.NewSyscallError("wsasend", err)
 | 
							if errors.As(err, &eno) {
 | 
				
			||||||
 | 
								err = os.NewSyscallError("wsasend", eno)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return 0, conn.opErr("write", err)
 | 
							return 0, conn.opErr("write", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -252,29 +501,43 @@ func (conn *HvsockConn) Close() error {
 | 
				
			|||||||
	return conn.sock.Close()
 | 
						return conn.sock.Close()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (conn *HvsockConn) IsClosed() bool {
 | 
				
			||||||
 | 
						return conn.sock.IsClosed()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// shutdown disables sending or receiving on a socket.
 | 
				
			||||||
func (conn *HvsockConn) shutdown(how int) error {
 | 
					func (conn *HvsockConn) shutdown(how int) error {
 | 
				
			||||||
	err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD)
 | 
						if conn.IsClosed() {
 | 
				
			||||||
 | 
							return socket.ErrSocketClosed
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := syscall.Shutdown(conn.sock.handle, how)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							// If the connection was closed, shutdowns fail with "not connected"
 | 
				
			||||||
 | 
							if errors.Is(err, windows.WSAENOTCONN) ||
 | 
				
			||||||
 | 
								errors.Is(err, windows.WSAESHUTDOWN) {
 | 
				
			||||||
 | 
								err = socket.ErrSocketClosed
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return os.NewSyscallError("shutdown", err)
 | 
							return os.NewSyscallError("shutdown", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CloseRead shuts down the read end of the socket.
 | 
					// CloseRead shuts down the read end of the socket, preventing future read operations.
 | 
				
			||||||
func (conn *HvsockConn) CloseRead() error {
 | 
					func (conn *HvsockConn) CloseRead() error {
 | 
				
			||||||
	err := conn.shutdown(syscall.SHUT_RD)
 | 
						err := conn.shutdown(syscall.SHUT_RD)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return conn.opErr("close", err)
 | 
							return conn.opErr("closeread", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CloseWrite shuts down the write end of the socket, notifying the other endpoint that
 | 
					// CloseWrite shuts down the write end of the socket, preventing future write operations and
 | 
				
			||||||
// no more data will be written.
 | 
					// notifying the other endpoint that no more data will be written.
 | 
				
			||||||
func (conn *HvsockConn) CloseWrite() error {
 | 
					func (conn *HvsockConn) CloseWrite() error {
 | 
				
			||||||
	err := conn.shutdown(syscall.SHUT_WR)
 | 
						err := conn.shutdown(syscall.SHUT_WR)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return conn.opErr("close", err)
 | 
							return conn.opErr("closewrite", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -291,8 +554,13 @@ func (conn *HvsockConn) RemoteAddr() net.Addr {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// SetDeadline implements the net.Conn SetDeadline method.
 | 
					// SetDeadline implements the net.Conn SetDeadline method.
 | 
				
			||||||
func (conn *HvsockConn) SetDeadline(t time.Time) error {
 | 
					func (conn *HvsockConn) SetDeadline(t time.Time) error {
 | 
				
			||||||
	conn.SetReadDeadline(t)
 | 
						// todo: implement `SetDeadline` for `win32File`
 | 
				
			||||||
	conn.SetWriteDeadline(t)
 | 
						if err := conn.SetReadDeadline(t); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("set read deadline: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := conn.SetWriteDeadline(t); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("set write deadline: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RawSockaddr allows structs to be used with [Bind] and [ConnectEx]. The
 | 
				
			||||||
 | 
					// struct must meet the Win32 sockaddr requirements specified here:
 | 
				
			||||||
 | 
					// https://docs.microsoft.com/en-us/windows/win32/winsock/sockaddr-2
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Specifically, the struct size must be least larger than an int16 (unsigned short)
 | 
				
			||||||
 | 
					// for the address family.
 | 
				
			||||||
 | 
					type RawSockaddr interface {
 | 
				
			||||||
 | 
						// Sockaddr returns a pointer to the RawSockaddr and its struct size, allowing
 | 
				
			||||||
 | 
						// for the RawSockaddr's data to be overwritten by syscalls (if necessary).
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// It is the callers responsibility to validate that the values are valid; invalid
 | 
				
			||||||
 | 
						// pointers or size can cause a panic.
 | 
				
			||||||
 | 
						Sockaddr() (unsafe.Pointer, int32, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										179
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/Microsoft/go-winio/pkg/guid"
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go socket.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//sys getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getsockname
 | 
				
			||||||
 | 
					//sys getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getpeername
 | 
				
			||||||
 | 
					//sys bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const socketError = uintptr(^uint32(0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// todo(helsaawy): create custom error types to store the desired vs actual size and addr family?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ErrBufferSize     = errors.New("buffer size")
 | 
				
			||||||
 | 
						ErrAddrFamily     = errors.New("address family")
 | 
				
			||||||
 | 
						ErrInvalidPointer = errors.New("invalid pointer")
 | 
				
			||||||
 | 
						ErrSocketClosed   = fmt.Errorf("socket closed: %w", net.ErrClosed)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// todo(helsaawy): replace these with generics, ie: GetSockName[S RawSockaddr](s windows.Handle) (S, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetSockName writes the local address of socket s to the [RawSockaddr] rsa.
 | 
				
			||||||
 | 
					// If rsa is not large enough, the [windows.WSAEFAULT] is returned.
 | 
				
			||||||
 | 
					func GetSockName(s windows.Handle, rsa RawSockaddr) error {
 | 
				
			||||||
 | 
						ptr, l, err := rsa.Sockaddr()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// although getsockname returns WSAEFAULT if the buffer is too small, it does not set
 | 
				
			||||||
 | 
						// &l to the correct size, so--apart from doubling the buffer repeatedly--there is no remedy
 | 
				
			||||||
 | 
						return getsockname(s, ptr, &l)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetPeerName returns the remote address the socket is connected to.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See [GetSockName] for more information.
 | 
				
			||||||
 | 
					func GetPeerName(s windows.Handle, rsa RawSockaddr) error {
 | 
				
			||||||
 | 
						ptr, l, err := rsa.Sockaddr()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return getpeername(s, ptr, &l)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Bind(s windows.Handle, rsa RawSockaddr) (err error) {
 | 
				
			||||||
 | 
						ptr, l, err := rsa.Sockaddr()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return bind(s, ptr, l)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// "golang.org/x/sys/windows".ConnectEx and .Bind only accept internal implementations of the
 | 
				
			||||||
 | 
					// their sockaddr interface, so they cannot be used with HvsockAddr
 | 
				
			||||||
 | 
					// Replicate functionality here from
 | 
				
			||||||
 | 
					// https://cs.opensource.google/go/x/sys/+/master:windows/syscall_windows.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The function pointers to `AcceptEx`, `ConnectEx` and `GetAcceptExSockaddrs` must be loaded at
 | 
				
			||||||
 | 
					// runtime via a WSAIoctl call:
 | 
				
			||||||
 | 
					// https://docs.microsoft.com/en-us/windows/win32/api/Mswsock/nc-mswsock-lpfn_connectex#remarks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type runtimeFunc struct {
 | 
				
			||||||
 | 
						id   guid.GUID
 | 
				
			||||||
 | 
						once sync.Once
 | 
				
			||||||
 | 
						addr uintptr
 | 
				
			||||||
 | 
						err  error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *runtimeFunc) Load() error {
 | 
				
			||||||
 | 
						f.once.Do(func() {
 | 
				
			||||||
 | 
							var s windows.Handle
 | 
				
			||||||
 | 
							s, f.err = windows.Socket(windows.AF_INET, windows.SOCK_STREAM, windows.IPPROTO_TCP)
 | 
				
			||||||
 | 
							if f.err != nil {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer windows.CloseHandle(s) //nolint:errcheck
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var n uint32
 | 
				
			||||||
 | 
							f.err = windows.WSAIoctl(s,
 | 
				
			||||||
 | 
								windows.SIO_GET_EXTENSION_FUNCTION_POINTER,
 | 
				
			||||||
 | 
								(*byte)(unsafe.Pointer(&f.id)),
 | 
				
			||||||
 | 
								uint32(unsafe.Sizeof(f.id)),
 | 
				
			||||||
 | 
								(*byte)(unsafe.Pointer(&f.addr)),
 | 
				
			||||||
 | 
								uint32(unsafe.Sizeof(f.addr)),
 | 
				
			||||||
 | 
								&n,
 | 
				
			||||||
 | 
								nil, //overlapped
 | 
				
			||||||
 | 
								0,   //completionRoutine
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return f.err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// todo: add `AcceptEx` and `GetAcceptExSockaddrs`
 | 
				
			||||||
 | 
						WSAID_CONNECTEX = guid.GUID{ //revive:disable-line:var-naming ALL_CAPS
 | 
				
			||||||
 | 
							Data1: 0x25a207b9,
 | 
				
			||||||
 | 
							Data2: 0xddf3,
 | 
				
			||||||
 | 
							Data3: 0x4660,
 | 
				
			||||||
 | 
							Data4: [8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						connectExFunc = runtimeFunc{id: WSAID_CONNECTEX}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ConnectEx(
 | 
				
			||||||
 | 
						fd windows.Handle,
 | 
				
			||||||
 | 
						rsa RawSockaddr,
 | 
				
			||||||
 | 
						sendBuf *byte,
 | 
				
			||||||
 | 
						sendDataLen uint32,
 | 
				
			||||||
 | 
						bytesSent *uint32,
 | 
				
			||||||
 | 
						overlapped *windows.Overlapped,
 | 
				
			||||||
 | 
					) error {
 | 
				
			||||||
 | 
						if err := connectExFunc.Load(); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to load ConnectEx function pointer: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ptr, n, err := rsa.Sockaddr()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BOOL LpfnConnectex(
 | 
				
			||||||
 | 
					//   [in]           SOCKET s,
 | 
				
			||||||
 | 
					//   [in]           const sockaddr *name,
 | 
				
			||||||
 | 
					//   [in]           int namelen,
 | 
				
			||||||
 | 
					//   [in, optional] PVOID lpSendBuffer,
 | 
				
			||||||
 | 
					//   [in]           DWORD dwSendDataLength,
 | 
				
			||||||
 | 
					//   [out]          LPDWORD lpdwBytesSent,
 | 
				
			||||||
 | 
					//   [in]           LPOVERLAPPED lpOverlapped
 | 
				
			||||||
 | 
					// )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func connectEx(
 | 
				
			||||||
 | 
						s windows.Handle,
 | 
				
			||||||
 | 
						name unsafe.Pointer,
 | 
				
			||||||
 | 
						namelen int32,
 | 
				
			||||||
 | 
						sendBuf *byte,
 | 
				
			||||||
 | 
						sendDataLen uint32,
 | 
				
			||||||
 | 
						bytesSent *uint32,
 | 
				
			||||||
 | 
						overlapped *windows.Overlapped,
 | 
				
			||||||
 | 
					) (err error) {
 | 
				
			||||||
 | 
						// todo: after upgrading to 1.18, switch from syscall.Syscall9 to syscall.SyscallN
 | 
				
			||||||
 | 
						r1, _, e1 := syscall.Syscall9(connectExFunc.addr,
 | 
				
			||||||
 | 
							7,
 | 
				
			||||||
 | 
							uintptr(s),
 | 
				
			||||||
 | 
							uintptr(name),
 | 
				
			||||||
 | 
							uintptr(namelen),
 | 
				
			||||||
 | 
							uintptr(unsafe.Pointer(sendBuf)),
 | 
				
			||||||
 | 
							uintptr(sendDataLen),
 | 
				
			||||||
 | 
							uintptr(unsafe.Pointer(bytesSent)),
 | 
				
			||||||
 | 
							uintptr(unsafe.Pointer(overlapped)),
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
							0)
 | 
				
			||||||
 | 
						if r1 == 0 {
 | 
				
			||||||
 | 
							if e1 != 0 {
 | 
				
			||||||
 | 
								err = error(e1)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err = syscall.EINVAL
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										72
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ unsafe.Pointer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Do the interface allocations only once for common
 | 
				
			||||||
 | 
					// Errno values.
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						errnoERROR_IO_PENDING = 997
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
 | 
				
			||||||
 | 
						errERROR_EINVAL     error = syscall.EINVAL
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// errnoErr returns common boxed Errno values, to prevent
 | 
				
			||||||
 | 
					// allocations at runtime.
 | 
				
			||||||
 | 
					func errnoErr(e syscall.Errno) error {
 | 
				
			||||||
 | 
						switch e {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							return errERROR_EINVAL
 | 
				
			||||||
 | 
						case errnoERROR_IO_PENDING:
 | 
				
			||||||
 | 
							return errERROR_IO_PENDING
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// TODO: add more here, after collecting data on the common
 | 
				
			||||||
 | 
						// error values see on Windows. (perhaps when running
 | 
				
			||||||
 | 
						// all.bat?)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						procbind        = modws2_32.NewProc("bind")
 | 
				
			||||||
 | 
						procgetpeername = modws2_32.NewProc("getpeername")
 | 
				
			||||||
 | 
						procgetsockname = modws2_32.NewProc("getsockname")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) {
 | 
				
			||||||
 | 
						r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
 | 
				
			||||||
 | 
						if r1 == socketError {
 | 
				
			||||||
 | 
							err = errnoErr(e1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
 | 
				
			||||||
 | 
						r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
 | 
				
			||||||
 | 
						if r1 == socketError {
 | 
				
			||||||
 | 
							err = errnoErr(e1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
 | 
				
			||||||
 | 
						r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
 | 
				
			||||||
 | 
						if r1 == socketError {
 | 
				
			||||||
 | 
							err = errnoErr(e1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										124
									
								
								vendor/github.com/Microsoft/go-winio/pipe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										124
									
								
								vendor/github.com/Microsoft/go-winio/pipe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
@@ -13,6 +14,8 @@ import (
 | 
				
			|||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
	"unsafe"
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
 | 
					//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
 | 
				
			||||||
@@ -21,10 +24,10 @@ import (
 | 
				
			|||||||
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
 | 
					//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
 | 
				
			||||||
//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
 | 
					//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
 | 
				
			||||||
//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
 | 
					//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
 | 
				
			||||||
//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile
 | 
					//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile
 | 
				
			||||||
//sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
 | 
					//sys rtlNtStatusToDosError(status ntStatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
 | 
				
			||||||
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U
 | 
					//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) = ntdll.RtlDosPathNameToNtPathName_U
 | 
				
			||||||
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl
 | 
					//sys rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) = ntdll.RtlDefaultNpAcl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ioStatusBlock struct {
 | 
					type ioStatusBlock struct {
 | 
				
			||||||
	Status, Information uintptr
 | 
						Status, Information uintptr
 | 
				
			||||||
@@ -51,45 +54,22 @@ type securityDescriptor struct {
 | 
				
			|||||||
	Control  uint16
 | 
						Control  uint16
 | 
				
			||||||
	Owner    uintptr
 | 
						Owner    uintptr
 | 
				
			||||||
	Group    uintptr
 | 
						Group    uintptr
 | 
				
			||||||
	Sacl     uintptr
 | 
						Sacl     uintptr //revive:disable-line:var-naming SACL, not Sacl
 | 
				
			||||||
	Dacl     uintptr
 | 
						Dacl     uintptr //revive:disable-line:var-naming DACL, not Dacl
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ntstatus int32
 | 
					type ntStatus int32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (status ntstatus) Err() error {
 | 
					func (status ntStatus) Err() error {
 | 
				
			||||||
	if status >= 0 {
 | 
						if status >= 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return rtlNtStatusToDosError(status)
 | 
						return rtlNtStatusToDosError(status)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	cERROR_PIPE_BUSY      = syscall.Errno(231)
 | 
					 | 
				
			||||||
	cERROR_NO_DATA        = syscall.Errno(232)
 | 
					 | 
				
			||||||
	cERROR_PIPE_CONNECTED = syscall.Errno(535)
 | 
					 | 
				
			||||||
	cERROR_SEM_TIMEOUT    = syscall.Errno(121)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cSECURITY_SQOS_PRESENT = 0x100000
 | 
					 | 
				
			||||||
	cSECURITY_ANONYMOUS    = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cPIPE_TYPE_MESSAGE = 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cPIPE_READMODE_MESSAGE = 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cFILE_OPEN   = 1
 | 
					 | 
				
			||||||
	cFILE_CREATE = 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cFILE_PIPE_MESSAGE_TYPE          = 1
 | 
					 | 
				
			||||||
	cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cSE_DACL_PRESENT = 4
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
 | 
						// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
 | 
				
			||||||
	// This error should match net.errClosing since docker takes a dependency on its text.
 | 
						ErrPipeListenerClosed = net.ErrClosed
 | 
				
			||||||
	ErrPipeListenerClosed = errors.New("use of closed network connection")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	errPipeWriteClosed = errors.New("pipe has been closed for write")
 | 
						errPipeWriteClosed = errors.New("pipe has been closed for write")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -116,9 +96,10 @@ func (f *win32Pipe) RemoteAddr() net.Addr {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *win32Pipe) SetDeadline(t time.Time) error {
 | 
					func (f *win32Pipe) SetDeadline(t time.Time) error {
 | 
				
			||||||
	f.SetReadDeadline(t)
 | 
						if err := f.SetReadDeadline(t); err != nil {
 | 
				
			||||||
	f.SetWriteDeadline(t)
 | 
							return err
 | 
				
			||||||
	return nil
 | 
						}
 | 
				
			||||||
 | 
						return f.SetWriteDeadline(t)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CloseWrite closes the write side of a message pipe in byte mode.
 | 
					// CloseWrite closes the write side of a message pipe in byte mode.
 | 
				
			||||||
@@ -157,14 +138,14 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
 | 
				
			|||||||
		return 0, io.EOF
 | 
							return 0, io.EOF
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	n, err := f.win32File.Read(b)
 | 
						n, err := f.win32File.Read(b)
 | 
				
			||||||
	if err == io.EOF {
 | 
						if err == io.EOF { //nolint:errorlint
 | 
				
			||||||
		// If this was the result of a zero-byte read, then
 | 
							// If this was the result of a zero-byte read, then
 | 
				
			||||||
		// it is possible that the read was due to a zero-size
 | 
							// it is possible that the read was due to a zero-size
 | 
				
			||||||
		// message. Since we are simulating CloseWrite with a
 | 
							// message. Since we are simulating CloseWrite with a
 | 
				
			||||||
		// zero-byte message, ensure that all future Read() calls
 | 
							// zero-byte message, ensure that all future Read() calls
 | 
				
			||||||
		// also return EOF.
 | 
							// also return EOF.
 | 
				
			||||||
		f.readEOF = true
 | 
							f.readEOF = true
 | 
				
			||||||
	} else if err == syscall.ERROR_MORE_DATA {
 | 
						} else if err == syscall.ERROR_MORE_DATA { //nolint:errorlint // err is Errno
 | 
				
			||||||
		// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
 | 
							// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
 | 
				
			||||||
		// and the message still has more bytes. Treat this as a success, since
 | 
							// and the message still has more bytes. Treat this as a success, since
 | 
				
			||||||
		// this package presents all named pipes as byte streams.
 | 
							// this package presents all named pipes as byte streams.
 | 
				
			||||||
@@ -173,7 +154,7 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
 | 
				
			|||||||
	return n, err
 | 
						return n, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s pipeAddress) Network() string {
 | 
					func (pipeAddress) Network() string {
 | 
				
			||||||
	return "pipe"
 | 
						return "pipe"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -184,16 +165,21 @@ func (s pipeAddress) String() string {
 | 
				
			|||||||
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
 | 
					// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
 | 
				
			||||||
func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) {
 | 
					func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) {
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
 | 
					 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case <-ctx.Done():
 | 
							case <-ctx.Done():
 | 
				
			||||||
			return syscall.Handle(0), ctx.Err()
 | 
								return syscall.Handle(0), ctx.Err()
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
 | 
								h, err := createFile(*path,
 | 
				
			||||||
 | 
									access,
 | 
				
			||||||
 | 
									0,
 | 
				
			||||||
 | 
									nil,
 | 
				
			||||||
 | 
									syscall.OPEN_EXISTING,
 | 
				
			||||||
 | 
									windows.FILE_FLAG_OVERLAPPED|windows.SECURITY_SQOS_PRESENT|windows.SECURITY_ANONYMOUS,
 | 
				
			||||||
 | 
									0)
 | 
				
			||||||
			if err == nil {
 | 
								if err == nil {
 | 
				
			||||||
				return h, nil
 | 
									return h, nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if err != cERROR_PIPE_BUSY {
 | 
								if err != windows.ERROR_PIPE_BUSY { //nolint:errorlint // err is Errno
 | 
				
			||||||
				return h, &os.PathError{Err: err, Op: "open", Path: *path}
 | 
									return h, &os.PathError{Err: err, Op: "open", Path: *path}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// Wait 10 msec and try again. This is a rather simplistic
 | 
								// Wait 10 msec and try again. This is a rather simplistic
 | 
				
			||||||
@@ -213,9 +199,10 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		absTimeout = time.Now().Add(2 * time.Second)
 | 
							absTimeout = time.Now().Add(2 * time.Second)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx, _ := context.WithDeadline(context.Background(), absTimeout)
 | 
						ctx, cancel := context.WithDeadline(context.Background(), absTimeout)
 | 
				
			||||||
 | 
						defer cancel()
 | 
				
			||||||
	conn, err := DialPipeContext(ctx, path)
 | 
						conn, err := DialPipeContext(ctx, path)
 | 
				
			||||||
	if err == context.DeadlineExceeded {
 | 
						if errors.Is(err, context.DeadlineExceeded) {
 | 
				
			||||||
		return nil, ErrTimeout
 | 
							return nil, ErrTimeout
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return conn, err
 | 
						return conn, err
 | 
				
			||||||
@@ -251,7 +238,7 @@ func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// If the pipe is in message mode, return a message byte pipe, which
 | 
						// If the pipe is in message mode, return a message byte pipe, which
 | 
				
			||||||
	// supports CloseWrite().
 | 
						// supports CloseWrite().
 | 
				
			||||||
	if flags&cPIPE_TYPE_MESSAGE != 0 {
 | 
						if flags&windows.PIPE_TYPE_MESSAGE != 0 {
 | 
				
			||||||
		return &win32MessageBytePipe{
 | 
							return &win32MessageBytePipe{
 | 
				
			||||||
			win32Pipe: win32Pipe{win32File: f, path: path},
 | 
								win32Pipe: win32Pipe{win32File: f, path: path},
 | 
				
			||||||
		}, nil
 | 
							}, nil
 | 
				
			||||||
@@ -283,7 +270,11 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
 | 
				
			|||||||
	oa.Length = unsafe.Sizeof(oa)
 | 
						oa.Length = unsafe.Sizeof(oa)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var ntPath unicodeString
 | 
						var ntPath unicodeString
 | 
				
			||||||
	if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil {
 | 
						if err := rtlDosPathNameToNtPathName(&path16[0],
 | 
				
			||||||
 | 
							&ntPath,
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
						).Err(); err != nil {
 | 
				
			||||||
		return 0, &os.PathError{Op: "open", Path: path, Err: err}
 | 
							return 0, &os.PathError{Op: "open", Path: path, Err: err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer localFree(ntPath.Buffer)
 | 
						defer localFree(ntPath.Buffer)
 | 
				
			||||||
@@ -292,8 +283,8 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
 | 
				
			|||||||
	// The security descriptor is only needed for the first pipe.
 | 
						// The security descriptor is only needed for the first pipe.
 | 
				
			||||||
	if first {
 | 
						if first {
 | 
				
			||||||
		if sd != nil {
 | 
							if sd != nil {
 | 
				
			||||||
			len := uint32(len(sd))
 | 
								l := uint32(len(sd))
 | 
				
			||||||
			sdb := localAlloc(0, len)
 | 
								sdb := localAlloc(0, l)
 | 
				
			||||||
			defer localFree(sdb)
 | 
								defer localFree(sdb)
 | 
				
			||||||
			copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
 | 
								copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
 | 
				
			||||||
			oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
 | 
								oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
 | 
				
			||||||
@@ -301,28 +292,28 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
 | 
				
			|||||||
			// Construct the default named pipe security descriptor.
 | 
								// Construct the default named pipe security descriptor.
 | 
				
			||||||
			var dacl uintptr
 | 
								var dacl uintptr
 | 
				
			||||||
			if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
 | 
								if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
 | 
				
			||||||
				return 0, fmt.Errorf("getting default named pipe ACL: %s", err)
 | 
									return 0, fmt.Errorf("getting default named pipe ACL: %w", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			defer localFree(dacl)
 | 
								defer localFree(dacl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sdb := &securityDescriptor{
 | 
								sdb := &securityDescriptor{
 | 
				
			||||||
				Revision: 1,
 | 
									Revision: 1,
 | 
				
			||||||
				Control:  cSE_DACL_PRESENT,
 | 
									Control:  windows.SE_DACL_PRESENT,
 | 
				
			||||||
				Dacl:     dacl,
 | 
									Dacl:     dacl,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			oa.SecurityDescriptor = sdb
 | 
								oa.SecurityDescriptor = sdb
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS)
 | 
						typ := uint32(windows.FILE_PIPE_REJECT_REMOTE_CLIENTS)
 | 
				
			||||||
	if c.MessageMode {
 | 
						if c.MessageMode {
 | 
				
			||||||
		typ |= cFILE_PIPE_MESSAGE_TYPE
 | 
							typ |= windows.FILE_PIPE_MESSAGE_TYPE
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	disposition := uint32(cFILE_OPEN)
 | 
						disposition := uint32(windows.FILE_OPEN)
 | 
				
			||||||
	access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
 | 
						access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
 | 
				
			||||||
	if first {
 | 
						if first {
 | 
				
			||||||
		disposition = cFILE_CREATE
 | 
							disposition = windows.FILE_CREATE
 | 
				
			||||||
		// By not asking for read or write access, the named pipe file system
 | 
							// By not asking for read or write access, the named pipe file system
 | 
				
			||||||
		// will put this pipe into an initially disconnected state, blocking
 | 
							// will put this pipe into an initially disconnected state, blocking
 | 
				
			||||||
		// client connections until the next call with first == false.
 | 
							// client connections until the next call with first == false.
 | 
				
			||||||
@@ -335,7 +326,20 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
 | 
				
			|||||||
		h    syscall.Handle
 | 
							h    syscall.Handle
 | 
				
			||||||
		iosb ioStatusBlock
 | 
							iosb ioStatusBlock
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err()
 | 
						err = ntCreateNamedPipeFile(&h,
 | 
				
			||||||
 | 
							access,
 | 
				
			||||||
 | 
							&oa,
 | 
				
			||||||
 | 
							&iosb,
 | 
				
			||||||
 | 
							syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
 | 
				
			||||||
 | 
							disposition,
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
							typ,
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
							0xffffffff,
 | 
				
			||||||
 | 
							uint32(c.InputBufferSize),
 | 
				
			||||||
 | 
							uint32(c.OutputBufferSize),
 | 
				
			||||||
 | 
							&timeout).Err()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, &os.PathError{Op: "open", Path: path, Err: err}
 | 
							return 0, &os.PathError{Op: "open", Path: path, Err: err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -380,7 +384,7 @@ func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) {
 | 
				
			|||||||
		p.Close()
 | 
							p.Close()
 | 
				
			||||||
		p = nil
 | 
							p = nil
 | 
				
			||||||
		err = <-ch
 | 
							err = <-ch
 | 
				
			||||||
		if err == nil || err == ErrFileClosed {
 | 
							if err == nil || err == ErrFileClosed { //nolint:errorlint // err is Errno
 | 
				
			||||||
			err = ErrPipeListenerClosed
 | 
								err = ErrPipeListenerClosed
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -402,12 +406,12 @@ func (l *win32PipeListener) listenerRoutine() {
 | 
				
			|||||||
				p, err = l.makeConnectedServerPipe()
 | 
									p, err = l.makeConnectedServerPipe()
 | 
				
			||||||
				// If the connection was immediately closed by the client, try
 | 
									// If the connection was immediately closed by the client, try
 | 
				
			||||||
				// again.
 | 
									// again.
 | 
				
			||||||
				if err != cERROR_NO_DATA {
 | 
									if err != windows.ERROR_NO_DATA { //nolint:errorlint // err is Errno
 | 
				
			||||||
					break
 | 
										break
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			responseCh <- acceptResponse{p, err}
 | 
								responseCh <- acceptResponse{p, err}
 | 
				
			||||||
			closed = err == ErrPipeListenerClosed
 | 
								closed = err == ErrPipeListenerClosed //nolint:errorlint // err is Errno
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	syscall.Close(l.firstHandle)
 | 
						syscall.Close(l.firstHandle)
 | 
				
			||||||
@@ -469,15 +473,15 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func connectPipe(p *win32File) error {
 | 
					func connectPipe(p *win32File) error {
 | 
				
			||||||
	c, err := p.prepareIo()
 | 
						c, err := p.prepareIO()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer p.wg.Done()
 | 
						defer p.wg.Done()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = connectNamedPipe(p.handle, &c.o)
 | 
						err = connectNamedPipe(p.handle, &c.o)
 | 
				
			||||||
	_, err = p.asyncIo(c, nil, 0, err)
 | 
						_, err = p.asyncIO(c, nil, 0, err)
 | 
				
			||||||
	if err != nil && err != cERROR_PIPE_CONNECTED {
 | 
						if err != nil && err != windows.ERROR_PIPE_CONNECTED { //nolint:errorlint // err is Errno
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,5 +1,3 @@
 | 
				
			|||||||
// +build windows
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Package guid provides a GUID type. The backing structure for a GUID is
 | 
					// Package guid provides a GUID type. The backing structure for a GUID is
 | 
				
			||||||
// identical to that used by the golang.org/x/sys/windows GUID type.
 | 
					// identical to that used by the golang.org/x/sys/windows GUID type.
 | 
				
			||||||
// There are two main binary encodings used for a GUID, the big-endian encoding,
 | 
					// There are two main binary encodings used for a GUID, the big-endian encoding,
 | 
				
			||||||
@@ -9,26 +7,26 @@ package guid
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto/rand"
 | 
						"crypto/rand"
 | 
				
			||||||
	"crypto/sha1"
 | 
						"crypto/sha1" //nolint:gosec // not used for secure application
 | 
				
			||||||
	"encoding"
 | 
						"encoding"
 | 
				
			||||||
	"encoding/binary"
 | 
						"encoding/binary"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"golang.org/x/sys/windows"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:generate go run golang.org/x/tools/cmd/stringer -type=Variant -trimprefix=Variant -linecomment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Variant specifies which GUID variant (or "type") of the GUID. It determines
 | 
					// Variant specifies which GUID variant (or "type") of the GUID. It determines
 | 
				
			||||||
// how the entirety of the rest of the GUID is interpreted.
 | 
					// how the entirety of the rest of the GUID is interpreted.
 | 
				
			||||||
type Variant uint8
 | 
					type Variant uint8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The variants specified by RFC 4122.
 | 
					// The variants specified by RFC 4122 section 4.1.1.
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	// VariantUnknown specifies a GUID variant which does not conform to one of
 | 
						// VariantUnknown specifies a GUID variant which does not conform to one of
 | 
				
			||||||
	// the variant encodings specified in RFC 4122.
 | 
						// the variant encodings specified in RFC 4122.
 | 
				
			||||||
	VariantUnknown Variant = iota
 | 
						VariantUnknown Variant = iota
 | 
				
			||||||
	VariantNCS
 | 
						VariantNCS
 | 
				
			||||||
	VariantRFC4122
 | 
						VariantRFC4122 // RFC 4122
 | 
				
			||||||
	VariantMicrosoft
 | 
						VariantMicrosoft
 | 
				
			||||||
	VariantFuture
 | 
						VariantFuture
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -38,16 +36,13 @@ const (
 | 
				
			|||||||
// hash of an input string.
 | 
					// hash of an input string.
 | 
				
			||||||
type Version uint8
 | 
					type Version uint8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (v Version) String() string {
 | 
				
			||||||
 | 
						return strconv.FormatUint(uint64(v), 10)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ = (encoding.TextMarshaler)(GUID{})
 | 
					var _ = (encoding.TextMarshaler)(GUID{})
 | 
				
			||||||
var _ = (encoding.TextUnmarshaler)(&GUID{})
 | 
					var _ = (encoding.TextUnmarshaler)(&GUID{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GUID represents a GUID/UUID. It has the same structure as
 | 
					 | 
				
			||||||
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
 | 
					 | 
				
			||||||
// that type. It is defined as its own type so that stringification and
 | 
					 | 
				
			||||||
// marshaling can be supported. The representation matches that used by native
 | 
					 | 
				
			||||||
// Windows code.
 | 
					 | 
				
			||||||
type GUID windows.GUID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
 | 
					// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
 | 
				
			||||||
func NewV4() (GUID, error) {
 | 
					func NewV4() (GUID, error) {
 | 
				
			||||||
	var b [16]byte
 | 
						var b [16]byte
 | 
				
			||||||
@@ -70,7 +65,7 @@ func NewV4() (GUID, error) {
 | 
				
			|||||||
// big-endian UTF16 stream of bytes. If that is desired, the string can be
 | 
					// big-endian UTF16 stream of bytes. If that is desired, the string can be
 | 
				
			||||||
// encoded as such before being passed to this function.
 | 
					// encoded as such before being passed to this function.
 | 
				
			||||||
func NewV5(namespace GUID, name []byte) (GUID, error) {
 | 
					func NewV5(namespace GUID, name []byte) (GUID, error) {
 | 
				
			||||||
	b := sha1.New()
 | 
						b := sha1.New() //nolint:gosec // not used for secure application
 | 
				
			||||||
	namespaceBytes := namespace.ToArray()
 | 
						namespaceBytes := namespace.ToArray()
 | 
				
			||||||
	b.Write(namespaceBytes[:])
 | 
						b.Write(namespaceBytes[:])
 | 
				
			||||||
	b.Write(name)
 | 
						b.Write(name)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					//go:build !windows
 | 
				
			||||||
 | 
					// +build !windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package guid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GUID represents a GUID/UUID. It has the same structure as
 | 
				
			||||||
 | 
					// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
 | 
				
			||||||
 | 
					// that type. It is defined as its own type as that is only available to builds
 | 
				
			||||||
 | 
					// targeted at `windows`. The representation matches that used by native Windows
 | 
				
			||||||
 | 
					// code.
 | 
				
			||||||
 | 
					type GUID struct {
 | 
				
			||||||
 | 
						Data1 uint32
 | 
				
			||||||
 | 
						Data2 uint16
 | 
				
			||||||
 | 
						Data3 uint16
 | 
				
			||||||
 | 
						Data4 [8]byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package guid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "golang.org/x/sys/windows"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GUID represents a GUID/UUID. It has the same structure as
 | 
				
			||||||
 | 
					// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
 | 
				
			||||||
 | 
					// that type. It is defined as its own type so that stringification and
 | 
				
			||||||
 | 
					// marshaling can be supported. The representation matches that used by native
 | 
				
			||||||
 | 
					// Windows code.
 | 
				
			||||||
 | 
					type GUID windows.GUID
 | 
				
			||||||
							
								
								
									
										27
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					// Code generated by "stringer -type=Variant -trimprefix=Variant -linecomment"; DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package guid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func _() {
 | 
				
			||||||
 | 
						// An "invalid array index" compiler error signifies that the constant values have changed.
 | 
				
			||||||
 | 
						// Re-run the stringer command to generate them again.
 | 
				
			||||||
 | 
						var x [1]struct{}
 | 
				
			||||||
 | 
						_ = x[VariantUnknown-0]
 | 
				
			||||||
 | 
						_ = x[VariantNCS-1]
 | 
				
			||||||
 | 
						_ = x[VariantRFC4122-2]
 | 
				
			||||||
 | 
						_ = x[VariantMicrosoft-3]
 | 
				
			||||||
 | 
						_ = x[VariantFuture-4]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const _Variant_name = "UnknownNCSRFC 4122MicrosoftFuture"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _Variant_index = [...]uint8{0, 7, 10, 18, 27, 33}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i Variant) String() string {
 | 
				
			||||||
 | 
						if i >= Variant(len(_Variant_index)-1) {
 | 
				
			||||||
 | 
							return "Variant(" + strconv.FormatInt(int64(i), 10) + ")"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return _Variant_name[_Variant_index[i]:_Variant_index[i+1]]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										44
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,13 +1,13 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package security
 | 
					package security
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"unsafe"
 | 
						"unsafe"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/pkg/errors"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type (
 | 
					type (
 | 
				
			||||||
@@ -21,6 +21,7 @@ type (
 | 
				
			|||||||
	trusteeForm         uint32
 | 
						trusteeForm         uint32
 | 
				
			||||||
	trusteeType         uint32
 | 
						trusteeType         uint32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//nolint:structcheck // structcheck thinks fields are unused, but the are used to pass data to OS
 | 
				
			||||||
	explicitAccess struct {
 | 
						explicitAccess struct {
 | 
				
			||||||
		accessPermissions accessMask
 | 
							accessPermissions accessMask
 | 
				
			||||||
		accessMode        accessMode
 | 
							accessMode        accessMode
 | 
				
			||||||
@@ -28,6 +29,7 @@ type (
 | 
				
			|||||||
		trustee           trustee
 | 
							trustee           trustee
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//nolint:structcheck,unused // structcheck thinks fields are unused, but the are used to pass data to OS
 | 
				
			||||||
	trustee struct {
 | 
						trustee struct {
 | 
				
			||||||
		multipleTrustee          *trustee
 | 
							multipleTrustee          *trustee
 | 
				
			||||||
		multipleTrusteeOperation int32
 | 
							multipleTrusteeOperation int32
 | 
				
			||||||
@@ -45,6 +47,7 @@ const (
 | 
				
			|||||||
	desiredAccessReadControl desiredAccess = 0x20000
 | 
						desiredAccessReadControl desiredAccess = 0x20000
 | 
				
			||||||
	desiredAccessWriteDac    desiredAccess = 0x40000
 | 
						desiredAccessWriteDac    desiredAccess = 0x40000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//cspell:disable-next-line
 | 
				
			||||||
	gvmga = "GrantVmGroupAccess:"
 | 
						gvmga = "GrantVmGroupAccess:"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inheritModeNoInheritance                  inheritMode = 0x0
 | 
						inheritModeNoInheritance                  inheritMode = 0x0
 | 
				
			||||||
@@ -57,9 +60,9 @@ const (
 | 
				
			|||||||
	shareModeRead  shareMode = 0x1
 | 
						shareModeRead  shareMode = 0x1
 | 
				
			||||||
	shareModeWrite shareMode = 0x2
 | 
						shareModeWrite shareMode = 0x2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sidVmGroup = "S-1-5-83-0"
 | 
						sidVMGroup = "S-1-5-83-0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trusteeFormIsSid trusteeForm = 0
 | 
						trusteeFormIsSID trusteeForm = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trusteeTypeWellKnownGroup trusteeType = 5
 | 
						trusteeTypeWellKnownGroup trusteeType = 5
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -68,11 +71,13 @@ const (
 | 
				
			|||||||
// include Grant ACE entries for the VM Group SID. This is a golang re-
 | 
					// include Grant ACE entries for the VM Group SID. This is a golang re-
 | 
				
			||||||
// implementation of the same function in vmcompute, just not exported in
 | 
					// implementation of the same function in vmcompute, just not exported in
 | 
				
			||||||
// RS5. Which kind of sucks. Sucks a lot :/
 | 
					// RS5. Which kind of sucks. Sucks a lot :/
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//revive:disable-next-line:var-naming VM, not Vm
 | 
				
			||||||
func GrantVmGroupAccess(name string) error {
 | 
					func GrantVmGroupAccess(name string) error {
 | 
				
			||||||
	// Stat (to determine if `name` is a directory).
 | 
						// Stat (to determine if `name` is a directory).
 | 
				
			||||||
	s, err := os.Stat(name)
 | 
						s, err := os.Stat(name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.Wrapf(err, "%s os.Stat %s", gvmga, name)
 | 
							return fmt.Errorf("%s os.Stat %s: %w", gvmga, name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get a handle to the file/directory. Must defer Close on success.
 | 
						// Get a handle to the file/directory. Must defer Close on success.
 | 
				
			||||||
@@ -80,7 +85,7 @@ func GrantVmGroupAccess(name string) error {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err // Already wrapped
 | 
							return err // Already wrapped
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer syscall.CloseHandle(fd)
 | 
						defer syscall.CloseHandle(fd) //nolint:errcheck
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get the current DACL and Security Descriptor. Must defer LocalFree on success.
 | 
						// Get the current DACL and Security Descriptor. Must defer LocalFree on success.
 | 
				
			||||||
	ot := objectTypeFileObject
 | 
						ot := objectTypeFileObject
 | 
				
			||||||
@@ -88,9 +93,9 @@ func GrantVmGroupAccess(name string) error {
 | 
				
			|||||||
	sd := uintptr(0)
 | 
						sd := uintptr(0)
 | 
				
			||||||
	origDACL := uintptr(0)
 | 
						origDACL := uintptr(0)
 | 
				
			||||||
	if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil {
 | 
						if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil {
 | 
				
			||||||
		return errors.Wrapf(err, "%s GetSecurityInfo %s", gvmga, name)
 | 
							return fmt.Errorf("%s GetSecurityInfo %s: %w", gvmga, name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd)))
 | 
						defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd))) //nolint:errcheck
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Generate a new DACL which is the current DACL with the required ACEs added.
 | 
						// Generate a new DACL which is the current DACL with the required ACEs added.
 | 
				
			||||||
	// Must defer LocalFree on success.
 | 
						// Must defer LocalFree on success.
 | 
				
			||||||
@@ -98,11 +103,11 @@ func GrantVmGroupAccess(name string) error {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err // Already wrapped
 | 
							return err // Already wrapped
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL)))
 | 
						defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL))) //nolint:errcheck
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// And finally use SetSecurityInfo to apply the updated DACL.
 | 
						// And finally use SetSecurityInfo to apply the updated DACL.
 | 
				
			||||||
	if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil {
 | 
						if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil {
 | 
				
			||||||
		return errors.Wrapf(err, "%s SetSecurityInfo %s", gvmga, name)
 | 
							return fmt.Errorf("%s SetSecurityInfo %s: %w", gvmga, name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -111,16 +116,19 @@ func GrantVmGroupAccess(name string) error {
 | 
				
			|||||||
// createFile is a helper function to call [Nt]CreateFile to get a handle to
 | 
					// createFile is a helper function to call [Nt]CreateFile to get a handle to
 | 
				
			||||||
// the file or directory.
 | 
					// the file or directory.
 | 
				
			||||||
func createFile(name string, isDir bool) (syscall.Handle, error) {
 | 
					func createFile(name string, isDir bool) (syscall.Handle, error) {
 | 
				
			||||||
	namep := syscall.StringToUTF16(name)
 | 
						namep, err := syscall.UTF16FromString(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return syscall.InvalidHandle, fmt.Errorf("could not convernt name to UTF-16: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	da := uint32(desiredAccessReadControl | desiredAccessWriteDac)
 | 
						da := uint32(desiredAccessReadControl | desiredAccessWriteDac)
 | 
				
			||||||
	sm := uint32(shareModeRead | shareModeWrite)
 | 
						sm := uint32(shareModeRead | shareModeWrite)
 | 
				
			||||||
	fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL)
 | 
						fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL)
 | 
				
			||||||
	if isDir {
 | 
						if isDir {
 | 
				
			||||||
		fa = uint32(fa | syscall.FILE_FLAG_BACKUP_SEMANTICS)
 | 
							fa |= syscall.FILE_FLAG_BACKUP_SEMANTICS
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0)
 | 
						fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, errors.Wrapf(err, "%s syscall.CreateFile %s", gvmga, name)
 | 
							return syscall.InvalidHandle, fmt.Errorf("%s syscall.CreateFile %s: %w", gvmga, name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return fd, nil
 | 
						return fd, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -129,9 +137,9 @@ func createFile(name string, isDir bool) (syscall.Handle, error) {
 | 
				
			|||||||
// The caller is responsible for LocalFree of the returned DACL on success.
 | 
					// The caller is responsible for LocalFree of the returned DACL on success.
 | 
				
			||||||
func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) {
 | 
					func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) {
 | 
				
			||||||
	// Generate pointers to the SIDs based on the string SIDs
 | 
						// Generate pointers to the SIDs based on the string SIDs
 | 
				
			||||||
	sid, err := syscall.StringToSid(sidVmGroup)
 | 
						sid, err := syscall.StringToSid(sidVMGroup)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, errors.Wrapf(err, "%s syscall.StringToSid %s %s", gvmga, name, sidVmGroup)
 | 
							return 0, fmt.Errorf("%s syscall.StringToSid %s %s: %w", gvmga, name, sidVMGroup, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inheritance := inheritModeNoInheritance
 | 
						inheritance := inheritModeNoInheritance
 | 
				
			||||||
@@ -140,12 +148,12 @@ func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintp
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eaArray := []explicitAccess{
 | 
						eaArray := []explicitAccess{
 | 
				
			||||||
		explicitAccess{
 | 
							{
 | 
				
			||||||
			accessPermissions: accessMaskDesiredPermission,
 | 
								accessPermissions: accessMaskDesiredPermission,
 | 
				
			||||||
			accessMode:        accessModeGrant,
 | 
								accessMode:        accessModeGrant,
 | 
				
			||||||
			inheritance:       inheritance,
 | 
								inheritance:       inheritance,
 | 
				
			||||||
			trustee: trustee{
 | 
								trustee: trustee{
 | 
				
			||||||
				trusteeForm: trusteeFormIsSid,
 | 
									trusteeForm: trusteeFormIsSID,
 | 
				
			||||||
				trusteeType: trusteeTypeWellKnownGroup,
 | 
									trusteeType: trusteeTypeWellKnownGroup,
 | 
				
			||||||
				name:        uintptr(unsafe.Pointer(sid)),
 | 
									name:        uintptr(unsafe.Pointer(sid)),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -154,7 +162,7 @@ func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintp
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	modifiedDACL := uintptr(0)
 | 
						modifiedDACL := uintptr(0)
 | 
				
			||||||
	if err := setEntriesInAcl(uintptr(uint32(1)), uintptr(unsafe.Pointer(&eaArray[0])), origDACL, &modifiedDACL); err != nil {
 | 
						if err := setEntriesInAcl(uintptr(uint32(1)), uintptr(unsafe.Pointer(&eaArray[0])), origDACL, &modifiedDACL); err != nil {
 | 
				
			||||||
		return 0, errors.Wrapf(err, "%s SetEntriesInAcl %s", gvmga, name)
 | 
							return 0, fmt.Errorf("%s SetEntriesInAcl %s: %w", gvmga, name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return modifiedDACL, nil
 | 
						return modifiedDACL, nil
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
package security
 | 
					package security
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:generate go run mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
 | 
					//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go syscall_windows.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo
 | 
					//sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (win32err error) = advapi32.GetSecurityInfo
 | 
				
			||||||
//sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) [failretval!=0] = advapi32.SetSecurityInfo
 | 
					//sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (win32err error) = advapi32.SetSecurityInfo
 | 
				
			||||||
//sys setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (err error) [failretval!=0] = advapi32.SetEntriesInAclW
 | 
					//sys setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (win32err error) = advapi32.SetEntriesInAclW
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,6 @@
 | 
				
			|||||||
// Code generated by 'go generate'; DO NOT EDIT.
 | 
					//go:build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package security
 | 
					package security
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -45,26 +47,26 @@ var (
 | 
				
			|||||||
	procSetSecurityInfo  = modadvapi32.NewProc("SetSecurityInfo")
 | 
						procSetSecurityInfo  = modadvapi32.NewProc("SetSecurityInfo")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) {
 | 
					func getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (win32err error) {
 | 
				
			||||||
	r1, _, e1 := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(ppsidOwner)), uintptr(unsafe.Pointer(ppsidGroup)), uintptr(unsafe.Pointer(ppDacl)), uintptr(unsafe.Pointer(ppSacl)), uintptr(unsafe.Pointer(ppSecurityDescriptor)), 0)
 | 
						r0, _, _ := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(ppsidOwner)), uintptr(unsafe.Pointer(ppsidGroup)), uintptr(unsafe.Pointer(ppDacl)), uintptr(unsafe.Pointer(ppSacl)), uintptr(unsafe.Pointer(ppSecurityDescriptor)), 0)
 | 
				
			||||||
	if r1 != 0 {
 | 
						if r0 != 0 {
 | 
				
			||||||
		err = errnoErr(e1)
 | 
							win32err = syscall.Errno(r0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (err error) {
 | 
					func setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (win32err error) {
 | 
				
			||||||
	r1, _, e1 := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(count), uintptr(pListOfEEs), uintptr(oldAcl), uintptr(unsafe.Pointer(newAcl)), 0, 0)
 | 
						r0, _, _ := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(count), uintptr(pListOfEEs), uintptr(oldAcl), uintptr(unsafe.Pointer(newAcl)), 0, 0)
 | 
				
			||||||
	if r1 != 0 {
 | 
						if r0 != 0 {
 | 
				
			||||||
		err = errnoErr(e1)
 | 
							win32err = syscall.Errno(r0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) {
 | 
					func setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (win32err error) {
 | 
				
			||||||
	r1, _, e1 := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(psidOwner), uintptr(psidGroup), uintptr(pDacl), uintptr(pSacl), 0, 0)
 | 
						r0, _, _ := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(psidOwner), uintptr(psidGroup), uintptr(pDacl), uintptr(pSacl), 0, 0)
 | 
				
			||||||
	if r1 != 0 {
 | 
						if r0 != 0 {
 | 
				
			||||||
		err = errnoErr(e1)
 | 
							win32err = syscall.Errno(r0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								vendor/github.com/Microsoft/go-winio/privilege.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/Microsoft/go-winio/privilege.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
@@ -24,19 +25,15 @@ import (
 | 
				
			|||||||
//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
 | 
					//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	SE_PRIVILEGE_ENABLED = 2
 | 
						//revive:disable-next-line:var-naming ALL_CAPS
 | 
				
			||||||
 | 
						SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
 | 
						//revive:disable-next-line:var-naming ALL_CAPS
 | 
				
			||||||
 | 
						ERROR_NOT_ALL_ASSIGNED syscall.Errno = windows.ERROR_NOT_ALL_ASSIGNED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SeBackupPrivilege  = "SeBackupPrivilege"
 | 
						SeBackupPrivilege   = "SeBackupPrivilege"
 | 
				
			||||||
	SeRestorePrivilege = "SeRestorePrivilege"
 | 
						SeRestorePrivilege  = "SeRestorePrivilege"
 | 
				
			||||||
)
 | 
						SeSecurityPrivilege = "SeSecurityPrivilege"
 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	securityAnonymous = iota
 | 
					 | 
				
			||||||
	securityIdentification
 | 
					 | 
				
			||||||
	securityImpersonation
 | 
					 | 
				
			||||||
	securityDelegation
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -50,11 +47,9 @@ type PrivilegeError struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *PrivilegeError) Error() string {
 | 
					func (e *PrivilegeError) Error() string {
 | 
				
			||||||
	s := ""
 | 
						s := "Could not enable privilege "
 | 
				
			||||||
	if len(e.privileges) > 1 {
 | 
						if len(e.privileges) > 1 {
 | 
				
			||||||
		s = "Could not enable privileges "
 | 
							s = "Could not enable privileges "
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		s = "Could not enable privilege "
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for i, p := range e.privileges {
 | 
						for i, p := range e.privileges {
 | 
				
			||||||
		if i != 0 {
 | 
							if i != 0 {
 | 
				
			||||||
@@ -93,7 +88,7 @@ func RunWithPrivileges(names []string, fn func() error) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func mapPrivileges(names []string) ([]uint64, error) {
 | 
					func mapPrivileges(names []string) ([]uint64, error) {
 | 
				
			||||||
	var privileges []uint64
 | 
						privileges := make([]uint64, 0, len(names))
 | 
				
			||||||
	privNameMutex.Lock()
 | 
						privNameMutex.Lock()
 | 
				
			||||||
	defer privNameMutex.Unlock()
 | 
						defer privNameMutex.Unlock()
 | 
				
			||||||
	for _, name := range names {
 | 
						for _, name := range names {
 | 
				
			||||||
@@ -126,7 +121,7 @@ func enableDisableProcessPrivilege(names []string, action uint32) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p, _ := windows.GetCurrentProcess()
 | 
						p := windows.CurrentProcess()
 | 
				
			||||||
	var token windows.Token
 | 
						var token windows.Token
 | 
				
			||||||
	err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token)
 | 
						err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -139,10 +134,10 @@ func enableDisableProcessPrivilege(names []string, action uint32) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
 | 
					func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
 | 
				
			||||||
	var b bytes.Buffer
 | 
						var b bytes.Buffer
 | 
				
			||||||
	binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
 | 
						_ = binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
 | 
				
			||||||
	for _, p := range privileges {
 | 
						for _, p := range privileges {
 | 
				
			||||||
		binary.Write(&b, binary.LittleEndian, p)
 | 
							_ = binary.Write(&b, binary.LittleEndian, p)
 | 
				
			||||||
		binary.Write(&b, binary.LittleEndian, action)
 | 
							_ = binary.Write(&b, binary.LittleEndian, action)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	prevState := make([]byte, b.Len())
 | 
						prevState := make([]byte, b.Len())
 | 
				
			||||||
	reqSize := uint32(0)
 | 
						reqSize := uint32(0)
 | 
				
			||||||
@@ -150,7 +145,7 @@ func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) e
 | 
				
			|||||||
	if !success {
 | 
						if !success {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err == ERROR_NOT_ALL_ASSIGNED {
 | 
						if err == ERROR_NOT_ALL_ASSIGNED { //nolint:errorlint // err is Errno
 | 
				
			||||||
		return &PrivilegeError{privileges}
 | 
							return &PrivilegeError{privileges}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -176,7 +171,7 @@ func getPrivilegeName(luid uint64) string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newThreadToken() (windows.Token, error) {
 | 
					func newThreadToken() (windows.Token, error) {
 | 
				
			||||||
	err := impersonateSelf(securityImpersonation)
 | 
						err := impersonateSelf(windows.SecurityImpersonation)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, err
 | 
							return 0, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								vendor/github.com/Microsoft/go-winio/reparse.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/Microsoft/go-winio/reparse.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
@@ -113,16 +116,16 @@ func EncodeReparsePoint(rp *ReparsePoint) []byte {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var b bytes.Buffer
 | 
						var b bytes.Buffer
 | 
				
			||||||
	binary.Write(&b, binary.LittleEndian, &data)
 | 
						_ = binary.Write(&b, binary.LittleEndian, &data)
 | 
				
			||||||
	if !rp.IsMountPoint {
 | 
						if !rp.IsMountPoint {
 | 
				
			||||||
		flags := uint32(0)
 | 
							flags := uint32(0)
 | 
				
			||||||
		if relative {
 | 
							if relative {
 | 
				
			||||||
			flags |= 1
 | 
								flags |= 1
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		binary.Write(&b, binary.LittleEndian, flags)
 | 
							_ = binary.Write(&b, binary.LittleEndian, flags)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	binary.Write(&b, binary.LittleEndian, ntTarget16)
 | 
						_ = binary.Write(&b, binary.LittleEndian, ntTarget16)
 | 
				
			||||||
	binary.Write(&b, binary.LittleEndian, target16)
 | 
						_ = binary.Write(&b, binary.LittleEndian, target16)
 | 
				
			||||||
	return b.Bytes()
 | 
						return b.Bytes()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										64
									
								
								vendor/github.com/Microsoft/go-winio/sd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								vendor/github.com/Microsoft/go-winio/sd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,23 +1,25 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"unsafe"
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
 | 
					//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
 | 
				
			||||||
 | 
					//sys lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountSidW
 | 
				
			||||||
//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
 | 
					//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
 | 
				
			||||||
 | 
					//sys convertStringSidToSid(str *uint16, sid **byte) (err error) = advapi32.ConvertStringSidToSidW
 | 
				
			||||||
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
 | 
					//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
 | 
				
			||||||
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
 | 
					//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
 | 
				
			||||||
//sys localFree(mem uintptr) = LocalFree
 | 
					//sys localFree(mem uintptr) = LocalFree
 | 
				
			||||||
//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
 | 
					//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	cERROR_NONE_MAPPED = syscall.Errno(1332)
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type AccountLookupError struct {
 | 
					type AccountLookupError struct {
 | 
				
			||||||
	Name string
 | 
						Name string
 | 
				
			||||||
	Err  error
 | 
						Err  error
 | 
				
			||||||
@@ -28,8 +30,10 @@ func (e *AccountLookupError) Error() string {
 | 
				
			|||||||
		return "lookup account: empty account name specified"
 | 
							return "lookup account: empty account name specified"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var s string
 | 
						var s string
 | 
				
			||||||
	switch e.Err {
 | 
						switch {
 | 
				
			||||||
	case cERROR_NONE_MAPPED:
 | 
						case errors.Is(e.Err, windows.ERROR_INVALID_SID):
 | 
				
			||||||
 | 
							s = "the security ID structure is invalid"
 | 
				
			||||||
 | 
						case errors.Is(e.Err, windows.ERROR_NONE_MAPPED):
 | 
				
			||||||
		s = "not found"
 | 
							s = "not found"
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		s = e.Err.Error()
 | 
							s = e.Err.Error()
 | 
				
			||||||
@@ -37,6 +41,8 @@ func (e *AccountLookupError) Error() string {
 | 
				
			|||||||
	return "lookup account " + e.Name + ": " + s
 | 
						return "lookup account " + e.Name + ": " + s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *AccountLookupError) Unwrap() error { return e.Err }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type SddlConversionError struct {
 | 
					type SddlConversionError struct {
 | 
				
			||||||
	Sddl string
 | 
						Sddl string
 | 
				
			||||||
	Err  error
 | 
						Err  error
 | 
				
			||||||
@@ -46,15 +52,19 @@ func (e *SddlConversionError) Error() string {
 | 
				
			|||||||
	return "convert " + e.Sddl + ": " + e.Err.Error()
 | 
						return "convert " + e.Sddl + ": " + e.Err.Error()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *SddlConversionError) Unwrap() error { return e.Err }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LookupSidByName looks up the SID of an account by name
 | 
					// LookupSidByName looks up the SID of an account by name
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//revive:disable-next-line:var-naming SID, not Sid
 | 
				
			||||||
func LookupSidByName(name string) (sid string, err error) {
 | 
					func LookupSidByName(name string) (sid string, err error) {
 | 
				
			||||||
	if name == "" {
 | 
						if name == "" {
 | 
				
			||||||
		return "", &AccountLookupError{name, cERROR_NONE_MAPPED}
 | 
							return "", &AccountLookupError{name, windows.ERROR_NONE_MAPPED}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var sidSize, sidNameUse, refDomainSize uint32
 | 
						var sidSize, sidNameUse, refDomainSize uint32
 | 
				
			||||||
	err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
 | 
						err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
 | 
				
			||||||
	if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER {
 | 
						if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
 | 
				
			||||||
		return "", &AccountLookupError{name, err}
 | 
							return "", &AccountLookupError{name, err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sidBuffer := make([]byte, sidSize)
 | 
						sidBuffer := make([]byte, sidSize)
 | 
				
			||||||
@@ -73,6 +83,42 @@ func LookupSidByName(name string) (sid string, err error) {
 | 
				
			|||||||
	return sid, nil
 | 
						return sid, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LookupNameBySid looks up the name of an account by SID
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//revive:disable-next-line:var-naming SID, not Sid
 | 
				
			||||||
 | 
					func LookupNameBySid(sid string) (name string, err error) {
 | 
				
			||||||
 | 
						if sid == "" {
 | 
				
			||||||
 | 
							return "", &AccountLookupError{sid, windows.ERROR_NONE_MAPPED}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sidBuffer, err := windows.UTF16PtrFromString(sid)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", &AccountLookupError{sid, err}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var sidPtr *byte
 | 
				
			||||||
 | 
						if err = convertStringSidToSid(sidBuffer, &sidPtr); err != nil {
 | 
				
			||||||
 | 
							return "", &AccountLookupError{sid, err}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer localFree(uintptr(unsafe.Pointer(sidPtr)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var nameSize, refDomainSize, sidNameUse uint32
 | 
				
			||||||
 | 
						err = lookupAccountSid(nil, sidPtr, nil, &nameSize, nil, &refDomainSize, &sidNameUse)
 | 
				
			||||||
 | 
						if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
 | 
				
			||||||
 | 
							return "", &AccountLookupError{sid, err}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nameBuffer := make([]uint16, nameSize)
 | 
				
			||||||
 | 
						refDomainBuffer := make([]uint16, refDomainSize)
 | 
				
			||||||
 | 
						err = lookupAccountSid(nil, sidPtr, &nameBuffer[0], &nameSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", &AccountLookupError{sid, err}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						name = windows.UTF16ToString(nameBuffer)
 | 
				
			||||||
 | 
						return name, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
 | 
					func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
 | 
				
			||||||
	var sdBuffer uintptr
 | 
						var sdBuffer uintptr
 | 
				
			||||||
	err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
 | 
						err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
 | 
				
			||||||
@@ -87,7 +133,7 @@ func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func SecurityDescriptorToSddl(sd []byte) (string, error) {
 | 
					func SecurityDescriptorToSddl(sd []byte) (string, error) {
 | 
				
			||||||
	var sddl *uint16
 | 
						var sddl *uint16
 | 
				
			||||||
	// The returned string length seems to including an aribtrary number of terminating NULs.
 | 
						// The returned string length seems to include an arbitrary number of terminating NULs.
 | 
				
			||||||
	// Don't use it.
 | 
						// Don't use it.
 | 
				
			||||||
	err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
 | 
						err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								vendor/github.com/Microsoft/go-winio/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/Microsoft/go-winio/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
 | 
					//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								vendor/github.com/Microsoft/go-winio/tools.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/Microsoft/go-winio/tools.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					//go:build tools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package winio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import _ "golang.org/x/tools/cmd/stringer"
 | 
				
			||||||
							
								
								
									
										122
									
								
								vendor/github.com/Microsoft/go-winio/vhd/vhd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										122
									
								
								vendor/github.com/Microsoft/go-winio/vhd/vhd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package vhd
 | 
					package vhd
 | 
				
			||||||
@@ -7,17 +8,16 @@ import (
 | 
				
			|||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/Microsoft/go-winio/pkg/guid"
 | 
						"github.com/Microsoft/go-winio/pkg/guid"
 | 
				
			||||||
	"github.com/pkg/errors"
 | 
					 | 
				
			||||||
	"golang.org/x/sys/windows"
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:generate go run mksyscall_windows.go -output zvhd_windows.go vhd.go
 | 
					//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zvhd_windows.go vhd.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = virtdisk.CreateVirtualDisk
 | 
					//sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) = virtdisk.CreateVirtualDisk
 | 
				
			||||||
//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) [failretval != 0] = virtdisk.OpenVirtualDisk
 | 
					//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk
 | 
				
			||||||
//sys attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (err error) [failretval != 0] = virtdisk.AttachVirtualDisk
 | 
					//sys attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (win32err error) = virtdisk.AttachVirtualDisk
 | 
				
			||||||
//sys detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = virtdisk.DetachVirtualDisk
 | 
					//sys detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (win32err error) = virtdisk.DetachVirtualDisk
 | 
				
			||||||
//sys getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) [failretval != 0] = virtdisk.GetVirtualDiskPhysicalPath
 | 
					//sys getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (win32err error) = virtdisk.GetVirtualDiskPhysicalPath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type (
 | 
					type (
 | 
				
			||||||
	CreateVirtualDiskFlag uint32
 | 
						CreateVirtualDiskFlag uint32
 | 
				
			||||||
@@ -62,20 +62,35 @@ type OpenVirtualDiskParameters struct {
 | 
				
			|||||||
	Version2 OpenVersion2
 | 
						Version2 OpenVersion2
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The higher level `OpenVersion2` struct uses `bool`s to refer to `GetInfoOnly` and `ReadOnly` for ease of use. However,
 | 
				
			||||||
 | 
					// the internal windows structure uses `BOOL`s aka int32s for these types. `openVersion2` is used for translating
 | 
				
			||||||
 | 
					// `OpenVersion2` fields to the correct windows internal field types on the `Open____` methods.
 | 
				
			||||||
 | 
					type openVersion2 struct {
 | 
				
			||||||
 | 
						getInfoOnly    int32
 | 
				
			||||||
 | 
						readOnly       int32
 | 
				
			||||||
 | 
						resiliencyGUID guid.GUID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type openVirtualDiskParameters struct {
 | 
				
			||||||
 | 
						version  uint32
 | 
				
			||||||
 | 
						version2 openVersion2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type AttachVersion2 struct {
 | 
					type AttachVersion2 struct {
 | 
				
			||||||
	RestrictedOffset uint64
 | 
						RestrictedOffset uint64
 | 
				
			||||||
	RestrictedLength uint64
 | 
						RestrictedLength uint64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type AttachVirtualDiskParameters struct {
 | 
					type AttachVirtualDiskParameters struct {
 | 
				
			||||||
	Version  uint32 // Must always be set to 2
 | 
						Version  uint32
 | 
				
			||||||
	Version2 AttachVersion2
 | 
						Version2 AttachVersion2
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 | 
						//revive:disable-next-line:var-naming ALL_CAPS
 | 
				
			||||||
	VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 0x3
 | 
						VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 0x3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Access Mask for opening a VHD
 | 
						// Access Mask for opening a VHD.
 | 
				
			||||||
	VirtualDiskAccessNone     VirtualDiskAccessMask = 0x00000000
 | 
						VirtualDiskAccessNone     VirtualDiskAccessMask = 0x00000000
 | 
				
			||||||
	VirtualDiskAccessAttachRO VirtualDiskAccessMask = 0x00010000
 | 
						VirtualDiskAccessAttachRO VirtualDiskAccessMask = 0x00010000
 | 
				
			||||||
	VirtualDiskAccessAttachRW VirtualDiskAccessMask = 0x00020000
 | 
						VirtualDiskAccessAttachRW VirtualDiskAccessMask = 0x00020000
 | 
				
			||||||
@@ -87,7 +102,7 @@ const (
 | 
				
			|||||||
	VirtualDiskAccessAll      VirtualDiskAccessMask = 0x003f0000
 | 
						VirtualDiskAccessAll      VirtualDiskAccessMask = 0x003f0000
 | 
				
			||||||
	VirtualDiskAccessWritable VirtualDiskAccessMask = 0x00320000
 | 
						VirtualDiskAccessWritable VirtualDiskAccessMask = 0x00320000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Flags for creating a VHD
 | 
						// Flags for creating a VHD.
 | 
				
			||||||
	CreateVirtualDiskFlagNone                              CreateVirtualDiskFlag = 0x0
 | 
						CreateVirtualDiskFlagNone                              CreateVirtualDiskFlag = 0x0
 | 
				
			||||||
	CreateVirtualDiskFlagFullPhysicalAllocation            CreateVirtualDiskFlag = 0x1
 | 
						CreateVirtualDiskFlagFullPhysicalAllocation            CreateVirtualDiskFlag = 0x1
 | 
				
			||||||
	CreateVirtualDiskFlagPreventWritesToSourceDisk         CreateVirtualDiskFlag = 0x2
 | 
						CreateVirtualDiskFlagPreventWritesToSourceDisk         CreateVirtualDiskFlag = 0x2
 | 
				
			||||||
@@ -95,12 +110,12 @@ const (
 | 
				
			|||||||
	CreateVirtualDiskFlagCreateBackingStorage              CreateVirtualDiskFlag = 0x8
 | 
						CreateVirtualDiskFlagCreateBackingStorage              CreateVirtualDiskFlag = 0x8
 | 
				
			||||||
	CreateVirtualDiskFlagUseChangeTrackingSourceLimit      CreateVirtualDiskFlag = 0x10
 | 
						CreateVirtualDiskFlagUseChangeTrackingSourceLimit      CreateVirtualDiskFlag = 0x10
 | 
				
			||||||
	CreateVirtualDiskFlagPreserveParentChangeTrackingState CreateVirtualDiskFlag = 0x20
 | 
						CreateVirtualDiskFlagPreserveParentChangeTrackingState CreateVirtualDiskFlag = 0x20
 | 
				
			||||||
	CreateVirtualDiskFlagVhdSetUseOriginalBackingStorage   CreateVirtualDiskFlag = 0x40
 | 
						CreateVirtualDiskFlagVhdSetUseOriginalBackingStorage   CreateVirtualDiskFlag = 0x40 //revive:disable-line:var-naming VHD, not Vhd
 | 
				
			||||||
	CreateVirtualDiskFlagSparseFile                        CreateVirtualDiskFlag = 0x80
 | 
						CreateVirtualDiskFlagSparseFile                        CreateVirtualDiskFlag = 0x80
 | 
				
			||||||
	CreateVirtualDiskFlagPmemCompatible                    CreateVirtualDiskFlag = 0x100
 | 
						CreateVirtualDiskFlagPmemCompatible                    CreateVirtualDiskFlag = 0x100 //revive:disable-line:var-naming PMEM, not Pmem
 | 
				
			||||||
	CreateVirtualDiskFlagSupportCompressedVolumes          CreateVirtualDiskFlag = 0x200
 | 
						CreateVirtualDiskFlagSupportCompressedVolumes          CreateVirtualDiskFlag = 0x200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Flags for opening a VHD
 | 
						// Flags for opening a VHD.
 | 
				
			||||||
	OpenVirtualDiskFlagNone                        VirtualDiskFlag = 0x00000000
 | 
						OpenVirtualDiskFlagNone                        VirtualDiskFlag = 0x00000000
 | 
				
			||||||
	OpenVirtualDiskFlagNoParents                   VirtualDiskFlag = 0x00000001
 | 
						OpenVirtualDiskFlagNoParents                   VirtualDiskFlag = 0x00000001
 | 
				
			||||||
	OpenVirtualDiskFlagBlankFile                   VirtualDiskFlag = 0x00000002
 | 
						OpenVirtualDiskFlagBlankFile                   VirtualDiskFlag = 0x00000002
 | 
				
			||||||
@@ -113,7 +128,7 @@ const (
 | 
				
			|||||||
	OpenVirtualDiskFlagNoWriteHardening            VirtualDiskFlag = 0x00000100
 | 
						OpenVirtualDiskFlagNoWriteHardening            VirtualDiskFlag = 0x00000100
 | 
				
			||||||
	OpenVirtualDiskFlagSupportCompressedVolumes    VirtualDiskFlag = 0x00000200
 | 
						OpenVirtualDiskFlagSupportCompressedVolumes    VirtualDiskFlag = 0x00000200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Flags for attaching a VHD
 | 
						// Flags for attaching a VHD.
 | 
				
			||||||
	AttachVirtualDiskFlagNone                          AttachVirtualDiskFlag = 0x00000000
 | 
						AttachVirtualDiskFlagNone                          AttachVirtualDiskFlag = 0x00000000
 | 
				
			||||||
	AttachVirtualDiskFlagReadOnly                      AttachVirtualDiskFlag = 0x00000001
 | 
						AttachVirtualDiskFlagReadOnly                      AttachVirtualDiskFlag = 0x00000001
 | 
				
			||||||
	AttachVirtualDiskFlagNoDriveLetter                 AttachVirtualDiskFlag = 0x00000002
 | 
						AttachVirtualDiskFlagNoDriveLetter                 AttachVirtualDiskFlag = 0x00000002
 | 
				
			||||||
@@ -126,12 +141,14 @@ const (
 | 
				
			|||||||
	AttachVirtualDiskFlagSinglePartition               AttachVirtualDiskFlag = 0x00000100
 | 
						AttachVirtualDiskFlagSinglePartition               AttachVirtualDiskFlag = 0x00000100
 | 
				
			||||||
	AttachVirtualDiskFlagRegisterVolume                AttachVirtualDiskFlag = 0x00000200
 | 
						AttachVirtualDiskFlagRegisterVolume                AttachVirtualDiskFlag = 0x00000200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Flags for detaching a VHD
 | 
						// Flags for detaching a VHD.
 | 
				
			||||||
	DetachVirtualDiskFlagNone DetachVirtualDiskFlag = 0x0
 | 
						DetachVirtualDiskFlagNone DetachVirtualDiskFlag = 0x0
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CreateVhdx is a helper function to create a simple vhdx file at the given path using
 | 
					// CreateVhdx is a helper function to create a simple vhdx file at the given path using
 | 
				
			||||||
// default values.
 | 
					// default values.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//revive:disable-next-line:var-naming VHDX, not Vhdx
 | 
				
			||||||
func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
 | 
					func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
 | 
				
			||||||
	params := CreateVirtualDiskParameters{
 | 
						params := CreateVirtualDiskParameters{
 | 
				
			||||||
		Version: 2,
 | 
							Version: 2,
 | 
				
			||||||
@@ -146,21 +163,20 @@ func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := syscall.CloseHandle(handle); err != nil {
 | 
						return syscall.CloseHandle(handle)
 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DetachVirtualDisk detaches a virtual hard disk by handle.
 | 
					// DetachVirtualDisk detaches a virtual hard disk by handle.
 | 
				
			||||||
func DetachVirtualDisk(handle syscall.Handle) (err error) {
 | 
					func DetachVirtualDisk(handle syscall.Handle) (err error) {
 | 
				
			||||||
	if err := detachVirtualDisk(handle, 0, 0); err != nil {
 | 
						if err := detachVirtualDisk(handle, 0, 0); err != nil {
 | 
				
			||||||
		return errors.Wrap(err, "failed to detach virtual disk")
 | 
							return fmt.Errorf("failed to detach virtual disk: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DetachVhd detaches a vhd found at `path`.
 | 
					// DetachVhd detaches a vhd found at `path`.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//revive:disable-next-line:var-naming VHD, not Vhd
 | 
				
			||||||
func DetachVhd(path string) error {
 | 
					func DetachVhd(path string) error {
 | 
				
			||||||
	handle, err := OpenVirtualDisk(
 | 
						handle, err := OpenVirtualDisk(
 | 
				
			||||||
		path,
 | 
							path,
 | 
				
			||||||
@@ -170,12 +186,16 @@ func DetachVhd(path string) error {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer syscall.CloseHandle(handle)
 | 
						defer syscall.CloseHandle(handle) //nolint:errcheck
 | 
				
			||||||
	return DetachVirtualDisk(handle)
 | 
						return DetachVirtualDisk(handle)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AttachVirtualDisk attaches a virtual hard disk for use.
 | 
					// AttachVirtualDisk attaches a virtual hard disk for use.
 | 
				
			||||||
func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtualDiskFlag, parameters *AttachVirtualDiskParameters) (err error) {
 | 
					func AttachVirtualDisk(
 | 
				
			||||||
 | 
						handle syscall.Handle,
 | 
				
			||||||
 | 
						attachVirtualDiskFlag AttachVirtualDiskFlag,
 | 
				
			||||||
 | 
						parameters *AttachVirtualDiskParameters,
 | 
				
			||||||
 | 
					) (err error) {
 | 
				
			||||||
	// Supports both version 1 and 2 of the attach parameters as version 2 wasn't present in RS5.
 | 
						// Supports both version 1 and 2 of the attach parameters as version 2 wasn't present in RS5.
 | 
				
			||||||
	if err := attachVirtualDisk(
 | 
						if err := attachVirtualDisk(
 | 
				
			||||||
		handle,
 | 
							handle,
 | 
				
			||||||
@@ -185,13 +205,15 @@ func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtua
 | 
				
			|||||||
		parameters,
 | 
							parameters,
 | 
				
			||||||
		nil,
 | 
							nil,
 | 
				
			||||||
	); err != nil {
 | 
						); err != nil {
 | 
				
			||||||
		return errors.Wrap(err, "failed to attach virtual disk")
 | 
							return fmt.Errorf("failed to attach virtual disk: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AttachVhd attaches a virtual hard disk at `path` for use. Attaches using version 2
 | 
					// AttachVhd attaches a virtual hard disk at `path` for use. Attaches using version 2
 | 
				
			||||||
// of the ATTACH_VIRTUAL_DISK_PARAMETERS.
 | 
					// of the ATTACH_VIRTUAL_DISK_PARAMETERS.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//revive:disable-next-line:var-naming VHD, not Vhd
 | 
				
			||||||
func AttachVhd(path string) (err error) {
 | 
					func AttachVhd(path string) (err error) {
 | 
				
			||||||
	handle, err := OpenVirtualDisk(
 | 
						handle, err := OpenVirtualDisk(
 | 
				
			||||||
		path,
 | 
							path,
 | 
				
			||||||
@@ -202,20 +224,24 @@ func AttachVhd(path string) (err error) {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	defer syscall.CloseHandle(handle)
 | 
						defer syscall.CloseHandle(handle) //nolint:errcheck
 | 
				
			||||||
	params := AttachVirtualDiskParameters{Version: 2}
 | 
						params := AttachVirtualDiskParameters{Version: 2}
 | 
				
			||||||
	if err := AttachVirtualDisk(
 | 
						if err := AttachVirtualDisk(
 | 
				
			||||||
		handle,
 | 
							handle,
 | 
				
			||||||
		AttachVirtualDiskFlagNone,
 | 
							AttachVirtualDiskFlagNone,
 | 
				
			||||||
		¶ms,
 | 
							¶ms,
 | 
				
			||||||
	); err != nil {
 | 
						); err != nil {
 | 
				
			||||||
		return errors.Wrap(err, "failed to attach virtual disk")
 | 
							return fmt.Errorf("failed to attach virtual disk: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags.
 | 
					// OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags.
 | 
				
			||||||
func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag) (syscall.Handle, error) {
 | 
					func OpenVirtualDisk(
 | 
				
			||||||
 | 
						vhdPath string,
 | 
				
			||||||
 | 
						virtualDiskAccessMask VirtualDiskAccessMask,
 | 
				
			||||||
 | 
						openVirtualDiskFlags VirtualDiskFlag,
 | 
				
			||||||
 | 
					) (syscall.Handle, error) {
 | 
				
			||||||
	parameters := OpenVirtualDiskParameters{Version: 2}
 | 
						parameters := OpenVirtualDiskParameters{Version: 2}
 | 
				
			||||||
	handle, err := OpenVirtualDiskWithParameters(
 | 
						handle, err := OpenVirtualDiskWithParameters(
 | 
				
			||||||
		vhdPath,
 | 
							vhdPath,
 | 
				
			||||||
@@ -230,29 +256,55 @@ func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// OpenVirtualDiskWithParameters obtains a handle to a VHD opened with supplied access mask, flags and parameters.
 | 
					// OpenVirtualDiskWithParameters obtains a handle to a VHD opened with supplied access mask, flags and parameters.
 | 
				
			||||||
func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag, parameters *OpenVirtualDiskParameters) (syscall.Handle, error) {
 | 
					func OpenVirtualDiskWithParameters(
 | 
				
			||||||
 | 
						vhdPath string,
 | 
				
			||||||
 | 
						virtualDiskAccessMask VirtualDiskAccessMask,
 | 
				
			||||||
 | 
						openVirtualDiskFlags VirtualDiskFlag,
 | 
				
			||||||
 | 
						parameters *OpenVirtualDiskParameters,
 | 
				
			||||||
 | 
					) (syscall.Handle, error) {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		handle      syscall.Handle
 | 
							handle      syscall.Handle
 | 
				
			||||||
		defaultType VirtualStorageType
 | 
							defaultType VirtualStorageType
 | 
				
			||||||
 | 
							getInfoOnly int32
 | 
				
			||||||
 | 
							readOnly    int32
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	if parameters.Version != 2 {
 | 
						if parameters.Version != 2 {
 | 
				
			||||||
		return handle, fmt.Errorf("only version 2 VHDs are supported, found version: %d", parameters.Version)
 | 
							return handle, fmt.Errorf("only version 2 VHDs are supported, found version: %d", parameters.Version)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if parameters.Version2.GetInfoOnly {
 | 
				
			||||||
 | 
							getInfoOnly = 1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if parameters.Version2.ReadOnly {
 | 
				
			||||||
 | 
							readOnly = 1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						params := &openVirtualDiskParameters{
 | 
				
			||||||
 | 
							version: parameters.Version,
 | 
				
			||||||
 | 
							version2: openVersion2{
 | 
				
			||||||
 | 
								getInfoOnly,
 | 
				
			||||||
 | 
								readOnly,
 | 
				
			||||||
 | 
								parameters.Version2.ResiliencyGUID,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err := openVirtualDisk(
 | 
						if err := openVirtualDisk(
 | 
				
			||||||
		&defaultType,
 | 
							&defaultType,
 | 
				
			||||||
		vhdPath,
 | 
							vhdPath,
 | 
				
			||||||
		uint32(virtualDiskAccessMask),
 | 
							uint32(virtualDiskAccessMask),
 | 
				
			||||||
		uint32(openVirtualDiskFlags),
 | 
							uint32(openVirtualDiskFlags),
 | 
				
			||||||
		parameters,
 | 
							params,
 | 
				
			||||||
		&handle,
 | 
							&handle,
 | 
				
			||||||
	); err != nil {
 | 
						); err != nil {
 | 
				
			||||||
		return 0, errors.Wrap(err, "failed to open virtual disk")
 | 
							return 0, fmt.Errorf("failed to open virtual disk: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return handle, nil
 | 
						return handle, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CreateVirtualDisk creates a virtual harddisk and returns a handle to the disk.
 | 
					// CreateVirtualDisk creates a virtual harddisk and returns a handle to the disk.
 | 
				
			||||||
func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, createVirtualDiskFlags CreateVirtualDiskFlag, parameters *CreateVirtualDiskParameters) (syscall.Handle, error) {
 | 
					func CreateVirtualDisk(
 | 
				
			||||||
 | 
						path string,
 | 
				
			||||||
 | 
						virtualDiskAccessMask VirtualDiskAccessMask,
 | 
				
			||||||
 | 
						createVirtualDiskFlags CreateVirtualDiskFlag,
 | 
				
			||||||
 | 
						parameters *CreateVirtualDiskParameters,
 | 
				
			||||||
 | 
					) (syscall.Handle, error) {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		handle      syscall.Handle
 | 
							handle      syscall.Handle
 | 
				
			||||||
		defaultType VirtualStorageType
 | 
							defaultType VirtualStorageType
 | 
				
			||||||
@@ -272,7 +324,7 @@ func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask,
 | 
				
			|||||||
		nil,
 | 
							nil,
 | 
				
			||||||
		&handle,
 | 
							&handle,
 | 
				
			||||||
	); err != nil {
 | 
						); err != nil {
 | 
				
			||||||
		return handle, errors.Wrap(err, "failed to create virtual disk")
 | 
							return handle, fmt.Errorf("failed to create virtual disk: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return handle, nil
 | 
						return handle, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -290,12 +342,14 @@ func GetVirtualDiskPhysicalPath(handle syscall.Handle) (_ string, err error) {
 | 
				
			|||||||
		&diskPathSizeInBytes,
 | 
							&diskPathSizeInBytes,
 | 
				
			||||||
		&diskPhysicalPathBuf[0],
 | 
							&diskPhysicalPathBuf[0],
 | 
				
			||||||
	); err != nil {
 | 
						); err != nil {
 | 
				
			||||||
		return "", errors.Wrap(err, "failed to get disk physical path")
 | 
							return "", fmt.Errorf("failed to get disk physical path: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return windows.UTF16ToString(diskPhysicalPathBuf[:]), nil
 | 
						return windows.UTF16ToString(diskPhysicalPathBuf[:]), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CreateDiffVhd is a helper function to create a differencing virtual disk.
 | 
					// CreateDiffVhd is a helper function to create a differencing virtual disk.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//revive:disable-next-line:var-naming VHD, not Vhd
 | 
				
			||||||
func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error {
 | 
					func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error {
 | 
				
			||||||
	// Setting `ParentPath` is how to signal to create a differencing disk.
 | 
						// Setting `ParentPath` is how to signal to create a differencing disk.
 | 
				
			||||||
	createParams := &CreateVirtualDiskParameters{
 | 
						createParams := &CreateVirtualDiskParameters{
 | 
				
			||||||
@@ -314,10 +368,10 @@ func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error
 | 
				
			|||||||
		createParams,
 | 
							createParams,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return fmt.Errorf("failed to create differencing vhd: %s", err)
 | 
							return fmt.Errorf("failed to create differencing vhd: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := syscall.CloseHandle(vhdHandle); err != nil {
 | 
						if err := syscall.CloseHandle(vhdHandle); err != nil {
 | 
				
			||||||
		return fmt.Errorf("failed to close differencing vhd handle: %s", err)
 | 
							return fmt.Errorf("failed to close differencing vhd handle: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										56
									
								
								vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										56
									
								
								vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,6 @@
 | 
				
			|||||||
// Code generated by 'go generate'; DO NOT EDIT.
 | 
					//go:build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package vhd
 | 
					package vhd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -47,60 +49,60 @@ var (
 | 
				
			|||||||
	procOpenVirtualDisk            = modvirtdisk.NewProc("OpenVirtualDisk")
 | 
						procOpenVirtualDisk            = modvirtdisk.NewProc("OpenVirtualDisk")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (err error) {
 | 
					func attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (win32err error) {
 | 
				
			||||||
	r1, _, e1 := syscall.Syscall6(procAttachVirtualDisk.Addr(), 6, uintptr(handle), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(attachVirtualDiskFlag), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped)))
 | 
						r0, _, _ := syscall.Syscall6(procAttachVirtualDisk.Addr(), 6, uintptr(handle), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(attachVirtualDiskFlag), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped)))
 | 
				
			||||||
	if r1 != 0 {
 | 
						if r0 != 0 {
 | 
				
			||||||
		err = errnoErr(e1)
 | 
							win32err = syscall.Errno(r0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) {
 | 
					func createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) {
 | 
				
			||||||
	var _p0 *uint16
 | 
						var _p0 *uint16
 | 
				
			||||||
	_p0, err = syscall.UTF16PtrFromString(path)
 | 
						_p0, win32err = syscall.UTF16PtrFromString(path)
 | 
				
			||||||
	if err != nil {
 | 
						if win32err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return _createVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, securityDescriptor, createVirtualDiskFlags, providerSpecificFlags, parameters, overlapped, handle)
 | 
						return _createVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, securityDescriptor, createVirtualDiskFlags, providerSpecificFlags, parameters, overlapped, handle)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func _createVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) {
 | 
					func _createVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) {
 | 
				
			||||||
	r1, _, e1 := syscall.Syscall9(procCreateVirtualDisk.Addr(), 9, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(createVirtualDiskFlags), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(handle)))
 | 
						r0, _, _ := syscall.Syscall9(procCreateVirtualDisk.Addr(), 9, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(createVirtualDiskFlags), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(handle)))
 | 
				
			||||||
	if r1 != 0 {
 | 
						if r0 != 0 {
 | 
				
			||||||
		err = errnoErr(e1)
 | 
							win32err = syscall.Errno(r0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) {
 | 
					func detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (win32err error) {
 | 
				
			||||||
	r1, _, e1 := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(detachVirtualDiskFlags), uintptr(providerSpecificFlags))
 | 
						r0, _, _ := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(detachVirtualDiskFlags), uintptr(providerSpecificFlags))
 | 
				
			||||||
	if r1 != 0 {
 | 
						if r0 != 0 {
 | 
				
			||||||
		err = errnoErr(e1)
 | 
							win32err = syscall.Errno(r0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) {
 | 
					func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (win32err error) {
 | 
				
			||||||
	r1, _, e1 := syscall.Syscall(procGetVirtualDiskPhysicalPath.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(diskPathSizeInBytes)), uintptr(unsafe.Pointer(buffer)))
 | 
						r0, _, _ := syscall.Syscall(procGetVirtualDiskPhysicalPath.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(diskPathSizeInBytes)), uintptr(unsafe.Pointer(buffer)))
 | 
				
			||||||
	if r1 != 0 {
 | 
						if r0 != 0 {
 | 
				
			||||||
		err = errnoErr(e1)
 | 
							win32err = syscall.Errno(r0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) {
 | 
					func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) {
 | 
				
			||||||
	var _p0 *uint16
 | 
						var _p0 *uint16
 | 
				
			||||||
	_p0, err = syscall.UTF16PtrFromString(path)
 | 
						_p0, win32err = syscall.UTF16PtrFromString(path)
 | 
				
			||||||
	if err != nil {
 | 
						if win32err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, openVirtualDiskFlags, parameters, handle)
 | 
						return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, openVirtualDiskFlags, parameters, handle)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) {
 | 
					func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) {
 | 
				
			||||||
	r1, _, e1 := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(openVirtualDiskFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle)))
 | 
						r0, _, _ := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(openVirtualDiskFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle)))
 | 
				
			||||||
	if r1 != 0 {
 | 
						if r0 != 0 {
 | 
				
			||||||
		err = errnoErr(e1)
 | 
							win32err = syscall.Errno(r0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										45
									
								
								vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,6 @@
 | 
				
			|||||||
// Code generated by 'go generate'; DO NOT EDIT.
 | 
					//go:build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package winio
 | 
					package winio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -47,9 +49,11 @@ var (
 | 
				
			|||||||
	procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
 | 
						procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
 | 
				
			||||||
	procConvertSidToStringSidW                               = modadvapi32.NewProc("ConvertSidToStringSidW")
 | 
						procConvertSidToStringSidW                               = modadvapi32.NewProc("ConvertSidToStringSidW")
 | 
				
			||||||
	procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
 | 
						procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
 | 
				
			||||||
 | 
						procConvertStringSidToSidW                               = modadvapi32.NewProc("ConvertStringSidToSidW")
 | 
				
			||||||
	procGetSecurityDescriptorLength                          = modadvapi32.NewProc("GetSecurityDescriptorLength")
 | 
						procGetSecurityDescriptorLength                          = modadvapi32.NewProc("GetSecurityDescriptorLength")
 | 
				
			||||||
	procImpersonateSelf                                      = modadvapi32.NewProc("ImpersonateSelf")
 | 
						procImpersonateSelf                                      = modadvapi32.NewProc("ImpersonateSelf")
 | 
				
			||||||
	procLookupAccountNameW                                   = modadvapi32.NewProc("LookupAccountNameW")
 | 
						procLookupAccountNameW                                   = modadvapi32.NewProc("LookupAccountNameW")
 | 
				
			||||||
 | 
						procLookupAccountSidW                                    = modadvapi32.NewProc("LookupAccountSidW")
 | 
				
			||||||
	procLookupPrivilegeDisplayNameW                          = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
 | 
						procLookupPrivilegeDisplayNameW                          = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
 | 
				
			||||||
	procLookupPrivilegeNameW                                 = modadvapi32.NewProc("LookupPrivilegeNameW")
 | 
						procLookupPrivilegeNameW                                 = modadvapi32.NewProc("LookupPrivilegeNameW")
 | 
				
			||||||
	procLookupPrivilegeValueW                                = modadvapi32.NewProc("LookupPrivilegeValueW")
 | 
						procLookupPrivilegeValueW                                = modadvapi32.NewProc("LookupPrivilegeValueW")
 | 
				
			||||||
@@ -74,7 +78,6 @@ var (
 | 
				
			|||||||
	procRtlDosPathNameToNtPathName_U                         = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
 | 
						procRtlDosPathNameToNtPathName_U                         = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
 | 
				
			||||||
	procRtlNtStatusToDosErrorNoTeb                           = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
 | 
						procRtlNtStatusToDosErrorNoTeb                           = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
 | 
				
			||||||
	procWSAGetOverlappedResult                               = modws2_32.NewProc("WSAGetOverlappedResult")
 | 
						procWSAGetOverlappedResult                               = modws2_32.NewProc("WSAGetOverlappedResult")
 | 
				
			||||||
	procbind                                                 = modws2_32.NewProc("bind")
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
 | 
					func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
 | 
				
			||||||
@@ -123,6 +126,14 @@ func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision
 | 
				
			|||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func convertStringSidToSid(str *uint16, sid **byte) (err error) {
 | 
				
			||||||
 | 
						r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid)), 0)
 | 
				
			||||||
 | 
						if r1 == 0 {
 | 
				
			||||||
 | 
							err = errnoErr(e1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
 | 
					func getSecurityDescriptorLength(sd uintptr) (len uint32) {
 | 
				
			||||||
	r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
 | 
						r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
 | 
				
			||||||
	len = uint32(r0)
 | 
						len = uint32(r0)
 | 
				
			||||||
@@ -154,6 +165,14 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS
 | 
				
			|||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
 | 
				
			||||||
 | 
						r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
 | 
				
			||||||
 | 
						if r1 == 0 {
 | 
				
			||||||
 | 
							err = errnoErr(e1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
 | 
					func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
 | 
				
			||||||
	var _p0 *uint16
 | 
						var _p0 *uint16
 | 
				
			||||||
	_p0, err = syscall.UTF16PtrFromString(systemName)
 | 
						_p0, err = syscall.UTF16PtrFromString(systemName)
 | 
				
			||||||
@@ -380,25 +399,25 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro
 | 
				
			|||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) {
 | 
					func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) {
 | 
				
			||||||
	r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
 | 
						r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
 | 
				
			||||||
	status = ntstatus(r0)
 | 
						status = ntStatus(r0)
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) {
 | 
					func rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) {
 | 
				
			||||||
	r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
 | 
						r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
 | 
				
			||||||
	status = ntstatus(r0)
 | 
						status = ntStatus(r0)
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) {
 | 
					func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) {
 | 
				
			||||||
	r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
 | 
						r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
 | 
				
			||||||
	status = ntstatus(r0)
 | 
						status = ntStatus(r0)
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func rtlNtStatusToDosError(status ntstatus) (winerr error) {
 | 
					func rtlNtStatusToDosError(status ntStatus) (winerr error) {
 | 
				
			||||||
	r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
 | 
						r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
 | 
				
			||||||
	if r0 != 0 {
 | 
						if r0 != 0 {
 | 
				
			||||||
		winerr = syscall.Errno(r0)
 | 
							winerr = syscall.Errno(r0)
 | 
				
			||||||
@@ -417,11 +436,3 @@ func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
 | 
					 | 
				
			||||||
	r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
 | 
					 | 
				
			||||||
	if r1 == socketError {
 | 
					 | 
				
			||||||
		err = errnoErr(e1)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										657
									
								
								vendor/golang.org/x/tools/cmd/stringer/stringer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										657
									
								
								vendor/golang.org/x/tools/cmd/stringer/stringer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,657 @@
 | 
				
			|||||||
 | 
					// Copyright 2014 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer
 | 
				
			||||||
 | 
					// interface. Given the name of a (signed or unsigned) integer type T that has constants
 | 
				
			||||||
 | 
					// defined, stringer will create a new self-contained Go source file implementing
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	func (t T) String() string
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The file is created in the same package and directory as the package that defines T.
 | 
				
			||||||
 | 
					// It has helpful defaults designed for use with go generate.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Stringer works best with constants that are consecutive values such as created using iota,
 | 
				
			||||||
 | 
					// but creates good code regardless. In the future it might also provide custom support for
 | 
				
			||||||
 | 
					// constant sets that are bit patterns.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// For example, given this snippet,
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	package painkiller
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	type Pill int
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	const (
 | 
				
			||||||
 | 
					//		Placebo Pill = iota
 | 
				
			||||||
 | 
					//		Aspirin
 | 
				
			||||||
 | 
					//		Ibuprofen
 | 
				
			||||||
 | 
					//		Paracetamol
 | 
				
			||||||
 | 
					//		Acetaminophen = Paracetamol
 | 
				
			||||||
 | 
					//	)
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// running this command
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	stringer -type=Pill
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// in the same directory will create the file pill_string.go, in package painkiller,
 | 
				
			||||||
 | 
					// containing a definition of
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	func (Pill) String() string
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// That method will translate the value of a Pill constant to the string representation
 | 
				
			||||||
 | 
					// of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will
 | 
				
			||||||
 | 
					// print the string "Aspirin".
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Typically this process would be run using go generate, like this:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	//go:generate stringer -type=Pill
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If multiple constants have the same value, the lexically first matching name will
 | 
				
			||||||
 | 
					// be used (in the example, Acetaminophen will print as "Paracetamol").
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// With no arguments, it processes the package in the current directory.
 | 
				
			||||||
 | 
					// Otherwise, the arguments must name a single directory holding a Go package
 | 
				
			||||||
 | 
					// or a set of Go source files that represent a single Go package.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The -type flag accepts a comma-separated list of types so a single run can
 | 
				
			||||||
 | 
					// generate methods for multiple types. The default output file is t_string.go,
 | 
				
			||||||
 | 
					// where t is the lower-cased name of the first type listed. It can be overridden
 | 
				
			||||||
 | 
					// with the -output flag.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The -linecomment flag tells stringer to generate the text of any line comment, trimmed
 | 
				
			||||||
 | 
					// of leading spaces, instead of the constant name. For instance, if the constants above had a
 | 
				
			||||||
 | 
					// Pill prefix, one could write
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	PillAspirin // Aspirin
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// to suppress it in the output.
 | 
				
			||||||
 | 
					package main // import "golang.org/x/tools/cmd/stringer"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"flag"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"go/ast"
 | 
				
			||||||
 | 
						"go/constant"
 | 
				
			||||||
 | 
						"go/format"
 | 
				
			||||||
 | 
						"go/token"
 | 
				
			||||||
 | 
						"go/types"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"sort"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/tools/go/packages"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						typeNames   = flag.String("type", "", "comma-separated list of type names; must be set")
 | 
				
			||||||
 | 
						output      = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
 | 
				
			||||||
 | 
						trimprefix  = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names")
 | 
				
			||||||
 | 
						linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present")
 | 
				
			||||||
 | 
						buildTags   = flag.String("tags", "", "comma-separated list of build tags to apply")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Usage is a replacement usage function for the flags package.
 | 
				
			||||||
 | 
					func Usage() {
 | 
				
			||||||
 | 
						fmt.Fprintf(os.Stderr, "Usage of stringer:\n")
 | 
				
			||||||
 | 
						fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n")
 | 
				
			||||||
 | 
						fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T files... # Must be a single package\n")
 | 
				
			||||||
 | 
						fmt.Fprintf(os.Stderr, "For more information, see:\n")
 | 
				
			||||||
 | 
						fmt.Fprintf(os.Stderr, "\thttps://pkg.go.dev/golang.org/x/tools/cmd/stringer\n")
 | 
				
			||||||
 | 
						fmt.Fprintf(os.Stderr, "Flags:\n")
 | 
				
			||||||
 | 
						flag.PrintDefaults()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						log.SetFlags(0)
 | 
				
			||||||
 | 
						log.SetPrefix("stringer: ")
 | 
				
			||||||
 | 
						flag.Usage = Usage
 | 
				
			||||||
 | 
						flag.Parse()
 | 
				
			||||||
 | 
						if len(*typeNames) == 0 {
 | 
				
			||||||
 | 
							flag.Usage()
 | 
				
			||||||
 | 
							os.Exit(2)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						types := strings.Split(*typeNames, ",")
 | 
				
			||||||
 | 
						var tags []string
 | 
				
			||||||
 | 
						if len(*buildTags) > 0 {
 | 
				
			||||||
 | 
							tags = strings.Split(*buildTags, ",")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We accept either one directory or a list of files. Which do we have?
 | 
				
			||||||
 | 
						args := flag.Args()
 | 
				
			||||||
 | 
						if len(args) == 0 {
 | 
				
			||||||
 | 
							// Default: process whole package in current directory.
 | 
				
			||||||
 | 
							args = []string{"."}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Parse the package once.
 | 
				
			||||||
 | 
						var dir string
 | 
				
			||||||
 | 
						g := Generator{
 | 
				
			||||||
 | 
							trimPrefix:  *trimprefix,
 | 
				
			||||||
 | 
							lineComment: *linecomment,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// TODO(suzmue): accept other patterns for packages (directories, list of files, import paths, etc).
 | 
				
			||||||
 | 
						if len(args) == 1 && isDirectory(args[0]) {
 | 
				
			||||||
 | 
							dir = args[0]
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if len(tags) != 0 {
 | 
				
			||||||
 | 
								log.Fatal("-tags option applies only to directories, not when files are specified")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							dir = filepath.Dir(args[0])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.parsePackage(args, tags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Print the header and package clause.
 | 
				
			||||||
 | 
						g.Printf("// Code generated by \"stringer %s\"; DO NOT EDIT.\n", strings.Join(os.Args[1:], " "))
 | 
				
			||||||
 | 
						g.Printf("\n")
 | 
				
			||||||
 | 
						g.Printf("package %s", g.pkg.name)
 | 
				
			||||||
 | 
						g.Printf("\n")
 | 
				
			||||||
 | 
						g.Printf("import \"strconv\"\n") // Used by all methods.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run generate for each type.
 | 
				
			||||||
 | 
						for _, typeName := range types {
 | 
				
			||||||
 | 
							g.generate(typeName)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Format the output.
 | 
				
			||||||
 | 
						src := g.format()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write to file.
 | 
				
			||||||
 | 
						outputName := *output
 | 
				
			||||||
 | 
						if outputName == "" {
 | 
				
			||||||
 | 
							baseName := fmt.Sprintf("%s_string.go", types[0])
 | 
				
			||||||
 | 
							outputName = filepath.Join(dir, strings.ToLower(baseName))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err := os.WriteFile(outputName, src, 0644)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("writing output: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// isDirectory reports whether the named file is a directory.
 | 
				
			||||||
 | 
					func isDirectory(name string) bool {
 | 
				
			||||||
 | 
						info, err := os.Stat(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return info.IsDir()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Generator holds the state of the analysis. Primarily used to buffer
 | 
				
			||||||
 | 
					// the output for format.Source.
 | 
				
			||||||
 | 
					type Generator struct {
 | 
				
			||||||
 | 
						buf bytes.Buffer // Accumulated output.
 | 
				
			||||||
 | 
						pkg *Package     // Package we are scanning.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						trimPrefix  string
 | 
				
			||||||
 | 
						lineComment bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) Printf(format string, args ...interface{}) {
 | 
				
			||||||
 | 
						fmt.Fprintf(&g.buf, format, args...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// File holds a single parsed file and associated data.
 | 
				
			||||||
 | 
					type File struct {
 | 
				
			||||||
 | 
						pkg  *Package  // Package to which this file belongs.
 | 
				
			||||||
 | 
						file *ast.File // Parsed AST.
 | 
				
			||||||
 | 
						// These fields are reset for each type being generated.
 | 
				
			||||||
 | 
						typeName string  // Name of the constant type.
 | 
				
			||||||
 | 
						values   []Value // Accumulator for constant values of that type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						trimPrefix  string
 | 
				
			||||||
 | 
						lineComment bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Package struct {
 | 
				
			||||||
 | 
						name  string
 | 
				
			||||||
 | 
						defs  map[*ast.Ident]types.Object
 | 
				
			||||||
 | 
						files []*File
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// parsePackage analyzes the single package constructed from the patterns and tags.
 | 
				
			||||||
 | 
					// parsePackage exits if there is an error.
 | 
				
			||||||
 | 
					func (g *Generator) parsePackage(patterns []string, tags []string) {
 | 
				
			||||||
 | 
						cfg := &packages.Config{
 | 
				
			||||||
 | 
							Mode: packages.NeedName | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax,
 | 
				
			||||||
 | 
							// TODO: Need to think about constants in test files. Maybe write type_string_test.go
 | 
				
			||||||
 | 
							// in a separate pass? For later.
 | 
				
			||||||
 | 
							Tests:      false,
 | 
				
			||||||
 | 
							BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join(tags, " "))},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pkgs, err := packages.Load(cfg, patterns...)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(pkgs) != 1 {
 | 
				
			||||||
 | 
							log.Fatalf("error: %d packages found", len(pkgs))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.addPackage(pkgs[0])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// addPackage adds a type checked Package and its syntax files to the generator.
 | 
				
			||||||
 | 
					func (g *Generator) addPackage(pkg *packages.Package) {
 | 
				
			||||||
 | 
						g.pkg = &Package{
 | 
				
			||||||
 | 
							name:  pkg.Name,
 | 
				
			||||||
 | 
							defs:  pkg.TypesInfo.Defs,
 | 
				
			||||||
 | 
							files: make([]*File, len(pkg.Syntax)),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, file := range pkg.Syntax {
 | 
				
			||||||
 | 
							g.pkg.files[i] = &File{
 | 
				
			||||||
 | 
								file:        file,
 | 
				
			||||||
 | 
								pkg:         g.pkg,
 | 
				
			||||||
 | 
								trimPrefix:  g.trimPrefix,
 | 
				
			||||||
 | 
								lineComment: g.lineComment,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generate produces the String method for the named type.
 | 
				
			||||||
 | 
					func (g *Generator) generate(typeName string) {
 | 
				
			||||||
 | 
						values := make([]Value, 0, 100)
 | 
				
			||||||
 | 
						for _, file := range g.pkg.files {
 | 
				
			||||||
 | 
							// Set the state for this run of the walker.
 | 
				
			||||||
 | 
							file.typeName = typeName
 | 
				
			||||||
 | 
							file.values = nil
 | 
				
			||||||
 | 
							if file.file != nil {
 | 
				
			||||||
 | 
								ast.Inspect(file.file, file.genDecl)
 | 
				
			||||||
 | 
								values = append(values, file.values...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(values) == 0 {
 | 
				
			||||||
 | 
							log.Fatalf("no values defined for type %s", typeName)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Generate code that will fail if the constants change value.
 | 
				
			||||||
 | 
						g.Printf("func _() {\n")
 | 
				
			||||||
 | 
						g.Printf("\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n")
 | 
				
			||||||
 | 
						g.Printf("\t// Re-run the stringer command to generate them again.\n")
 | 
				
			||||||
 | 
						g.Printf("\tvar x [1]struct{}\n")
 | 
				
			||||||
 | 
						for _, v := range values {
 | 
				
			||||||
 | 
							g.Printf("\t_ = x[%s - %s]\n", v.originalName, v.str)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Printf("}\n")
 | 
				
			||||||
 | 
						runs := splitIntoRuns(values)
 | 
				
			||||||
 | 
						// The decision of which pattern to use depends on the number of
 | 
				
			||||||
 | 
						// runs in the numbers. If there's only one, it's easy. For more than
 | 
				
			||||||
 | 
						// one, there's a tradeoff between complexity and size of the data
 | 
				
			||||||
 | 
						// and code vs. the simplicity of a map. A map takes more space,
 | 
				
			||||||
 | 
						// but so does the code. The decision here (crossover at 10) is
 | 
				
			||||||
 | 
						// arbitrary, but considers that for large numbers of runs the cost
 | 
				
			||||||
 | 
						// of the linear scan in the switch might become important, and
 | 
				
			||||||
 | 
						// rather than use yet another algorithm such as binary search,
 | 
				
			||||||
 | 
						// we punt and use a map. In any case, the likelihood of a map
 | 
				
			||||||
 | 
						// being necessary for any realistic example other than bitmasks
 | 
				
			||||||
 | 
						// is very low. And bitmasks probably deserve their own analysis,
 | 
				
			||||||
 | 
						// to be done some other day.
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case len(runs) == 1:
 | 
				
			||||||
 | 
							g.buildOneRun(runs, typeName)
 | 
				
			||||||
 | 
						case len(runs) <= 10:
 | 
				
			||||||
 | 
							g.buildMultipleRuns(runs, typeName)
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							g.buildMap(runs, typeName)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// splitIntoRuns breaks the values into runs of contiguous sequences.
 | 
				
			||||||
 | 
					// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}.
 | 
				
			||||||
 | 
					// The input slice is known to be non-empty.
 | 
				
			||||||
 | 
					func splitIntoRuns(values []Value) [][]Value {
 | 
				
			||||||
 | 
						// We use stable sort so the lexically first name is chosen for equal elements.
 | 
				
			||||||
 | 
						sort.Stable(byValue(values))
 | 
				
			||||||
 | 
						// Remove duplicates. Stable sort has put the one we want to print first,
 | 
				
			||||||
 | 
						// so use that one. The String method won't care about which named constant
 | 
				
			||||||
 | 
						// was the argument, so the first name for the given value is the only one to keep.
 | 
				
			||||||
 | 
						// We need to do this because identical values would cause the switch or map
 | 
				
			||||||
 | 
						// to fail to compile.
 | 
				
			||||||
 | 
						j := 1
 | 
				
			||||||
 | 
						for i := 1; i < len(values); i++ {
 | 
				
			||||||
 | 
							if values[i].value != values[i-1].value {
 | 
				
			||||||
 | 
								values[j] = values[i]
 | 
				
			||||||
 | 
								j++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						values = values[:j]
 | 
				
			||||||
 | 
						runs := make([][]Value, 0, 10)
 | 
				
			||||||
 | 
						for len(values) > 0 {
 | 
				
			||||||
 | 
							// One contiguous sequence per outer loop.
 | 
				
			||||||
 | 
							i := 1
 | 
				
			||||||
 | 
							for i < len(values) && values[i].value == values[i-1].value+1 {
 | 
				
			||||||
 | 
								i++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							runs = append(runs, values[:i])
 | 
				
			||||||
 | 
							values = values[i:]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return runs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// format returns the gofmt-ed contents of the Generator's buffer.
 | 
				
			||||||
 | 
					func (g *Generator) format() []byte {
 | 
				
			||||||
 | 
						src, err := format.Source(g.buf.Bytes())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							// Should never happen, but can arise when developing this code.
 | 
				
			||||||
 | 
							// The user can compile the output to see the error.
 | 
				
			||||||
 | 
							log.Printf("warning: internal error: invalid Go generated: %s", err)
 | 
				
			||||||
 | 
							log.Printf("warning: compile the package to analyze the error")
 | 
				
			||||||
 | 
							return g.buf.Bytes()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return src
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Value represents a declared constant.
 | 
				
			||||||
 | 
					type Value struct {
 | 
				
			||||||
 | 
						originalName string // The name of the constant.
 | 
				
			||||||
 | 
						name         string // The name with trimmed prefix.
 | 
				
			||||||
 | 
						// The value is stored as a bit pattern alone. The boolean tells us
 | 
				
			||||||
 | 
						// whether to interpret it as an int64 or a uint64; the only place
 | 
				
			||||||
 | 
						// this matters is when sorting.
 | 
				
			||||||
 | 
						// Much of the time the str field is all we need; it is printed
 | 
				
			||||||
 | 
						// by Value.String.
 | 
				
			||||||
 | 
						value  uint64 // Will be converted to int64 when needed.
 | 
				
			||||||
 | 
						signed bool   // Whether the constant is a signed type.
 | 
				
			||||||
 | 
						str    string // The string representation given by the "go/constant" package.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (v *Value) String() string {
 | 
				
			||||||
 | 
						return v.str
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// byValue lets us sort the constants into increasing order.
 | 
				
			||||||
 | 
					// We take care in the Less method to sort in signed or unsigned order,
 | 
				
			||||||
 | 
					// as appropriate.
 | 
				
			||||||
 | 
					type byValue []Value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b byValue) Len() int      { return len(b) }
 | 
				
			||||||
 | 
					func (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
 | 
				
			||||||
 | 
					func (b byValue) Less(i, j int) bool {
 | 
				
			||||||
 | 
						if b[i].signed {
 | 
				
			||||||
 | 
							return int64(b[i].value) < int64(b[j].value)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return b[i].value < b[j].value
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// genDecl processes one declaration clause.
 | 
				
			||||||
 | 
					func (f *File) genDecl(node ast.Node) bool {
 | 
				
			||||||
 | 
						decl, ok := node.(*ast.GenDecl)
 | 
				
			||||||
 | 
						if !ok || decl.Tok != token.CONST {
 | 
				
			||||||
 | 
							// We only care about const declarations.
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// The name of the type of the constants we are declaring.
 | 
				
			||||||
 | 
						// Can change if this is a multi-element declaration.
 | 
				
			||||||
 | 
						typ := ""
 | 
				
			||||||
 | 
						// Loop over the elements of the declaration. Each element is a ValueSpec:
 | 
				
			||||||
 | 
						// a list of names possibly followed by a type, possibly followed by values.
 | 
				
			||||||
 | 
						// If the type and value are both missing, we carry down the type (and value,
 | 
				
			||||||
 | 
						// but the "go/types" package takes care of that).
 | 
				
			||||||
 | 
						for _, spec := range decl.Specs {
 | 
				
			||||||
 | 
							vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST.
 | 
				
			||||||
 | 
							if vspec.Type == nil && len(vspec.Values) > 0 {
 | 
				
			||||||
 | 
								// "X = 1". With no type but a value. If the constant is untyped,
 | 
				
			||||||
 | 
								// skip this vspec and reset the remembered type.
 | 
				
			||||||
 | 
								typ = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// If this is a simple type conversion, remember the type.
 | 
				
			||||||
 | 
								// We don't mind if this is actually a call; a qualified call won't
 | 
				
			||||||
 | 
								// be matched (that will be SelectorExpr, not Ident), and only unusual
 | 
				
			||||||
 | 
								// situations will result in a function call that appears to be
 | 
				
			||||||
 | 
								// a type conversion.
 | 
				
			||||||
 | 
								ce, ok := vspec.Values[0].(*ast.CallExpr)
 | 
				
			||||||
 | 
								if !ok {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								id, ok := ce.Fun.(*ast.Ident)
 | 
				
			||||||
 | 
								if !ok {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								typ = id.Name
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if vspec.Type != nil {
 | 
				
			||||||
 | 
								// "X T". We have a type. Remember it.
 | 
				
			||||||
 | 
								ident, ok := vspec.Type.(*ast.Ident)
 | 
				
			||||||
 | 
								if !ok {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								typ = ident.Name
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if typ != f.typeName {
 | 
				
			||||||
 | 
								// This is not the type we're looking for.
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// We now have a list of names (from one line of source code) all being
 | 
				
			||||||
 | 
							// declared with the desired type.
 | 
				
			||||||
 | 
							// Grab their names and actual values and store them in f.values.
 | 
				
			||||||
 | 
							for _, name := range vspec.Names {
 | 
				
			||||||
 | 
								if name.Name == "_" {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// This dance lets the type checker find the values for us. It's a
 | 
				
			||||||
 | 
								// bit tricky: look up the object declared by the name, find its
 | 
				
			||||||
 | 
								// types.Const, and extract its value.
 | 
				
			||||||
 | 
								obj, ok := f.pkg.defs[name]
 | 
				
			||||||
 | 
								if !ok {
 | 
				
			||||||
 | 
									log.Fatalf("no value for constant %s", name)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								info := obj.Type().Underlying().(*types.Basic).Info()
 | 
				
			||||||
 | 
								if info&types.IsInteger == 0 {
 | 
				
			||||||
 | 
									log.Fatalf("can't handle non-integer constant type %s", typ)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.
 | 
				
			||||||
 | 
								if value.Kind() != constant.Int {
 | 
				
			||||||
 | 
									log.Fatalf("can't happen: constant is not an integer %s", name)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								i64, isInt := constant.Int64Val(value)
 | 
				
			||||||
 | 
								u64, isUint := constant.Uint64Val(value)
 | 
				
			||||||
 | 
								if !isInt && !isUint {
 | 
				
			||||||
 | 
									log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !isInt {
 | 
				
			||||||
 | 
									u64 = uint64(i64)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								v := Value{
 | 
				
			||||||
 | 
									originalName: name.Name,
 | 
				
			||||||
 | 
									value:        u64,
 | 
				
			||||||
 | 
									signed:       info&types.IsUnsigned == 0,
 | 
				
			||||||
 | 
									str:          value.String(),
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if c := vspec.Comment; f.lineComment && c != nil && len(c.List) == 1 {
 | 
				
			||||||
 | 
									v.name = strings.TrimSpace(c.Text())
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									v.name = strings.TrimPrefix(v.originalName, f.trimPrefix)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								f.values = append(f.values, v)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Helpers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// usize returns the number of bits of the smallest unsigned integer
 | 
				
			||||||
 | 
					// type that will hold n. Used to create the smallest possible slice of
 | 
				
			||||||
 | 
					// integers to use as indexes into the concatenated strings.
 | 
				
			||||||
 | 
					func usize(n int) int {
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case n < 1<<8:
 | 
				
			||||||
 | 
							return 8
 | 
				
			||||||
 | 
						case n < 1<<16:
 | 
				
			||||||
 | 
							return 16
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							// 2^32 is enough constants for anyone.
 | 
				
			||||||
 | 
							return 32
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// declareIndexAndNameVars declares the index slices and concatenated names
 | 
				
			||||||
 | 
					// strings representing the runs of values.
 | 
				
			||||||
 | 
					func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
 | 
				
			||||||
 | 
						var indexes, names []string
 | 
				
			||||||
 | 
						for i, run := range runs {
 | 
				
			||||||
 | 
							index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
 | 
				
			||||||
 | 
							if len(run) != 1 {
 | 
				
			||||||
 | 
								indexes = append(indexes, index)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							names = append(names, name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Printf("const (\n")
 | 
				
			||||||
 | 
						for _, name := range names {
 | 
				
			||||||
 | 
							g.Printf("\t%s\n", name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Printf(")\n\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(indexes) > 0 {
 | 
				
			||||||
 | 
							g.Printf("var (")
 | 
				
			||||||
 | 
							for _, index := range indexes {
 | 
				
			||||||
 | 
								g.Printf("\t%s\n", index)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.Printf(")\n\n")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars
 | 
				
			||||||
 | 
					func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) {
 | 
				
			||||||
 | 
						index, name := g.createIndexAndNameDecl(run, typeName, "")
 | 
				
			||||||
 | 
						g.Printf("const %s\n", name)
 | 
				
			||||||
 | 
						g.Printf("var %s\n", index)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var".
 | 
				
			||||||
 | 
					func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) {
 | 
				
			||||||
 | 
						b := new(bytes.Buffer)
 | 
				
			||||||
 | 
						indexes := make([]int, len(run))
 | 
				
			||||||
 | 
						for i := range run {
 | 
				
			||||||
 | 
							b.WriteString(run[i].name)
 | 
				
			||||||
 | 
							indexes[i] = b.Len()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						nameConst := fmt.Sprintf("_%s_name%s = %q", typeName, suffix, b.String())
 | 
				
			||||||
 | 
						nameLen := b.Len()
 | 
				
			||||||
 | 
						b.Reset()
 | 
				
			||||||
 | 
						fmt.Fprintf(b, "_%s_index%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen))
 | 
				
			||||||
 | 
						for i, v := range indexes {
 | 
				
			||||||
 | 
							if i > 0 {
 | 
				
			||||||
 | 
								fmt.Fprintf(b, ", ")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fmt.Fprintf(b, "%d", v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Fprintf(b, "}")
 | 
				
			||||||
 | 
						return b.String(), nameConst
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// declareNameVars declares the concatenated names string representing all the values in the runs.
 | 
				
			||||||
 | 
					func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) {
 | 
				
			||||||
 | 
						g.Printf("const _%s_name%s = \"", typeName, suffix)
 | 
				
			||||||
 | 
						for _, run := range runs {
 | 
				
			||||||
 | 
							for i := range run {
 | 
				
			||||||
 | 
								g.Printf("%s", run[i].name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Printf("\"\n")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// buildOneRun generates the variables and String method for a single run of contiguous values.
 | 
				
			||||||
 | 
					func (g *Generator) buildOneRun(runs [][]Value, typeName string) {
 | 
				
			||||||
 | 
						values := runs[0]
 | 
				
			||||||
 | 
						g.Printf("\n")
 | 
				
			||||||
 | 
						g.declareIndexAndNameVar(values, typeName)
 | 
				
			||||||
 | 
						// The generated code is simple enough to write as a Printf format.
 | 
				
			||||||
 | 
						lessThanZero := ""
 | 
				
			||||||
 | 
						if values[0].signed {
 | 
				
			||||||
 | 
							lessThanZero = "i < 0 || "
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if values[0].value == 0 { // Signed or unsigned, 0 is still 0.
 | 
				
			||||||
 | 
							g.Printf(stringOneRun, typeName, usize(len(values)), lessThanZero)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							g.Printf(stringOneRunWithOffset, typeName, values[0].String(), usize(len(values)), lessThanZero)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Arguments to format are:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//	[1]: type name
 | 
				
			||||||
 | 
					//	[2]: size of index element (8 for uint8 etc.)
 | 
				
			||||||
 | 
					//	[3]: less than zero check (for signed types)
 | 
				
			||||||
 | 
					const stringOneRun = `func (i %[1]s) String() string {
 | 
				
			||||||
 | 
						if %[3]si >= %[1]s(len(_%[1]s_index)-1) {
 | 
				
			||||||
 | 
							return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return _%[1]s_name[_%[1]s_index[i]:_%[1]s_index[i+1]]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Arguments to format are:
 | 
				
			||||||
 | 
					//	[1]: type name
 | 
				
			||||||
 | 
					//	[2]: lowest defined value for type, as a string
 | 
				
			||||||
 | 
					//	[3]: size of index element (8 for uint8 etc.)
 | 
				
			||||||
 | 
					//	[4]: less than zero check (for signed types)
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const stringOneRunWithOffset = `func (i %[1]s) String() string {
 | 
				
			||||||
 | 
						i -= %[2]s
 | 
				
			||||||
 | 
						if %[4]si >= %[1]s(len(_%[1]s_index)-1) {
 | 
				
			||||||
 | 
							return "%[1]s(" + strconv.FormatInt(int64(i + %[2]s), 10) + ")"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return _%[1]s_name[_%[1]s_index[i] : _%[1]s_index[i+1]]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values.
 | 
				
			||||||
 | 
					// For this pattern, a single Printf format won't do.
 | 
				
			||||||
 | 
					func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) {
 | 
				
			||||||
 | 
						g.Printf("\n")
 | 
				
			||||||
 | 
						g.declareIndexAndNameVars(runs, typeName)
 | 
				
			||||||
 | 
						g.Printf("func (i %s) String() string {\n", typeName)
 | 
				
			||||||
 | 
						g.Printf("\tswitch {\n")
 | 
				
			||||||
 | 
						for i, values := range runs {
 | 
				
			||||||
 | 
							if len(values) == 1 {
 | 
				
			||||||
 | 
								g.Printf("\tcase i == %s:\n", &values[0])
 | 
				
			||||||
 | 
								g.Printf("\t\treturn _%s_name_%d\n", typeName, i)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if values[0].value == 0 && !values[0].signed {
 | 
				
			||||||
 | 
								// For an unsigned lower bound of 0, "0 <= i" would be redundant.
 | 
				
			||||||
 | 
								g.Printf("\tcase i <= %s:\n", &values[len(values)-1])
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								g.Printf("\tcase %s <= i && i <= %s:\n", &values[0], &values[len(values)-1])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if values[0].value != 0 {
 | 
				
			||||||
 | 
								g.Printf("\t\ti -= %s\n", &values[0])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.Printf("\t\treturn _%s_name_%d[_%s_index_%d[i]:_%s_index_%d[i+1]]\n",
 | 
				
			||||||
 | 
								typeName, i, typeName, i, typeName, i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Printf("\tdefault:\n")
 | 
				
			||||||
 | 
						g.Printf("\t\treturn \"%s(\" + strconv.FormatInt(int64(i), 10) + \")\"\n", typeName)
 | 
				
			||||||
 | 
						g.Printf("\t}\n")
 | 
				
			||||||
 | 
						g.Printf("}\n")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// buildMap handles the case where the space is so sparse a map is a reasonable fallback.
 | 
				
			||||||
 | 
					// It's a rare situation but has simple code.
 | 
				
			||||||
 | 
					func (g *Generator) buildMap(runs [][]Value, typeName string) {
 | 
				
			||||||
 | 
						g.Printf("\n")
 | 
				
			||||||
 | 
						g.declareNameVars(runs, typeName, "")
 | 
				
			||||||
 | 
						g.Printf("\nvar _%s_map = map[%s]string{\n", typeName, typeName)
 | 
				
			||||||
 | 
						n := 0
 | 
				
			||||||
 | 
						for _, values := range runs {
 | 
				
			||||||
 | 
							for _, value := range values {
 | 
				
			||||||
 | 
								g.Printf("\t%s: _%s_name[%d:%d],\n", &value, typeName, n, n+len(value.name))
 | 
				
			||||||
 | 
								n += len(value.name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Printf("}\n\n")
 | 
				
			||||||
 | 
						g.Printf(stringMap, typeName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Argument to format is the type name.
 | 
				
			||||||
 | 
					const stringMap = `func (i %[1]s) String() string {
 | 
				
			||||||
 | 
						if str, ok := _%[1]s_map[i]; ok {
 | 
				
			||||||
 | 
							return str
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
							
								
								
									
										6
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -58,9 +58,10 @@ github.com/JeffAshton/win_pdh
 | 
				
			|||||||
# github.com/MakeNowJust/heredoc v1.0.0
 | 
					# github.com/MakeNowJust/heredoc v1.0.0
 | 
				
			||||||
## explicit; go 1.12
 | 
					## explicit; go 1.12
 | 
				
			||||||
github.com/MakeNowJust/heredoc
 | 
					github.com/MakeNowJust/heredoc
 | 
				
			||||||
# github.com/Microsoft/go-winio v0.4.17
 | 
					# github.com/Microsoft/go-winio v0.6.0
 | 
				
			||||||
## explicit; go 1.12
 | 
					## explicit; go 1.17
 | 
				
			||||||
github.com/Microsoft/go-winio
 | 
					github.com/Microsoft/go-winio
 | 
				
			||||||
 | 
					github.com/Microsoft/go-winio/internal/socket
 | 
				
			||||||
github.com/Microsoft/go-winio/pkg/guid
 | 
					github.com/Microsoft/go-winio/pkg/guid
 | 
				
			||||||
github.com/Microsoft/go-winio/pkg/security
 | 
					github.com/Microsoft/go-winio/pkg/security
 | 
				
			||||||
github.com/Microsoft/go-winio/vhd
 | 
					github.com/Microsoft/go-winio/vhd
 | 
				
			||||||
@@ -1028,6 +1029,7 @@ golang.org/x/time/rate
 | 
				
			|||||||
# golang.org/x/tools v0.8.0
 | 
					# golang.org/x/tools v0.8.0
 | 
				
			||||||
## explicit; go 1.18
 | 
					## explicit; go 1.18
 | 
				
			||||||
golang.org/x/tools/benchmark/parse
 | 
					golang.org/x/tools/benchmark/parse
 | 
				
			||||||
 | 
					golang.org/x/tools/cmd/stringer
 | 
				
			||||||
golang.org/x/tools/container/intsets
 | 
					golang.org/x/tools/container/intsets
 | 
				
			||||||
golang.org/x/tools/go/ast/astutil
 | 
					golang.org/x/tools/go/ast/astutil
 | 
				
			||||||
golang.org/x/tools/go/ast/inspector
 | 
					golang.org/x/tools/go/ast/inspector
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user