add deps
This commit is contained in:
parent
8a699044be
commit
4267ac8731
|
@ -0,0 +1,17 @@
|
||||||
|
xversion.go
|
||||||
|
zversion.go
|
||||||
|
|
||||||
|
# ---> Go
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
|
@ -0,0 +1,312 @@
|
||||||
|
Mozilla Public License Version 2.0
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
|
||||||
|
1.1. "Contributor" means each individual or legal entity that creates, contributes
|
||||||
|
to the creation of, or owns Covered Software.
|
||||||
|
|
||||||
|
1.2. "Contributor Version" means the combination of the Contributions of others
|
||||||
|
(if any) used by a Contributor and that particular Contributor's Contribution.
|
||||||
|
|
||||||
|
1.3. "Contribution" means Covered Software of a particular Contributor.
|
||||||
|
|
||||||
|
1.4. "Covered Software" means Source Code Form to which the initial Contributor
|
||||||
|
has attached the notice in Exhibit A, the Executable Form of such Source Code
|
||||||
|
Form, and Modifications of such Source Code Form, in each case including portions
|
||||||
|
thereof.
|
||||||
|
|
||||||
|
1.5. "Incompatible With Secondary Licenses" means
|
||||||
|
|
||||||
|
(a) that the initial Contributor has attached the notice described in Exhibit
|
||||||
|
B to the Covered Software; or
|
||||||
|
|
||||||
|
(b) that the Covered Software was made available under the terms of version
|
||||||
|
1.1 or earlier of the License, but not also under the terms of a Secondary
|
||||||
|
License.
|
||||||
|
|
||||||
|
1.6. "Executable Form" means any form of the work other than Source Code Form.
|
||||||
|
|
||||||
|
1.7. "Larger Work" means a work that combines Covered Software with other
|
||||||
|
material, in a separate file or files, that is not Covered Software.
|
||||||
|
|
||||||
|
1.8. "License" means this document.
|
||||||
|
|
||||||
|
1.9. "Licensable" means having the right to grant, to the maximum extent possible,
|
||||||
|
whether at the time of the initial grant or subsequently, any and all of the
|
||||||
|
rights conveyed by this License.
|
||||||
|
|
||||||
|
1.10. "Modifications" means any of the following:
|
||||||
|
|
||||||
|
(a) any file in Source Code Form that results from an addition to, deletion
|
||||||
|
from, or modification of the contents of Covered Software; or
|
||||||
|
|
||||||
|
(b) any new file in Source Code Form that contains any Covered Software.
|
||||||
|
|
||||||
|
1.11. "Patent Claims" of a Contributor means any patent claim(s), including
|
||||||
|
without limitation, method, process, and apparatus claims, in any patent Licensable
|
||||||
|
by such Contributor that would be infringed, but for the grant of the License,
|
||||||
|
by the making, using, selling, offering for sale, having made, import, or
|
||||||
|
transfer of either its Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
1.12. "Secondary License" means either the GNU General Public License, Version
|
||||||
|
2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General
|
||||||
|
Public License, Version 3.0, or any later versions of those licenses.
|
||||||
|
|
||||||
|
1.13. "Source Code Form" means the form of the work preferred for making modifications.
|
||||||
|
|
||||||
|
1.14. "You" (or "Your") means an individual or a legal entity exercising rights
|
||||||
|
under this License. For legal entities, "You" includes any entity that controls,
|
||||||
|
is controlled by, or is under common control with You. For purposes of this
|
||||||
|
definition, "control" means (a) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or otherwise,
|
||||||
|
or (b) ownership of more than fifty percent (50%) of the outstanding shares
|
||||||
|
or beneficial ownership of such entity.
|
||||||
|
|
||||||
|
2. License Grants and Conditions
|
||||||
|
|
||||||
|
2.1. Grants
|
||||||
|
|
||||||
|
Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive
|
||||||
|
license:
|
||||||
|
|
||||||
|
(a) under intellectual property rights (other than patent or trademark) Licensable
|
||||||
|
by such Contributor to use, reproduce, make available, modify, display, perform,
|
||||||
|
distribute, and otherwise exploit its Contributions, either on an unmodified
|
||||||
|
basis, with Modifications, or as part of a Larger Work; and
|
||||||
|
|
||||||
|
(b) under Patent Claims of such Contributor to make, use, sell, offer for
|
||||||
|
sale, have made, import, and otherwise transfer either its Contributions or
|
||||||
|
its Contributor Version.
|
||||||
|
|
||||||
|
2.2. Effective Date
|
||||||
|
|
||||||
|
The licenses granted in Section 2.1 with respect to any Contribution become
|
||||||
|
effective for each Contribution on the date the Contributor first distributes
|
||||||
|
such Contribution.
|
||||||
|
|
||||||
|
2.3. Limitations on Grant Scope
|
||||||
|
|
||||||
|
The licenses granted in this Section 2 are the only rights granted under this
|
||||||
|
License. No additional rights or licenses will be implied from the distribution
|
||||||
|
or licensing of Covered Software under this License. Notwithstanding Section
|
||||||
|
2.1(b) above, no patent license is granted by a Contributor:
|
||||||
|
|
||||||
|
(a) for any code that a Contributor has removed from Covered Software; or
|
||||||
|
|
||||||
|
(b) for infringements caused by: (i) Your and any other third party's modifications
|
||||||
|
of Covered Software, or (ii) the combination of its Contributions with other
|
||||||
|
software (except as part of its Contributor Version); or
|
||||||
|
|
||||||
|
(c) under Patent Claims infringed by Covered Software in the absence of its
|
||||||
|
Contributions.
|
||||||
|
|
||||||
|
This License does not grant any rights in the trademarks, service marks, or
|
||||||
|
logos of any Contributor (except as may be necessary to comply with the notice
|
||||||
|
requirements in Section 3.4).
|
||||||
|
|
||||||
|
2.4. Subsequent Licenses
|
||||||
|
|
||||||
|
No Contributor makes additional grants as a result of Your choice to distribute
|
||||||
|
the Covered Software under a subsequent version of this License (see Section
|
||||||
|
10.2) or under the terms of a Secondary License (if permitted under the terms
|
||||||
|
of Section 3.3).
|
||||||
|
|
||||||
|
2.5. Representation
|
||||||
|
|
||||||
|
Each Contributor represents that the Contributor believes its Contributions
|
||||||
|
are its original creation(s) or it has sufficient rights to grant the rights
|
||||||
|
to its Contributions conveyed by this License.
|
||||||
|
|
||||||
|
2.6. Fair Use
|
||||||
|
|
||||||
|
This License is not intended to limit any rights You have under applicable
|
||||||
|
copyright doctrines of fair use, fair dealing, or other equivalents.
|
||||||
|
|
||||||
|
2.7. Conditions
|
||||||
|
|
||||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||||
|
Section 2.1.
|
||||||
|
|
||||||
|
3. Responsibilities
|
||||||
|
|
||||||
|
3.1. Distribution of Source Form
|
||||||
|
|
||||||
|
All distribution of Covered Software in Source Code Form, including any Modifications
|
||||||
|
that You create or to which You contribute, must be under the terms of this
|
||||||
|
License. You must inform recipients that the Source Code Form of the Covered
|
||||||
|
Software is governed by the terms of this License, and how they can obtain
|
||||||
|
a copy of this License. You may not attempt to alter or restrict the recipients'
|
||||||
|
rights in the Source Code Form.
|
||||||
|
|
||||||
|
3.2. Distribution of Executable Form
|
||||||
|
|
||||||
|
If You distribute Covered Software in Executable Form then:
|
||||||
|
|
||||||
|
(a) such Covered Software must also be made available in Source Code Form,
|
||||||
|
as described in Section 3.1, and You must inform recipients of the Executable
|
||||||
|
Form how they can obtain a copy of such Source Code Form by reasonable means
|
||||||
|
in a timely manner, at a charge no more than the cost of distribution to the
|
||||||
|
recipient; and
|
||||||
|
|
||||||
|
(b) You may distribute such Executable Form under the terms of this License,
|
||||||
|
or sublicense it under different terms, provided that the license for the
|
||||||
|
Executable Form does not attempt to limit or alter the recipients' rights
|
||||||
|
in the Source Code Form under this License.
|
||||||
|
|
||||||
|
3.3. Distribution of a Larger Work
|
||||||
|
|
||||||
|
You may create and distribute a Larger Work under terms of Your choice, provided
|
||||||
|
that You also comply with the requirements of this License for the Covered
|
||||||
|
Software. If the Larger Work is a combination of Covered Software with a work
|
||||||
|
governed by one or more Secondary Licenses, and the Covered Software is not
|
||||||
|
Incompatible With Secondary Licenses, this License permits You to additionally
|
||||||
|
distribute such Covered Software under the terms of such Secondary License(s),
|
||||||
|
so that the recipient of the Larger Work may, at their option, further distribute
|
||||||
|
the Covered Software under the terms of either this License or such Secondary
|
||||||
|
License(s).
|
||||||
|
|
||||||
|
3.4. Notices
|
||||||
|
|
||||||
|
You may not remove or alter the substance of any license notices (including
|
||||||
|
copyright notices, patent notices, disclaimers of warranty, or limitations
|
||||||
|
of liability) contained within the Source Code Form of the Covered Software,
|
||||||
|
except that You may alter any license notices to the extent required to remedy
|
||||||
|
known factual inaccuracies.
|
||||||
|
|
||||||
|
3.5. Application of Additional Terms
|
||||||
|
|
||||||
|
You may choose to offer, and to charge a fee for, warranty, support, indemnity
|
||||||
|
or liability obligations to one or more recipients of Covered Software. However,
|
||||||
|
You may do so only on Your own behalf, and not on behalf of any Contributor.
|
||||||
|
You must make it absolutely clear that any such warranty, support, indemnity,
|
||||||
|
or liability obligation is offered by You alone, and You hereby agree to indemnify
|
||||||
|
every Contributor for any liability incurred by such Contributor as a result
|
||||||
|
of warranty, support, indemnity or liability terms You offer. You may include
|
||||||
|
additional disclaimers of warranty and limitations of liability specific to
|
||||||
|
any jurisdiction.
|
||||||
|
|
||||||
|
4. Inability to Comply Due to Statute or Regulation
|
||||||
|
|
||||||
|
If it is impossible for You to comply with any of the terms of this License
|
||||||
|
with respect to some or all of the Covered Software due to statute, judicial
|
||||||
|
order, or regulation then You must: (a) comply with the terms of this License
|
||||||
|
to the maximum extent possible; and (b) describe the limitations and the code
|
||||||
|
they affect. Such description must be placed in a text file included with
|
||||||
|
all distributions of the Covered Software under this License. Except to the
|
||||||
|
extent prohibited by statute or regulation, such description must be sufficiently
|
||||||
|
detailed for a recipient of ordinary skill to be able to understand it.
|
||||||
|
|
||||||
|
5. Termination
|
||||||
|
|
||||||
|
5.1. The rights granted under this License will terminate automatically if
|
||||||
|
You fail to comply with any of its terms. However, if You become compliant,
|
||||||
|
then the rights granted under this License from a particular Contributor are
|
||||||
|
reinstated (a) provisionally, unless and until such Contributor explicitly
|
||||||
|
and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor
|
||||||
|
fails to notify You of the non-compliance by some reasonable means prior to
|
||||||
|
60 days after You have come back into compliance. Moreover, Your grants from
|
||||||
|
a particular Contributor are reinstated on an ongoing basis if such Contributor
|
||||||
|
notifies You of the non-compliance by some reasonable means, this is the first
|
||||||
|
time You have received notice of non-compliance with this License from such
|
||||||
|
Contributor, and You become compliant prior to 30 days after Your receipt
|
||||||
|
of the notice.
|
||||||
|
|
||||||
|
5.2. If You initiate litigation against any entity by asserting a patent infringement
|
||||||
|
claim (excluding declaratory judgment actions, counter-claims, and cross-claims)
|
||||||
|
alleging that a Contributor Version directly or indirectly infringes any patent,
|
||||||
|
then the rights granted to You by any and all Contributors for the Covered
|
||||||
|
Software under Section 2.1 of this License shall terminate.
|
||||||
|
|
||||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end
|
||||||
|
user license agreements (excluding distributors and resellers) which have
|
||||||
|
been validly granted by You or Your distributors under this License prior
|
||||||
|
to termination shall survive termination.
|
||||||
|
|
||||||
|
6. Disclaimer of Warranty
|
||||||
|
|
||||||
|
Covered Software is provided under this License on an "as is" basis, without
|
||||||
|
warranty of any kind, either expressed, implied, or statutory, including,
|
||||||
|
without limitation, warranties that the Covered Software is free of defects,
|
||||||
|
merchantable, fit for a particular purpose or non-infringing. The entire risk
|
||||||
|
as to the quality and performance of the Covered Software is with You. Should
|
||||||
|
any Covered Software prove defective in any respect, You (not any Contributor)
|
||||||
|
assume the cost of any necessary servicing, repair, or correction. This disclaimer
|
||||||
|
of warranty constitutes an essential part of this License. No use of any Covered
|
||||||
|
Software is authorized under this License except under this disclaimer.
|
||||||
|
|
||||||
|
7. Limitation of Liability
|
||||||
|
|
||||||
|
Under no circumstances and under no legal theory, whether tort (including
|
||||||
|
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||||
|
distributes Covered Software as permitted above, be liable to You for any
|
||||||
|
direct, indirect, special, incidental, or consequential damages of any character
|
||||||
|
including, without limitation, damages for lost profits, loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all other commercial
|
||||||
|
damages or losses, even if such party shall have been informed of the possibility
|
||||||
|
of such damages. This limitation of liability shall not apply to liability
|
||||||
|
for death or personal injury resulting from such party's negligence to the
|
||||||
|
extent applicable law prohibits such limitation. Some jurisdictions do not
|
||||||
|
allow the exclusion or limitation of incidental or consequential damages,
|
||||||
|
so this exclusion and limitation may not apply to You.
|
||||||
|
|
||||||
|
8. Litigation
|
||||||
|
|
||||||
|
Any litigation relating to this License may be brought only in the courts
|
||||||
|
of a jurisdiction where the defendant maintains its principal place of business
|
||||||
|
and such litigation shall be governed by laws of that jurisdiction, without
|
||||||
|
reference to its conflict-of-law provisions. Nothing in this Section shall
|
||||||
|
prevent a party's ability to bring cross-claims or counter-claims.
|
||||||
|
|
||||||
|
9. Miscellaneous
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning the subject matter
|
||||||
|
hereof. If any provision of this License is held to be unenforceable, such
|
||||||
|
provision shall be reformed only to the extent necessary to make it enforceable.
|
||||||
|
Any law or regulation which provides that the language of a contract shall
|
||||||
|
be construed against the drafter shall not be used to construe this License
|
||||||
|
against a Contributor.
|
||||||
|
|
||||||
|
10. Versions of the License
|
||||||
|
|
||||||
|
10.1. New Versions
|
||||||
|
|
||||||
|
Mozilla Foundation is the license steward. Except as provided in Section 10.3,
|
||||||
|
no one other than the license steward has the right to modify or publish new
|
||||||
|
versions of this License. Each version will be given a distinguishing version
|
||||||
|
number.
|
||||||
|
|
||||||
|
10.2. Effect of New Versions
|
||||||
|
|
||||||
|
You may distribute the Covered Software under the terms of the version of
|
||||||
|
the License under which You originally received the Covered Software, or under
|
||||||
|
the terms of any subsequent version published by the license steward.
|
||||||
|
|
||||||
|
10.3. Modified Versions
|
||||||
|
|
||||||
|
If you create software not governed by this License, and you want to create
|
||||||
|
a new license for such software, you may create and use a modified version
|
||||||
|
of this License if you rename the license and remove any references to the
|
||||||
|
name of the license steward (except to note that such modified license differs
|
||||||
|
from this License).
|
||||||
|
|
||||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
||||||
|
|
||||||
|
If You choose to distribute Source Code Form that is Incompatible With Secondary
|
||||||
|
Licenses under the terms of this version of the License, the notice described
|
||||||
|
in Exhibit B of this License must be attached. Exhibit A - Source Code Form
|
||||||
|
License Notice
|
||||||
|
|
||||||
|
This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||||
|
v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain
|
||||||
|
one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
If it is not possible or desirable to put the notice in a particular file,
|
||||||
|
then You may include the notice in a location (such as a LICENSE file in a
|
||||||
|
relevant directory) where a recipient would be likely to look for such a notice.
|
||||||
|
|
||||||
|
You may add additional accurate notices of copyright ownership.
|
||||||
|
|
||||||
|
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||||
|
|
||||||
|
This Source Code Form is "Incompatible With Secondary Licenses", as defined
|
||||||
|
by the Mozilla Public License, v. 2.0.
|
|
@ -0,0 +1,195 @@
|
||||||
|
# git-version.go
|
||||||
|
|
||||||
|
Use git tags to add semver to your go package.
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Goal: Either use an exact version like v1.0.0
|
||||||
|
or translate the git version like v1.0.0-4-g0000000
|
||||||
|
to a semver like v1.0.1-pre4+g0000000
|
||||||
|
|
||||||
|
Fail gracefully when git repo isn't available.
|
||||||
|
```
|
||||||
|
|
||||||
|
# Demo
|
||||||
|
|
||||||
|
Generate an `xversion.go` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run git.rootprojects.org/root/go-gitver
|
||||||
|
cat xversion.go
|
||||||
|
```
|
||||||
|
|
||||||
|
<small>**Note**: The file is named `xversion.go` by default so that the
|
||||||
|
generated file's `init()` will come later, and thus take priority, over
|
||||||
|
most other files.</small>
|
||||||
|
|
||||||
|
See `go-gitver`s self-generated version:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run git.rootprojects.org/root/go-gitver version
|
||||||
|
```
|
||||||
|
|
||||||
|
# QuickStart
|
||||||
|
|
||||||
|
Add this to the top of your main file:
|
||||||
|
|
||||||
|
```go
|
||||||
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a file that imports go-gitver (for versioning)
|
||||||
|
|
||||||
|
```go
|
||||||
|
// +build tools
|
||||||
|
|
||||||
|
package example
|
||||||
|
|
||||||
|
import _ "git.rootprojects.org/root/go-gitver"
|
||||||
|
```
|
||||||
|
|
||||||
|
Change you build instructions to be something like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod vendor
|
||||||
|
go generate -mod=vendor ./...
|
||||||
|
go build -mod=vendor -o example cmd/example/*.go
|
||||||
|
```
|
||||||
|
|
||||||
|
You don't have to use `mod vendor`, but I highly recommend it.
|
||||||
|
|
||||||
|
# Options
|
||||||
|
|
||||||
|
```txt
|
||||||
|
version print version and exit
|
||||||
|
--fail exit with non-zero status code on failure
|
||||||
|
--package <name> will set the package name
|
||||||
|
--outfile <name> will replace `xversion.go` with the given file path
|
||||||
|
```
|
||||||
|
|
||||||
|
ENVs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Alias for --fail
|
||||||
|
GITVER_FAIL=true
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver --fail
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run -mod=vendor git.rootprojects.org/root/go-gitver version
|
||||||
|
```
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
See `examples/basic`
|
||||||
|
|
||||||
|
1. Create a `tools` package in your project
|
||||||
|
2. Guard it against regular builds with `// +build tools`
|
||||||
|
3. Include `_ "git.rootprojects.org/root/go-gitver"` in the imports
|
||||||
|
4. Declare `var GitRev, GitVersion, GitTimestamp string` in your `package main`
|
||||||
|
5. Include `//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver` as well
|
||||||
|
|
||||||
|
`tools/tools.go`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// +build tools
|
||||||
|
|
||||||
|
// This is a dummy package for build tooling
|
||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "git.rootprojects.org/root/go-gitver"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
`main.go`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
//go:generate go run git.rootprojects.org/root/go-gitver --fail
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
var (
|
||||||
|
GitRev = "0000000"
|
||||||
|
GitVersion = "v0.0.0-pre0+0000000"
|
||||||
|
GitTimestamp = "0000-00-00T00:00:00+0000"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(GitRev)
|
||||||
|
fmt.Println(GitVersion)
|
||||||
|
fmt.Println(GitTimestamp)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're using `go mod vendor` (which I highly recommend that you do),
|
||||||
|
you'd modify the `go:generate` ever so slightly:
|
||||||
|
|
||||||
|
```go
|
||||||
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver --fail
|
||||||
|
```
|
||||||
|
|
||||||
|
The only reason I didn't do that in the example is that I'd be included
|
||||||
|
the repository in itself and that would be... weird.
|
||||||
|
|
||||||
|
# Why a tools package?
|
||||||
|
|
||||||
|
> import "git.rootprojects.org/root/go-gitver" is a program, not an importable package
|
||||||
|
|
||||||
|
Having a tools package with a build tag that you don't use is a nice way to add exact
|
||||||
|
versions of a command package used for tooling to your `go.mod` with `go mod tidy`,
|
||||||
|
without getting the error above.
|
||||||
|
|
||||||
|
# git: behind the curtain
|
||||||
|
|
||||||
|
These are the commands that are used under the hood to produce the versions.
|
||||||
|
|
||||||
|
Shows the git tag + description. Assumes that you're using the semver format `v1.0.0` for your base tags.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git describe --tags --dirty --always
|
||||||
|
# v1.0.0
|
||||||
|
# v1.0.0-1-g0000000
|
||||||
|
# v1.0.0-dirty
|
||||||
|
```
|
||||||
|
|
||||||
|
Show the commit date (when the commit made it into the current tree).
|
||||||
|
Internally we use the current date when the working tree is dirty.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git show v1.0.0-1-g0000000 --format=%cd --date=format:%Y-%m-%dT%H:%M:%SZ%z --no-patch
|
||||||
|
# 2010-01-01T20:30:00Z-0600
|
||||||
|
# fatal: ambiguous argument 'v1.0.0-1-g0000000-dirty': unknown revision or path not in the working tree.
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows the most recent commit.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git rev-parse HEAD
|
||||||
|
# 0000000000000000000000000000000000000000
|
||||||
|
```
|
||||||
|
|
||||||
|
# Errors
|
||||||
|
|
||||||
|
### cannot find package "."
|
||||||
|
|
||||||
|
```txt
|
||||||
|
package git.rootprojects.org/root/go-gitver: cannot find package "." in:
|
||||||
|
/Users/me/go-example/vendor/git.rootprojects.org/root/go-gitver
|
||||||
|
cmd/example/example.go:1: running "go": exit status 1
|
||||||
|
```
|
||||||
|
|
||||||
|
You forgot to update deps and re-vendor:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod tidy
|
||||||
|
go mod vendor
|
||||||
|
```
|
|
@ -0,0 +1,104 @@
|
||||||
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"os"
|
||||||
|
"text/template"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.rootprojects.org/root/go-gitver/gitver"
|
||||||
|
)
|
||||||
|
|
||||||
|
var GitRev, GitVersion, GitTimestamp string
|
||||||
|
var exitCode int
|
||||||
|
var verFile = "xversion.go"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pkg := "main"
|
||||||
|
|
||||||
|
args := os.Args[1:]
|
||||||
|
for i := range args {
|
||||||
|
arg := args[i]
|
||||||
|
if "-f" == arg || "--fail" == arg {
|
||||||
|
exitCode = 1
|
||||||
|
} else if ("--outfile" == arg || "-o" == arg) && len(args) > i+1 {
|
||||||
|
verFile = args[i+1]
|
||||||
|
args[i+1] = ""
|
||||||
|
} else if "--package" == arg && len(args) > i+1 {
|
||||||
|
pkg = args[i+1]
|
||||||
|
args[i+1] = ""
|
||||||
|
} else if "-V" == arg || "version" == arg || "-version" == arg || "--version" == arg {
|
||||||
|
fmt.Println(GitRev)
|
||||||
|
fmt.Println(GitVersion)
|
||||||
|
fmt.Println(GitTimestamp)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if "" != os.Getenv("GITVER_FAIL") && "false" != os.Getenv("GITVER_FAIL") {
|
||||||
|
exitCode = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := gitver.ExecAndParse()
|
||||||
|
if nil != err {
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to get git version: %s\n", err)
|
||||||
|
if exitCode > 0 {
|
||||||
|
os.Exit(exitCode)
|
||||||
|
}
|
||||||
|
v = &gitver.Versions{
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create or overwrite the go file from template
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := versionTpl.Execute(&buf, struct {
|
||||||
|
Package string
|
||||||
|
Timestamp string
|
||||||
|
Version string
|
||||||
|
GitRev string
|
||||||
|
}{
|
||||||
|
Package: pkg,
|
||||||
|
Timestamp: v.Timestamp.Format(time.RFC3339),
|
||||||
|
Version: v.Version,
|
||||||
|
GitRev: v.Rev,
|
||||||
|
}); nil != err {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format
|
||||||
|
src, err := format.Source(buf.Bytes())
|
||||||
|
if nil != err {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to disk (in the Current Working Directory)
|
||||||
|
f, err := os.Create(verFile)
|
||||||
|
if nil != err {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if _, err := f.Write(src); nil != err {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := f.Close(); nil != err {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var versionTpl = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT.
|
||||||
|
package {{ .Package }}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
{{ if .GitRev -}}
|
||||||
|
GitRev = "{{ .GitRev }}"
|
||||||
|
{{ end -}}
|
||||||
|
{{ if .Version -}}
|
||||||
|
GitVersion = "{{ .Version }}"
|
||||||
|
{{ end -}}
|
||||||
|
GitTimestamp = "{{ .Timestamp }}"
|
||||||
|
}
|
||||||
|
`))
|
|
@ -0,0 +1,143 @@
|
||||||
|
package gitver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var exactVer *regexp.Regexp
|
||||||
|
var gitVer *regexp.Regexp
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// exactly vX.Y.Z (go-compatible semver)
|
||||||
|
exactVer = regexp.MustCompile(`^v\d+\.\d+\.\d+$`)
|
||||||
|
|
||||||
|
// vX.Y.Z-n-g0000000 git post-release, semver prerelease
|
||||||
|
// vX.Y.Z-dirty git post-release, semver prerelease
|
||||||
|
gitVer = regexp.MustCompile(`^(v\d+\.\d+)\.(\d+)(-(\d+))?(-(g[0-9a-f]+))?(-(dirty))?`)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Versions struct {
|
||||||
|
Timestamp time.Time
|
||||||
|
Version string
|
||||||
|
Rev string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExecAndParse() (*Versions, error) {
|
||||||
|
desc, err := gitDesc()
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rev, err := gitRev()
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ver, err := semVer(desc)
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ts, err := gitTimestamp(desc)
|
||||||
|
if nil != err {
|
||||||
|
ts = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Versions{
|
||||||
|
Timestamp: ts,
|
||||||
|
Version: ver,
|
||||||
|
Rev: rev,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gitDesc() (string, error) {
|
||||||
|
args := strings.Split("git describe --tags --dirty --always", " ")
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if nil != err {
|
||||||
|
// Don't panic, just carry on
|
||||||
|
//out = []byte("v0.0.0-0-g0000000")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(out)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gitRev() (string, error) {
|
||||||
|
args := strings.Split("git rev-parse HEAD", " ")
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if nil != err {
|
||||||
|
return "", fmt.Errorf("\nUnexpected Error\n\n"+
|
||||||
|
"Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+
|
||||||
|
"Please include the following:\n\n"+
|
||||||
|
"Command: %s\n"+
|
||||||
|
"Output: %s\n"+
|
||||||
|
"Error: %s\n"+
|
||||||
|
"\nPlease and Thank You.\n\n", strings.Join(args, " "), out, err)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(out)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func semVer(desc string) (string, error) {
|
||||||
|
if exactVer.MatchString(desc) {
|
||||||
|
// v1.0.0
|
||||||
|
return desc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !gitVer.MatchString(desc) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// (v1.0).(0)(-(1))(-(g0000000))(-(dirty))
|
||||||
|
vers := gitVer.FindStringSubmatch(desc)
|
||||||
|
patch, err := strconv.Atoi(vers[2])
|
||||||
|
if nil != err {
|
||||||
|
return "", fmt.Errorf("\nUnexpected Error\n\n"+
|
||||||
|
"Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+
|
||||||
|
"Please include the following:\n\n"+
|
||||||
|
"git description: %s\n"+
|
||||||
|
"RegExp: %#v\n"+
|
||||||
|
"Error: %s\n"+
|
||||||
|
"\nPlease and Thank You.\n\n", desc, gitVer, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// v1.0.1-pre1
|
||||||
|
// v1.0.1-pre1+g0000000
|
||||||
|
// v1.0.1-pre0+dirty
|
||||||
|
// v1.0.1-pre0+g0000000-dirty
|
||||||
|
if "" == vers[4] {
|
||||||
|
vers[4] = "0"
|
||||||
|
}
|
||||||
|
ver := fmt.Sprintf("%s.%d-pre%s", vers[1], patch+1, vers[4])
|
||||||
|
if "" != vers[6] || "dirty" == vers[8] {
|
||||||
|
ver += "+"
|
||||||
|
if "" != vers[6] {
|
||||||
|
ver += vers[6]
|
||||||
|
if "" != vers[8] {
|
||||||
|
ver += "-"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ver += vers[8]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ver, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gitTimestamp(desc string) (time.Time, error) {
|
||||||
|
args := []string{
|
||||||
|
"git",
|
||||||
|
"show", desc,
|
||||||
|
"--format=%cd",
|
||||||
|
"--date=format:%Y-%m-%dT%H:%M:%SZ%z",
|
||||||
|
"--no-patch",
|
||||||
|
}
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if nil != err {
|
||||||
|
// a dirty desc was probably used
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
return time.Parse(time.RFC3339, strings.TrimSpace(string(out)))
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
module git.rootprojects.org/root/go-gitver
|
||||||
|
|
||||||
|
go 1.12
|
|
@ -0,0 +1,9 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
// use recently generated version info as a fallback
|
||||||
|
// for when git isn't present (i.e. go run <url>)
|
||||||
|
func init() {
|
||||||
|
GitRev = "0921ed1e6007493c886c87ee9a15f2cceecb1f9f"
|
||||||
|
GitVersion = "v1.1.2"
|
||||||
|
GitTimestamp = "2019-07-01T02:32:58-06:00"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
# This source code refers to The Go Authors for copyright purposes.
|
||||||
|
# The master list of authors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/AUTHORS.
|
|
@ -0,0 +1,3 @@
|
||||||
|
# This source code was written by the Go contributors.
|
||||||
|
# The master list of contributors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/CONTRIBUTORS.
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,22 @@
|
||||||
|
Additional IP Rights Grant (Patents)
|
||||||
|
|
||||||
|
"This implementation" means the copyrightable works distributed by
|
||||||
|
Google as part of the Go project.
|
||||||
|
|
||||||
|
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||||
|
patent license to make, have made, use, offer to sell, sell, import,
|
||||||
|
transfer and otherwise run, modify and propagate the contents of this
|
||||||
|
implementation of Go, where such license applies only to those patent
|
||||||
|
claims, both currently owned or controlled by Google and acquired in
|
||||||
|
the future, licensable by Google that are necessarily infringed by this
|
||||||
|
implementation of Go. This grant does not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of this
|
||||||
|
implementation. If you or your agent or exclusive licensee institute or
|
||||||
|
order or agree to the institution of patent litigation against any
|
||||||
|
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||||
|
that this implementation of Go or any code incorporated within this
|
||||||
|
implementation of Go constitutes direct or contributory patent
|
||||||
|
infringement, or inducement of patent infringement, then any patent
|
||||||
|
rights granted to you under this License for this implementation of Go
|
||||||
|
shall terminate as of the date such litigation is filed.
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
type Errno = syscall.Errno
|
||||||
|
type SysProcAttr = syscall.SysProcAttr
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2009 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.
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for 386, Windows are implemented in runtime/syscall_windows.goc
|
||||||
|
//
|
||||||
|
|
||||||
|
TEXT ·getprocaddress(SB), 7, $0-16
|
||||||
|
JMP syscall·getprocaddress(SB)
|
||||||
|
|
||||||
|
TEXT ·loadlibrary(SB), 7, $0-12
|
||||||
|
JMP syscall·loadlibrary(SB)
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2009 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.
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for amd64, Windows are implemented in runtime/syscall_windows.goc
|
||||||
|
//
|
||||||
|
|
||||||
|
TEXT ·getprocaddress(SB), 7, $0-32
|
||||||
|
JMP syscall·getprocaddress(SB)
|
||||||
|
|
||||||
|
TEXT ·loadlibrary(SB), 7, $0-24
|
||||||
|
JMP syscall·loadlibrary(SB)
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
TEXT ·getprocaddress(SB),NOSPLIT,$0
|
||||||
|
B syscall·getprocaddress(SB)
|
||||||
|
|
||||||
|
TEXT ·loadlibrary(SB),NOSPLIT,$0
|
||||||
|
B syscall·loadlibrary(SB)
|
|
@ -0,0 +1,378 @@
|
||||||
|
// Copyright 2011 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.
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DLLError describes reasons for DLL load failures.
|
||||||
|
type DLLError struct {
|
||||||
|
Err error
|
||||||
|
ObjName string
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DLLError) Error() string { return e.Msg }
|
||||||
|
|
||||||
|
// Implemented in runtime/syscall_windows.goc; we provide jumps to them in our assembly file.
|
||||||
|
func loadlibrary(filename *uint16) (handle uintptr, err syscall.Errno)
|
||||||
|
func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err syscall.Errno)
|
||||||
|
|
||||||
|
// A DLL implements access to a single DLL.
|
||||||
|
type DLL struct {
|
||||||
|
Name string
|
||||||
|
Handle Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadDLL loads DLL file into memory.
|
||||||
|
//
|
||||||
|
// Warning: using LoadDLL without an absolute path name is subject to
|
||||||
|
// DLL preloading attacks. To safely load a system DLL, use LazyDLL
|
||||||
|
// with System set to true, or use LoadLibraryEx directly.
|
||||||
|
func LoadDLL(name string) (dll *DLL, err error) {
|
||||||
|
namep, err := UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
h, e := loadlibrary(namep)
|
||||||
|
if e != 0 {
|
||||||
|
return nil, &DLLError{
|
||||||
|
Err: e,
|
||||||
|
ObjName: name,
|
||||||
|
Msg: "Failed to load " + name + ": " + e.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d := &DLL{
|
||||||
|
Name: name,
|
||||||
|
Handle: Handle(h),
|
||||||
|
}
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustLoadDLL is like LoadDLL but panics if load operation failes.
|
||||||
|
func MustLoadDLL(name string) *DLL {
|
||||||
|
d, e := LoadDLL(name)
|
||||||
|
if e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindProc searches DLL d for procedure named name and returns *Proc
|
||||||
|
// if found. It returns an error if search fails.
|
||||||
|
func (d *DLL) FindProc(name string) (proc *Proc, err error) {
|
||||||
|
namep, err := BytePtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
a, e := getprocaddress(uintptr(d.Handle), namep)
|
||||||
|
if e != 0 {
|
||||||
|
return nil, &DLLError{
|
||||||
|
Err: e,
|
||||||
|
ObjName: name,
|
||||||
|
Msg: "Failed to find " + name + " procedure in " + d.Name + ": " + e.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p := &Proc{
|
||||||
|
Dll: d,
|
||||||
|
Name: name,
|
||||||
|
addr: a,
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustFindProc is like FindProc but panics if search fails.
|
||||||
|
func (d *DLL) MustFindProc(name string) *Proc {
|
||||||
|
p, e := d.FindProc(name)
|
||||||
|
if e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release unloads DLL d from memory.
|
||||||
|
func (d *DLL) Release() (err error) {
|
||||||
|
return FreeLibrary(d.Handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Proc implements access to a procedure inside a DLL.
|
||||||
|
type Proc struct {
|
||||||
|
Dll *DLL
|
||||||
|
Name string
|
||||||
|
addr uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr returns the address of the procedure represented by p.
|
||||||
|
// The return value can be passed to Syscall to run the procedure.
|
||||||
|
func (p *Proc) Addr() uintptr {
|
||||||
|
return p.addr
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:uintptrescapes
|
||||||
|
|
||||||
|
// Call executes procedure p with arguments a. It will panic, if more than 15 arguments
|
||||||
|
// are supplied.
|
||||||
|
//
|
||||||
|
// The returned error is always non-nil, constructed from the result of GetLastError.
|
||||||
|
// Callers must inspect the primary return value to decide whether an error occurred
|
||||||
|
// (according to the semantics of the specific function being called) before consulting
|
||||||
|
// the error. The error will be guaranteed to contain windows.Errno.
|
||||||
|
func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||||
|
switch len(a) {
|
||||||
|
case 0:
|
||||||
|
return syscall.Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0)
|
||||||
|
case 1:
|
||||||
|
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], 0, 0)
|
||||||
|
case 2:
|
||||||
|
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], 0)
|
||||||
|
case 3:
|
||||||
|
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], a[2])
|
||||||
|
case 4:
|
||||||
|
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)
|
||||||
|
case 5:
|
||||||
|
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0)
|
||||||
|
case 6:
|
||||||
|
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5])
|
||||||
|
case 7:
|
||||||
|
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
|
||||||
|
case 8:
|
||||||
|
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
|
||||||
|
case 9:
|
||||||
|
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
|
||||||
|
case 10:
|
||||||
|
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
|
||||||
|
case 11:
|
||||||
|
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
|
||||||
|
case 12:
|
||||||
|
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
|
||||||
|
case 13:
|
||||||
|
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
|
||||||
|
case 14:
|
||||||
|
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
|
||||||
|
case 15:
|
||||||
|
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
|
||||||
|
default:
|
||||||
|
panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A LazyDLL implements access to a single DLL.
|
||||||
|
// It will delay the load of the DLL until the first
|
||||||
|
// call to its Handle method or to one of its
|
||||||
|
// LazyProc's Addr method.
|
||||||
|
type LazyDLL struct {
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// System determines whether the DLL must be loaded from the
|
||||||
|
// Windows System directory, bypassing the normal DLL search
|
||||||
|
// path.
|
||||||
|
System bool
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
dll *DLL // non nil once DLL is loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load loads DLL file d.Name into memory. It returns an error if fails.
|
||||||
|
// Load will not try to load DLL, if it is already loaded into memory.
|
||||||
|
func (d *LazyDLL) Load() error {
|
||||||
|
// Non-racy version of:
|
||||||
|
// if d.dll != nil {
|
||||||
|
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll))) != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
if d.dll != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// kernel32.dll is special, since it's where LoadLibraryEx comes from.
|
||||||
|
// The kernel already special-cases its name, so it's always
|
||||||
|
// loaded from system32.
|
||||||
|
var dll *DLL
|
||||||
|
var err error
|
||||||
|
if d.Name == "kernel32.dll" {
|
||||||
|
dll, err = LoadDLL(d.Name)
|
||||||
|
} else {
|
||||||
|
dll, err = loadLibraryEx(d.Name, d.System)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-racy version of:
|
||||||
|
// d.dll = dll
|
||||||
|
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)), unsafe.Pointer(dll))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustLoad is like Load but panics if search fails.
|
||||||
|
func (d *LazyDLL) mustLoad() {
|
||||||
|
e := d.Load()
|
||||||
|
if e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle returns d's module handle.
|
||||||
|
func (d *LazyDLL) Handle() uintptr {
|
||||||
|
d.mustLoad()
|
||||||
|
return uintptr(d.dll.Handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProc returns a LazyProc for accessing the named procedure in the DLL d.
|
||||||
|
func (d *LazyDLL) NewProc(name string) *LazyProc {
|
||||||
|
return &LazyProc{l: d, Name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLazyDLL creates new LazyDLL associated with DLL file.
|
||||||
|
func NewLazyDLL(name string) *LazyDLL {
|
||||||
|
return &LazyDLL{Name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLazySystemDLL is like NewLazyDLL, but will only
|
||||||
|
// search Windows System directory for the DLL if name is
|
||||||
|
// a base name (like "advapi32.dll").
|
||||||
|
func NewLazySystemDLL(name string) *LazyDLL {
|
||||||
|
return &LazyDLL{Name: name, System: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A LazyProc implements access to a procedure inside a LazyDLL.
|
||||||
|
// It delays the lookup until the Addr method is called.
|
||||||
|
type LazyProc struct {
|
||||||
|
Name string
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
l *LazyDLL
|
||||||
|
proc *Proc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find searches DLL for procedure named p.Name. It returns
|
||||||
|
// an error if search fails. Find will not search procedure,
|
||||||
|
// if it is already found and loaded into memory.
|
||||||
|
func (p *LazyProc) Find() error {
|
||||||
|
// Non-racy version of:
|
||||||
|
// if p.proc == nil {
|
||||||
|
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
if p.proc == nil {
|
||||||
|
e := p.l.Load()
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
proc, e := p.l.dll.FindProc(p.Name)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
// Non-racy version of:
|
||||||
|
// p.proc = proc
|
||||||
|
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustFind is like Find but panics if search fails.
|
||||||
|
func (p *LazyProc) mustFind() {
|
||||||
|
e := p.Find()
|
||||||
|
if e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr returns the address of the procedure represented by p.
|
||||||
|
// The return value can be passed to Syscall to run the procedure.
|
||||||
|
// It will panic if the procedure cannot be found.
|
||||||
|
func (p *LazyProc) Addr() uintptr {
|
||||||
|
p.mustFind()
|
||||||
|
return p.proc.Addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:uintptrescapes
|
||||||
|
|
||||||
|
// Call executes procedure p with arguments a. It will panic, if more than 15 arguments
|
||||||
|
// are supplied. It will also panic if the procedure cannot be found.
|
||||||
|
//
|
||||||
|
// The returned error is always non-nil, constructed from the result of GetLastError.
|
||||||
|
// Callers must inspect the primary return value to decide whether an error occurred
|
||||||
|
// (according to the semantics of the specific function being called) before consulting
|
||||||
|
// the error. The error will be guaranteed to contain windows.Errno.
|
||||||
|
func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||||
|
p.mustFind()
|
||||||
|
return p.proc.Call(a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
var canDoSearchSystem32Once struct {
|
||||||
|
sync.Once
|
||||||
|
v bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func initCanDoSearchSystem32() {
|
||||||
|
// https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx says:
|
||||||
|
// "Windows 7, Windows Server 2008 R2, Windows Vista, and Windows
|
||||||
|
// Server 2008: The LOAD_LIBRARY_SEARCH_* flags are available on
|
||||||
|
// systems that have KB2533623 installed. To determine whether the
|
||||||
|
// flags are available, use GetProcAddress to get the address of the
|
||||||
|
// AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories
|
||||||
|
// function. If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_*
|
||||||
|
// flags can be used with LoadLibraryEx."
|
||||||
|
canDoSearchSystem32Once.v = (modkernel32.NewProc("AddDllDirectory").Find() == nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func canDoSearchSystem32() bool {
|
||||||
|
canDoSearchSystem32Once.Do(initCanDoSearchSystem32)
|
||||||
|
return canDoSearchSystem32Once.v
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBaseName(name string) bool {
|
||||||
|
for _, c := range name {
|
||||||
|
if c == ':' || c == '/' || c == '\\' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadLibraryEx wraps the Windows LoadLibraryEx function.
|
||||||
|
//
|
||||||
|
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx
|
||||||
|
//
|
||||||
|
// If name is not an absolute path, LoadLibraryEx searches for the DLL
|
||||||
|
// in a variety of automatic locations unless constrained by flags.
|
||||||
|
// See: https://msdn.microsoft.com/en-us/library/ff919712%28VS.85%29.aspx
|
||||||
|
func loadLibraryEx(name string, system bool) (*DLL, error) {
|
||||||
|
loadDLL := name
|
||||||
|
var flags uintptr
|
||||||
|
if system {
|
||||||
|
if canDoSearchSystem32() {
|
||||||
|
const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
|
||||||
|
flags = LOAD_LIBRARY_SEARCH_SYSTEM32
|
||||||
|
} else if isBaseName(name) {
|
||||||
|
// WindowsXP or unpatched Windows machine
|
||||||
|
// trying to load "foo.dll" out of the system
|
||||||
|
// folder, but LoadLibraryEx doesn't support
|
||||||
|
// that yet on their system, so emulate it.
|
||||||
|
systemdir, err := GetSystemDirectory()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
loadDLL = systemdir + "\\" + name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h, err := LoadLibraryEx(loadDLL, 0, flags)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &DLL{Name: name, Handle: h}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type errString string
|
||||||
|
|
||||||
|
func (s errString) Error() string { return string(s) }
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright 2010 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.
|
||||||
|
|
||||||
|
// Windows environment variables.
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unicode/utf16"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Getenv(key string) (value string, found bool) {
|
||||||
|
return syscall.Getenv(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Setenv(key, value string) error {
|
||||||
|
return syscall.Setenv(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Clearenv() {
|
||||||
|
syscall.Clearenv()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Environ() []string {
|
||||||
|
return syscall.Environ()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a default environment associated with the token, rather than the current
|
||||||
|
// process. If inheritExisting is true, then this environment also inherits the
|
||||||
|
// environment of the current process.
|
||||||
|
func (token Token) Environ(inheritExisting bool) (env []string, err error) {
|
||||||
|
var block *uint16
|
||||||
|
err = CreateEnvironmentBlock(&block, token, inheritExisting)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer DestroyEnvironmentBlock(block)
|
||||||
|
blockp := uintptr(unsafe.Pointer(block))
|
||||||
|
for {
|
||||||
|
entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:]
|
||||||
|
for i, v := range entry {
|
||||||
|
if v == 0 {
|
||||||
|
entry = entry[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(entry) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
env = append(env, string(utf16.Decode(entry)))
|
||||||
|
blockp += 2 * (uintptr(len(entry)) + 1)
|
||||||
|
}
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unsetenv(key string) error {
|
||||||
|
return syscall.Unsetenv(key)
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2012 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.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
const (
|
||||||
|
EVENTLOG_SUCCESS = 0
|
||||||
|
EVENTLOG_ERROR_TYPE = 1
|
||||||
|
EVENTLOG_WARNING_TYPE = 2
|
||||||
|
EVENTLOG_INFORMATION_TYPE = 4
|
||||||
|
EVENTLOG_AUDIT_SUCCESS = 8
|
||||||
|
EVENTLOG_AUDIT_FAILURE = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
//sys RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) [failretval==0] = advapi32.RegisterEventSourceW
|
||||||
|
//sys DeregisterEventSource(handle Handle) (err error) = advapi32.DeregisterEventSource
|
||||||
|
//sys ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) = advapi32.ReportEventW
|
|
@ -0,0 +1,97 @@
|
||||||
|
// Copyright 2009 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.
|
||||||
|
|
||||||
|
// Fork, exec, wait, etc.
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
// EscapeArg rewrites command line argument s as prescribed
|
||||||
|
// in http://msdn.microsoft.com/en-us/library/ms880421.
|
||||||
|
// This function returns "" (2 double quotes) if s is empty.
|
||||||
|
// Alternatively, these transformations are done:
|
||||||
|
// - every back slash (\) is doubled, but only if immediately
|
||||||
|
// followed by double quote (");
|
||||||
|
// - every double quote (") is escaped by back slash (\);
|
||||||
|
// - finally, s is wrapped with double quotes (arg -> "arg"),
|
||||||
|
// but only if there is space or tab inside s.
|
||||||
|
func EscapeArg(s string) string {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return "\"\""
|
||||||
|
}
|
||||||
|
n := len(s)
|
||||||
|
hasSpace := false
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
switch s[i] {
|
||||||
|
case '"', '\\':
|
||||||
|
n++
|
||||||
|
case ' ', '\t':
|
||||||
|
hasSpace = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hasSpace {
|
||||||
|
n += 2
|
||||||
|
}
|
||||||
|
if n == len(s) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
qs := make([]byte, n)
|
||||||
|
j := 0
|
||||||
|
if hasSpace {
|
||||||
|
qs[j] = '"'
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
slashes := 0
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
switch s[i] {
|
||||||
|
default:
|
||||||
|
slashes = 0
|
||||||
|
qs[j] = s[i]
|
||||||
|
case '\\':
|
||||||
|
slashes++
|
||||||
|
qs[j] = s[i]
|
||||||
|
case '"':
|
||||||
|
for ; slashes > 0; slashes-- {
|
||||||
|
qs[j] = '\\'
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
qs[j] = '\\'
|
||||||
|
j++
|
||||||
|
qs[j] = s[i]
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
if hasSpace {
|
||||||
|
for ; slashes > 0; slashes-- {
|
||||||
|
qs[j] = '\\'
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
qs[j] = '"'
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
return string(qs[:j])
|
||||||
|
}
|
||||||
|
|
||||||
|
func CloseOnExec(fd Handle) {
|
||||||
|
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FullPath retrieves the full path of the specified file.
|
||||||
|
func FullPath(name string) (path string, err error) {
|
||||||
|
p, err := UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
n := uint32(100)
|
||||||
|
for {
|
||||||
|
buf := make([]uint16, n)
|
||||||
|
n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if n <= uint32(len(buf)) {
|
||||||
|
return UTF16ToString(buf[:n]), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
const (
|
||||||
|
MEM_COMMIT = 0x00001000
|
||||||
|
MEM_RESERVE = 0x00002000
|
||||||
|
MEM_DECOMMIT = 0x00004000
|
||||||
|
MEM_RELEASE = 0x00008000
|
||||||
|
MEM_RESET = 0x00080000
|
||||||
|
MEM_TOP_DOWN = 0x00100000
|
||||||
|
MEM_WRITE_WATCH = 0x00200000
|
||||||
|
MEM_PHYSICAL = 0x00400000
|
||||||
|
MEM_RESET_UNDO = 0x01000000
|
||||||
|
MEM_LARGE_PAGES = 0x20000000
|
||||||
|
|
||||||
|
PAGE_NOACCESS = 0x01
|
||||||
|
PAGE_READONLY = 0x02
|
||||||
|
PAGE_READWRITE = 0x04
|
||||||
|
PAGE_WRITECOPY = 0x08
|
||||||
|
PAGE_EXECUTE_READ = 0x20
|
||||||
|
PAGE_EXECUTE_READWRITE = 0x40
|
||||||
|
PAGE_EXECUTE_WRITECOPY = 0x80
|
||||||
|
)
|
|
@ -0,0 +1,63 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2019 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.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
winerror="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/shared/winerror.h | sort -Vr | head -n 1)"
|
||||||
|
[[ -n $winerror ]] || { echo "Unable to find winerror.h" >&2; exit 1; }
|
||||||
|
|
||||||
|
declare -A errors
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "// Code generated by 'mkerrors.bash'; DO NOT EDIT."
|
||||||
|
echo
|
||||||
|
echo "package windows"
|
||||||
|
echo "import \"syscall\""
|
||||||
|
echo "const ("
|
||||||
|
|
||||||
|
while read -r line; do
|
||||||
|
unset vtype
|
||||||
|
if [[ $line =~ ^#define\ +([A-Z0-9_]+k?)\ +([A-Z0-9_]+\()?([A-Z][A-Z0-9_]+k?)\)? ]]; then
|
||||||
|
key="${BASH_REMATCH[1]}"
|
||||||
|
value="${BASH_REMATCH[3]}"
|
||||||
|
elif [[ $line =~ ^#define\ +([A-Z0-9_]+k?)\ +([A-Z0-9_]+\()?((0x)?[0-9A-Fa-f]+)L?\)? ]]; then
|
||||||
|
key="${BASH_REMATCH[1]}"
|
||||||
|
value="${BASH_REMATCH[3]}"
|
||||||
|
vtype="${BASH_REMATCH[2]}"
|
||||||
|
elif [[ $line =~ ^#define\ +([A-Z0-9_]+k?)\ +\(\(([A-Z]+)\)((0x)?[0-9A-Fa-f]+)L?\) ]]; then
|
||||||
|
key="${BASH_REMATCH[1]}"
|
||||||
|
value="${BASH_REMATCH[3]}"
|
||||||
|
vtype="${BASH_REMATCH[2]}"
|
||||||
|
else
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
[[ -n $key && -n $value ]] || continue
|
||||||
|
[[ -z ${errors["$key"]} ]] || continue
|
||||||
|
errors["$key"]="$value"
|
||||||
|
if [[ -v vtype ]]; then
|
||||||
|
if [[ $key == FACILITY_* || $key == NO_ERROR ]]; then
|
||||||
|
vtype=""
|
||||||
|
elif [[ $vtype == *HANDLE* || $vtype == *HRESULT* ]]; then
|
||||||
|
vtype="Handle"
|
||||||
|
else
|
||||||
|
vtype="syscall.Errno"
|
||||||
|
fi
|
||||||
|
last_vtype="$vtype"
|
||||||
|
else
|
||||||
|
vtype=""
|
||||||
|
if [[ $last_vtype == Handle && $value == NO_ERROR ]]; then
|
||||||
|
value="S_OK"
|
||||||
|
elif [[ $last_vtype == syscall.Errno && $value == NO_ERROR ]]; then
|
||||||
|
value="ERROR_SUCCESS"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$key $vtype = $value"
|
||||||
|
done < "$winerror"
|
||||||
|
|
||||||
|
echo ")"
|
||||||
|
} | gofmt > "zerrors_windows.go"
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2019 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.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
knownfolders="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/um/KnownFolders.h | sort -Vr | head -n 1)"
|
||||||
|
[[ -n $knownfolders ]] || { echo "Unable to find KnownFolders.h" >&2; exit 1; }
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "// Code generated by 'mkknownfolderids.bash'; DO NOT EDIT."
|
||||||
|
echo
|
||||||
|
echo "package windows"
|
||||||
|
echo "type KNOWNFOLDERID GUID"
|
||||||
|
echo "var ("
|
||||||
|
while read -r line; do
|
||||||
|
[[ $line =~ DEFINE_KNOWN_FOLDER\((FOLDERID_[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+)\) ]] || continue
|
||||||
|
printf "%s = &KNOWNFOLDERID{0x%08x, 0x%04x, 0x%04x, [8]byte{0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x}}\n" \
|
||||||
|
"${BASH_REMATCH[1]}" $(( "${BASH_REMATCH[2]}" )) $(( "${BASH_REMATCH[3]}" )) $(( "${BASH_REMATCH[4]}" )) \
|
||||||
|
$(( "${BASH_REMATCH[5]}" )) $(( "${BASH_REMATCH[6]}" )) $(( "${BASH_REMATCH[7]}" )) $(( "${BASH_REMATCH[8]}" )) \
|
||||||
|
$(( "${BASH_REMATCH[9]}" )) $(( "${BASH_REMATCH[10]}" )) $(( "${BASH_REMATCH[11]}" )) $(( "${BASH_REMATCH[12]}" ))
|
||||||
|
done < "$knownfolders"
|
||||||
|
echo ")"
|
||||||
|
} | gofmt > "zknownfolderids_windows.go"
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright 2009 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.
|
||||||
|
|
||||||
|
// +build generate
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2012 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.
|
||||||
|
|
||||||
|
// +build windows,race
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const raceenabled = true
|
||||||
|
|
||||||
|
func raceAcquire(addr unsafe.Pointer) {
|
||||||
|
runtime.RaceAcquire(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReleaseMerge(addr unsafe.Pointer) {
|
||||||
|
runtime.RaceReleaseMerge(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReadRange(addr unsafe.Pointer, len int) {
|
||||||
|
runtime.RaceReadRange(addr, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceWriteRange(addr unsafe.Pointer, len int) {
|
||||||
|
runtime.RaceWriteRange(addr, len)
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2012 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.
|
||||||
|
|
||||||
|
// +build windows,!race
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const raceenabled = false
|
||||||
|
|
||||||
|
func raceAcquire(addr unsafe.Pointer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReleaseMerge(addr unsafe.Pointer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReadRange(addr unsafe.Pointer, len int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceWriteRange(addr unsafe.Pointer, len int) {
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
// Package registry provides access to the Windows registry.
|
||||||
|
//
|
||||||
|
// Here is a simple example, opening a registry key and reading a string value from it.
|
||||||
|
//
|
||||||
|
// k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
|
// }
|
||||||
|
// defer k.Close()
|
||||||
|
//
|
||||||
|
// s, _, err := k.GetStringValue("SystemRoot")
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
|
// }
|
||||||
|
// fmt.Printf("Windows system root is %q\n", s)
|
||||||
|
//
|
||||||
|
package registry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Registry key security and access rights.
|
||||||
|
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724878.aspx
|
||||||
|
// for details.
|
||||||
|
ALL_ACCESS = 0xf003f
|
||||||
|
CREATE_LINK = 0x00020
|
||||||
|
CREATE_SUB_KEY = 0x00004
|
||||||
|
ENUMERATE_SUB_KEYS = 0x00008
|
||||||
|
EXECUTE = 0x20019
|
||||||
|
NOTIFY = 0x00010
|
||||||
|
QUERY_VALUE = 0x00001
|
||||||
|
READ = 0x20019
|
||||||
|
SET_VALUE = 0x00002
|
||||||
|
WOW64_32KEY = 0x00200
|
||||||
|
WOW64_64KEY = 0x00100
|
||||||
|
WRITE = 0x20006
|
||||||
|
)
|
||||||
|
|
||||||
|
// Key is a handle to an open Windows registry key.
|
||||||
|
// Keys can be obtained by calling OpenKey; there are
|
||||||
|
// also some predefined root keys such as CURRENT_USER.
|
||||||
|
// Keys can be used directly in the Windows API.
|
||||||
|
type Key syscall.Handle
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Windows defines some predefined root keys that are always open.
|
||||||
|
// An application can use these keys as entry points to the registry.
|
||||||
|
// Normally these keys are used in OpenKey to open new keys,
|
||||||
|
// but they can also be used anywhere a Key is required.
|
||||||
|
CLASSES_ROOT = Key(syscall.HKEY_CLASSES_ROOT)
|
||||||
|
CURRENT_USER = Key(syscall.HKEY_CURRENT_USER)
|
||||||
|
LOCAL_MACHINE = Key(syscall.HKEY_LOCAL_MACHINE)
|
||||||
|
USERS = Key(syscall.HKEY_USERS)
|
||||||
|
CURRENT_CONFIG = Key(syscall.HKEY_CURRENT_CONFIG)
|
||||||
|
PERFORMANCE_DATA = Key(syscall.HKEY_PERFORMANCE_DATA)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Close closes open key k.
|
||||||
|
func (k Key) Close() error {
|
||||||
|
return syscall.RegCloseKey(syscall.Handle(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenKey opens a new key with path name relative to key k.
|
||||||
|
// It accepts any open key, including CURRENT_USER and others,
|
||||||
|
// and returns the new key and an error.
|
||||||
|
// The access parameter specifies desired access rights to the
|
||||||
|
// key to be opened.
|
||||||
|
func OpenKey(k Key, path string, access uint32) (Key, error) {
|
||||||
|
p, err := syscall.UTF16PtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var subkey syscall.Handle
|
||||||
|
err = syscall.RegOpenKeyEx(syscall.Handle(k), p, 0, access, &subkey)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return Key(subkey), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenRemoteKey opens a predefined registry key on another
|
||||||
|
// computer pcname. The key to be opened is specified by k, but
|
||||||
|
// can only be one of LOCAL_MACHINE, PERFORMANCE_DATA or USERS.
|
||||||
|
// If pcname is "", OpenRemoteKey returns local computer key.
|
||||||
|
func OpenRemoteKey(pcname string, k Key) (Key, error) {
|
||||||
|
var err error
|
||||||
|
var p *uint16
|
||||||
|
if pcname != "" {
|
||||||
|
p, err = syscall.UTF16PtrFromString(`\\` + pcname)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var remoteKey syscall.Handle
|
||||||
|
err = regConnectRegistry(p, syscall.Handle(k), &remoteKey)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return Key(remoteKey), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadSubKeyNames returns the names of subkeys of key k.
|
||||||
|
// The parameter n controls the number of returned names,
|
||||||
|
// analogous to the way os.File.Readdirnames works.
|
||||||
|
func (k Key) ReadSubKeyNames(n int) ([]string, error) {
|
||||||
|
names := make([]string, 0)
|
||||||
|
// Registry key size limit is 255 bytes and described there:
|
||||||
|
// https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx
|
||||||
|
buf := make([]uint16, 256) //plus extra room for terminating zero byte
|
||||||
|
loopItems:
|
||||||
|
for i := uint32(0); ; i++ {
|
||||||
|
if n > 0 {
|
||||||
|
if len(names) == n {
|
||||||
|
return names, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l := uint32(len(buf))
|
||||||
|
for {
|
||||||
|
err := syscall.RegEnumKeyEx(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err == syscall.ERROR_MORE_DATA {
|
||||||
|
// Double buffer size and try again.
|
||||||
|
l = uint32(2 * len(buf))
|
||||||
|
buf = make([]uint16, l)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err == _ERROR_NO_MORE_ITEMS {
|
||||||
|
break loopItems
|
||||||
|
}
|
||||||
|
return names, err
|
||||||
|
}
|
||||||
|
names = append(names, syscall.UTF16ToString(buf[:l]))
|
||||||
|
}
|
||||||
|
if n > len(names) {
|
||||||
|
return names, io.EOF
|
||||||
|
}
|
||||||
|
return names, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateKey creates a key named path under open key k.
|
||||||
|
// CreateKey returns the new key and a boolean flag that reports
|
||||||
|
// whether the key already existed.
|
||||||
|
// The access parameter specifies the access rights for the key
|
||||||
|
// to be created.
|
||||||
|
func CreateKey(k Key, path string, access uint32) (newk Key, openedExisting bool, err error) {
|
||||||
|
var h syscall.Handle
|
||||||
|
var d uint32
|
||||||
|
err = regCreateKeyEx(syscall.Handle(k), syscall.StringToUTF16Ptr(path),
|
||||||
|
0, nil, _REG_OPTION_NON_VOLATILE, access, nil, &h, &d)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false, err
|
||||||
|
}
|
||||||
|
return Key(h), d == _REG_OPENED_EXISTING_KEY, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteKey deletes the subkey path of key k and its values.
|
||||||
|
func DeleteKey(k Key, path string) error {
|
||||||
|
return regDeleteKey(syscall.Handle(k), syscall.StringToUTF16Ptr(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
// A KeyInfo describes the statistics of a key. It is returned by Stat.
|
||||||
|
type KeyInfo struct {
|
||||||
|
SubKeyCount uint32
|
||||||
|
MaxSubKeyLen uint32 // size of the key's subkey with the longest name, in Unicode characters, not including the terminating zero byte
|
||||||
|
ValueCount uint32
|
||||||
|
MaxValueNameLen uint32 // size of the key's longest value name, in Unicode characters, not including the terminating zero byte
|
||||||
|
MaxValueLen uint32 // longest data component among the key's values, in bytes
|
||||||
|
lastWriteTime syscall.Filetime
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModTime returns the key's last write time.
|
||||||
|
func (ki *KeyInfo) ModTime() time.Time {
|
||||||
|
return time.Unix(0, ki.lastWriteTime.Nanoseconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat retrieves information about the open key k.
|
||||||
|
func (k Key) Stat() (*KeyInfo, error) {
|
||||||
|
var ki KeyInfo
|
||||||
|
err := syscall.RegQueryInfoKey(syscall.Handle(k), nil, nil, nil,
|
||||||
|
&ki.SubKeyCount, &ki.MaxSubKeyLen, nil, &ki.ValueCount,
|
||||||
|
&ki.MaxValueNameLen, &ki.MaxValueLen, nil, &ki.lastWriteTime)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ki, nil
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build generate
|
||||||
|
|
||||||
|
package registry
|
||||||
|
|
||||||
|
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package registry
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
const (
|
||||||
|
_REG_OPTION_NON_VOLATILE = 0
|
||||||
|
|
||||||
|
_REG_CREATED_NEW_KEY = 1
|
||||||
|
_REG_OPENED_EXISTING_KEY = 2
|
||||||
|
|
||||||
|
_ERROR_NO_MORE_ITEMS syscall.Errno = 259
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadRegLoadMUIString() error {
|
||||||
|
return procRegLoadMUIStringW.Find()
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) = advapi32.RegCreateKeyExW
|
||||||
|
//sys regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) = advapi32.RegDeleteKeyW
|
||||||
|
//sys regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) = advapi32.RegSetValueExW
|
||||||
|
//sys regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegEnumValueW
|
||||||
|
//sys regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) = advapi32.RegDeleteValueW
|
||||||
|
//sys regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) = advapi32.RegLoadMUIStringW
|
||||||
|
//sys regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) = advapi32.RegConnectRegistryW
|
||||||
|
|
||||||
|
//sys expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) = kernel32.ExpandEnvironmentStringsW
|
|
@ -0,0 +1,387 @@
|
||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package registry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"syscall"
|
||||||
|
"unicode/utf16"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Registry value types.
|
||||||
|
NONE = 0
|
||||||
|
SZ = 1
|
||||||
|
EXPAND_SZ = 2
|
||||||
|
BINARY = 3
|
||||||
|
DWORD = 4
|
||||||
|
DWORD_BIG_ENDIAN = 5
|
||||||
|
LINK = 6
|
||||||
|
MULTI_SZ = 7
|
||||||
|
RESOURCE_LIST = 8
|
||||||
|
FULL_RESOURCE_DESCRIPTOR = 9
|
||||||
|
RESOURCE_REQUIREMENTS_LIST = 10
|
||||||
|
QWORD = 11
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrShortBuffer is returned when the buffer was too short for the operation.
|
||||||
|
ErrShortBuffer = syscall.ERROR_MORE_DATA
|
||||||
|
|
||||||
|
// ErrNotExist is returned when a registry key or value does not exist.
|
||||||
|
ErrNotExist = syscall.ERROR_FILE_NOT_FOUND
|
||||||
|
|
||||||
|
// ErrUnexpectedType is returned by Get*Value when the value's type was unexpected.
|
||||||
|
ErrUnexpectedType = errors.New("unexpected key value type")
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetValue retrieves the type and data for the specified value associated
|
||||||
|
// with an open key k. It fills up buffer buf and returns the retrieved
|
||||||
|
// byte count n. If buf is too small to fit the stored value it returns
|
||||||
|
// ErrShortBuffer error along with the required buffer size n.
|
||||||
|
// If no buffer is provided, it returns true and actual buffer size n.
|
||||||
|
// If no buffer is provided, GetValue returns the value's type only.
|
||||||
|
// If the value does not exist, the error returned is ErrNotExist.
|
||||||
|
//
|
||||||
|
// GetValue is a low level function. If value's type is known, use the appropriate
|
||||||
|
// Get*Value function instead.
|
||||||
|
func (k Key) GetValue(name string, buf []byte) (n int, valtype uint32, err error) {
|
||||||
|
pname, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
var pbuf *byte
|
||||||
|
if len(buf) > 0 {
|
||||||
|
pbuf = (*byte)(unsafe.Pointer(&buf[0]))
|
||||||
|
}
|
||||||
|
l := uint32(len(buf))
|
||||||
|
err = syscall.RegQueryValueEx(syscall.Handle(k), pname, nil, &valtype, pbuf, &l)
|
||||||
|
if err != nil {
|
||||||
|
return int(l), valtype, err
|
||||||
|
}
|
||||||
|
return int(l), valtype, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Key) getValue(name string, buf []byte) (data []byte, valtype uint32, err error) {
|
||||||
|
p, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
var t uint32
|
||||||
|
n := uint32(len(buf))
|
||||||
|
for {
|
||||||
|
err = syscall.RegQueryValueEx(syscall.Handle(k), p, nil, &t, (*byte)(unsafe.Pointer(&buf[0])), &n)
|
||||||
|
if err == nil {
|
||||||
|
return buf[:n], t, nil
|
||||||
|
}
|
||||||
|
if err != syscall.ERROR_MORE_DATA {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if n <= uint32(len(buf)) {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
buf = make([]byte, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringValue retrieves the string value for the specified
|
||||||
|
// value name associated with an open key k. It also returns the value's type.
|
||||||
|
// If value does not exist, GetStringValue returns ErrNotExist.
|
||||||
|
// If value is not SZ or EXPAND_SZ, it will return the correct value
|
||||||
|
// type and ErrUnexpectedType.
|
||||||
|
func (k Key) GetStringValue(name string) (val string, valtype uint32, err error) {
|
||||||
|
data, typ, err2 := k.getValue(name, make([]byte, 64))
|
||||||
|
if err2 != nil {
|
||||||
|
return "", typ, err2
|
||||||
|
}
|
||||||
|
switch typ {
|
||||||
|
case SZ, EXPAND_SZ:
|
||||||
|
default:
|
||||||
|
return "", typ, ErrUnexpectedType
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
return "", typ, nil
|
||||||
|
}
|
||||||
|
u := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:]
|
||||||
|
return syscall.UTF16ToString(u), typ, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMUIStringValue retrieves the localized string value for
|
||||||
|
// the specified value name associated with an open key k.
|
||||||
|
// If the value name doesn't exist or the localized string value
|
||||||
|
// can't be resolved, GetMUIStringValue returns ErrNotExist.
|
||||||
|
// GetMUIStringValue panics if the system doesn't support
|
||||||
|
// regLoadMUIString; use LoadRegLoadMUIString to check if
|
||||||
|
// regLoadMUIString is supported before calling this function.
|
||||||
|
func (k Key) GetMUIStringValue(name string) (string, error) {
|
||||||
|
pname, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]uint16, 1024)
|
||||||
|
var buflen uint32
|
||||||
|
var pdir *uint16
|
||||||
|
|
||||||
|
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||||
|
if err == syscall.ERROR_FILE_NOT_FOUND { // Try fallback path
|
||||||
|
|
||||||
|
// Try to resolve the string value using the system directory as
|
||||||
|
// a DLL search path; this assumes the string value is of the form
|
||||||
|
// @[path]\dllname,-strID but with no path given, e.g. @tzres.dll,-320.
|
||||||
|
|
||||||
|
// This approach works with tzres.dll but may have to be revised
|
||||||
|
// in the future to allow callers to provide custom search paths.
|
||||||
|
|
||||||
|
var s string
|
||||||
|
s, err = ExpandString("%SystemRoot%\\system32\\")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
pdir, err = syscall.UTF16PtrFromString(s)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
for err == syscall.ERROR_MORE_DATA { // Grow buffer if needed
|
||||||
|
if buflen <= uint32(len(buf)) {
|
||||||
|
break // Buffer not growing, assume race; break
|
||||||
|
}
|
||||||
|
buf = make([]uint16, buflen)
|
||||||
|
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return syscall.UTF16ToString(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpandString expands environment-variable strings and replaces
|
||||||
|
// them with the values defined for the current user.
|
||||||
|
// Use ExpandString to expand EXPAND_SZ strings.
|
||||||
|
func ExpandString(value string) (string, error) {
|
||||||
|
if value == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
p, err := syscall.UTF16PtrFromString(value)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
r := make([]uint16, 100)
|
||||||
|
for {
|
||||||
|
n, err := expandEnvironmentStrings(p, &r[0], uint32(len(r)))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if n <= uint32(len(r)) {
|
||||||
|
u := (*[1 << 29]uint16)(unsafe.Pointer(&r[0]))[:]
|
||||||
|
return syscall.UTF16ToString(u), nil
|
||||||
|
}
|
||||||
|
r = make([]uint16, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringsValue retrieves the []string value for the specified
|
||||||
|
// value name associated with an open key k. It also returns the value's type.
|
||||||
|
// If value does not exist, GetStringsValue returns ErrNotExist.
|
||||||
|
// If value is not MULTI_SZ, it will return the correct value
|
||||||
|
// type and ErrUnexpectedType.
|
||||||
|
func (k Key) GetStringsValue(name string) (val []string, valtype uint32, err error) {
|
||||||
|
data, typ, err2 := k.getValue(name, make([]byte, 64))
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, typ, err2
|
||||||
|
}
|
||||||
|
if typ != MULTI_SZ {
|
||||||
|
return nil, typ, ErrUnexpectedType
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
return nil, typ, nil
|
||||||
|
}
|
||||||
|
p := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:len(data)/2]
|
||||||
|
if len(p) == 0 {
|
||||||
|
return nil, typ, nil
|
||||||
|
}
|
||||||
|
if p[len(p)-1] == 0 {
|
||||||
|
p = p[:len(p)-1] // remove terminating null
|
||||||
|
}
|
||||||
|
val = make([]string, 0, 5)
|
||||||
|
from := 0
|
||||||
|
for i, c := range p {
|
||||||
|
if c == 0 {
|
||||||
|
val = append(val, string(utf16.Decode(p[from:i])))
|
||||||
|
from = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val, typ, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIntegerValue retrieves the integer value for the specified
|
||||||
|
// value name associated with an open key k. It also returns the value's type.
|
||||||
|
// If value does not exist, GetIntegerValue returns ErrNotExist.
|
||||||
|
// If value is not DWORD or QWORD, it will return the correct value
|
||||||
|
// type and ErrUnexpectedType.
|
||||||
|
func (k Key) GetIntegerValue(name string) (val uint64, valtype uint32, err error) {
|
||||||
|
data, typ, err2 := k.getValue(name, make([]byte, 8))
|
||||||
|
if err2 != nil {
|
||||||
|
return 0, typ, err2
|
||||||
|
}
|
||||||
|
switch typ {
|
||||||
|
case DWORD:
|
||||||
|
if len(data) != 4 {
|
||||||
|
return 0, typ, errors.New("DWORD value is not 4 bytes long")
|
||||||
|
}
|
||||||
|
var val32 uint32
|
||||||
|
copy((*[4]byte)(unsafe.Pointer(&val32))[:], data)
|
||||||
|
return uint64(val32), DWORD, nil
|
||||||
|
case QWORD:
|
||||||
|
if len(data) != 8 {
|
||||||
|
return 0, typ, errors.New("QWORD value is not 8 bytes long")
|
||||||
|
}
|
||||||
|
copy((*[8]byte)(unsafe.Pointer(&val))[:], data)
|
||||||
|
return val, QWORD, nil
|
||||||
|
default:
|
||||||
|
return 0, typ, ErrUnexpectedType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBinaryValue retrieves the binary value for the specified
|
||||||
|
// value name associated with an open key k. It also returns the value's type.
|
||||||
|
// If value does not exist, GetBinaryValue returns ErrNotExist.
|
||||||
|
// If value is not BINARY, it will return the correct value
|
||||||
|
// type and ErrUnexpectedType.
|
||||||
|
func (k Key) GetBinaryValue(name string) (val []byte, valtype uint32, err error) {
|
||||||
|
data, typ, err2 := k.getValue(name, make([]byte, 64))
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, typ, err2
|
||||||
|
}
|
||||||
|
if typ != BINARY {
|
||||||
|
return nil, typ, ErrUnexpectedType
|
||||||
|
}
|
||||||
|
return data, typ, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Key) setValue(name string, valtype uint32, data []byte) error {
|
||||||
|
p, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
return regSetValueEx(syscall.Handle(k), p, 0, valtype, nil, 0)
|
||||||
|
}
|
||||||
|
return regSetValueEx(syscall.Handle(k), p, 0, valtype, &data[0], uint32(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDWordValue sets the data and type of a name value
|
||||||
|
// under key k to value and DWORD.
|
||||||
|
func (k Key) SetDWordValue(name string, value uint32) error {
|
||||||
|
return k.setValue(name, DWORD, (*[4]byte)(unsafe.Pointer(&value))[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetQWordValue sets the data and type of a name value
|
||||||
|
// under key k to value and QWORD.
|
||||||
|
func (k Key) SetQWordValue(name string, value uint64) error {
|
||||||
|
return k.setValue(name, QWORD, (*[8]byte)(unsafe.Pointer(&value))[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Key) setStringValue(name string, valtype uint32, value string) error {
|
||||||
|
v, err := syscall.UTF16FromString(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||||
|
return k.setValue(name, valtype, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStringValue sets the data and type of a name value
|
||||||
|
// under key k to value and SZ. The value must not contain a zero byte.
|
||||||
|
func (k Key) SetStringValue(name, value string) error {
|
||||||
|
return k.setStringValue(name, SZ, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExpandStringValue sets the data and type of a name value
|
||||||
|
// under key k to value and EXPAND_SZ. The value must not contain a zero byte.
|
||||||
|
func (k Key) SetExpandStringValue(name, value string) error {
|
||||||
|
return k.setStringValue(name, EXPAND_SZ, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStringsValue sets the data and type of a name value
|
||||||
|
// under key k to value and MULTI_SZ. The value strings
|
||||||
|
// must not contain a zero byte.
|
||||||
|
func (k Key) SetStringsValue(name string, value []string) error {
|
||||||
|
ss := ""
|
||||||
|
for _, s := range value {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] == 0 {
|
||||||
|
return errors.New("string cannot have 0 inside")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss += s + "\x00"
|
||||||
|
}
|
||||||
|
v := utf16.Encode([]rune(ss + "\x00"))
|
||||||
|
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||||
|
return k.setValue(name, MULTI_SZ, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBinaryValue sets the data and type of a name value
|
||||||
|
// under key k to value and BINARY.
|
||||||
|
func (k Key) SetBinaryValue(name string, value []byte) error {
|
||||||
|
return k.setValue(name, BINARY, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteValue removes a named value from the key k.
|
||||||
|
func (k Key) DeleteValue(name string) error {
|
||||||
|
return regDeleteValue(syscall.Handle(k), syscall.StringToUTF16Ptr(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadValueNames returns the value names of key k.
|
||||||
|
// The parameter n controls the number of returned names,
|
||||||
|
// analogous to the way os.File.Readdirnames works.
|
||||||
|
func (k Key) ReadValueNames(n int) ([]string, error) {
|
||||||
|
ki, err := k.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
names := make([]string, 0, ki.ValueCount)
|
||||||
|
buf := make([]uint16, ki.MaxValueNameLen+1) // extra room for terminating null character
|
||||||
|
loopItems:
|
||||||
|
for i := uint32(0); ; i++ {
|
||||||
|
if n > 0 {
|
||||||
|
if len(names) == n {
|
||||||
|
return names, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l := uint32(len(buf))
|
||||||
|
for {
|
||||||
|
err := regEnumValue(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err == syscall.ERROR_MORE_DATA {
|
||||||
|
// Double buffer size and try again.
|
||||||
|
l = uint32(2 * len(buf))
|
||||||
|
buf = make([]uint16, l)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err == _ERROR_NO_MORE_ITEMS {
|
||||||
|
break loopItems
|
||||||
|
}
|
||||||
|
return names, err
|
||||||
|
}
|
||||||
|
names = append(names, syscall.UTF16ToString(buf[:l]))
|
||||||
|
}
|
||||||
|
if n > len(names) {
|
||||||
|
return names, io.EOF
|
||||||
|
}
|
||||||
|
return names, nil
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
// Code generated by 'go generate'; DO NOT EDIT.
|
||||||
|
|
||||||
|
package registry
|
||||||
|
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent
|
||||||
|
// allocations at runtime.
|
||||||
|
func errnoErr(e syscall.Errno) error {
|
||||||
|
switch e {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
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 (
|
||||||
|
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||||
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
|
|
||||||
|
procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW")
|
||||||
|
procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW")
|
||||||
|
procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
|
||||||
|
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
||||||
|
procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW")
|
||||||
|
procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW")
|
||||||
|
procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW")
|
||||||
|
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
|
||||||
|
)
|
||||||
|
|
||||||
|
func regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall9(procRegCreateKeyExW.Addr(), 9, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desired), uintptr(unsafe.Pointer(sa)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition)))
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall(procRegDeleteKeyW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(subkey)), 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize))
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall9(procRegEnumValueW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen)), 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall(procRegConnectRegistryW.Addr(), 3, uintptr(unsafe.Pointer(machinename)), uintptr(key), uintptr(unsafe.Pointer(result)))
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size))
|
||||||
|
n = uint32(r0)
|
||||||
|
if n == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,854 @@
|
||||||
|
// Copyright 2012 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.
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
STANDARD_RIGHTS_REQUIRED = 0xf0000
|
||||||
|
STANDARD_RIGHTS_READ = 0x20000
|
||||||
|
STANDARD_RIGHTS_WRITE = 0x20000
|
||||||
|
STANDARD_RIGHTS_EXECUTE = 0x20000
|
||||||
|
STANDARD_RIGHTS_ALL = 0x1F0000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NameUnknown = 0
|
||||||
|
NameFullyQualifiedDN = 1
|
||||||
|
NameSamCompatible = 2
|
||||||
|
NameDisplay = 3
|
||||||
|
NameUniqueId = 6
|
||||||
|
NameCanonical = 7
|
||||||
|
NameUserPrincipal = 8
|
||||||
|
NameCanonicalEx = 9
|
||||||
|
NameServicePrincipal = 10
|
||||||
|
NameDnsDomain = 12
|
||||||
|
)
|
||||||
|
|
||||||
|
// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
|
||||||
|
// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
|
||||||
|
//sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
|
||||||
|
//sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
|
||||||
|
|
||||||
|
// TranslateAccountName converts a directory service
|
||||||
|
// object name from one format to another.
|
||||||
|
func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
|
||||||
|
u, e := UTF16PtrFromString(username)
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
n := uint32(50)
|
||||||
|
for {
|
||||||
|
b := make([]uint16, n)
|
||||||
|
e = TranslateName(u, from, to, &b[0], &n)
|
||||||
|
if e == nil {
|
||||||
|
return UTF16ToString(b[:n]), nil
|
||||||
|
}
|
||||||
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
if n <= uint32(len(b)) {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// do not reorder
|
||||||
|
NetSetupUnknownStatus = iota
|
||||||
|
NetSetupUnjoined
|
||||||
|
NetSetupWorkgroupName
|
||||||
|
NetSetupDomainName
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserInfo10 struct {
|
||||||
|
Name *uint16
|
||||||
|
Comment *uint16
|
||||||
|
UsrComment *uint16
|
||||||
|
FullName *uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
|
||||||
|
//sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
|
||||||
|
//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
|
||||||
|
|
||||||
|
const (
|
||||||
|
// do not reorder
|
||||||
|
SidTypeUser = 1 + iota
|
||||||
|
SidTypeGroup
|
||||||
|
SidTypeDomain
|
||||||
|
SidTypeAlias
|
||||||
|
SidTypeWellKnownGroup
|
||||||
|
SidTypeDeletedAccount
|
||||||
|
SidTypeInvalid
|
||||||
|
SidTypeUnknown
|
||||||
|
SidTypeComputer
|
||||||
|
SidTypeLabel
|
||||||
|
)
|
||||||
|
|
||||||
|
type SidIdentifierAuthority struct {
|
||||||
|
Value [6]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
SECURITY_NULL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
|
||||||
|
SECURITY_WORLD_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
|
||||||
|
SECURITY_LOCAL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
|
||||||
|
SECURITY_CREATOR_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
|
||||||
|
SECURITY_NON_UNIQUE_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
|
||||||
|
SECURITY_NT_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
|
||||||
|
SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SECURITY_NULL_RID = 0
|
||||||
|
SECURITY_WORLD_RID = 0
|
||||||
|
SECURITY_LOCAL_RID = 0
|
||||||
|
SECURITY_CREATOR_OWNER_RID = 0
|
||||||
|
SECURITY_CREATOR_GROUP_RID = 1
|
||||||
|
SECURITY_DIALUP_RID = 1
|
||||||
|
SECURITY_NETWORK_RID = 2
|
||||||
|
SECURITY_BATCH_RID = 3
|
||||||
|
SECURITY_INTERACTIVE_RID = 4
|
||||||
|
SECURITY_LOGON_IDS_RID = 5
|
||||||
|
SECURITY_SERVICE_RID = 6
|
||||||
|
SECURITY_LOCAL_SYSTEM_RID = 18
|
||||||
|
SECURITY_BUILTIN_DOMAIN_RID = 32
|
||||||
|
SECURITY_PRINCIPAL_SELF_RID = 10
|
||||||
|
SECURITY_CREATOR_OWNER_SERVER_RID = 0x2
|
||||||
|
SECURITY_CREATOR_GROUP_SERVER_RID = 0x3
|
||||||
|
SECURITY_LOGON_IDS_RID_COUNT = 0x3
|
||||||
|
SECURITY_ANONYMOUS_LOGON_RID = 0x7
|
||||||
|
SECURITY_PROXY_RID = 0x8
|
||||||
|
SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
|
||||||
|
SECURITY_SERVER_LOGON_RID = SECURITY_ENTERPRISE_CONTROLLERS_RID
|
||||||
|
SECURITY_AUTHENTICATED_USER_RID = 0xb
|
||||||
|
SECURITY_RESTRICTED_CODE_RID = 0xc
|
||||||
|
SECURITY_NT_NON_UNIQUE_RID = 0x15
|
||||||
|
)
|
||||||
|
|
||||||
|
// Predefined domain-relative RIDs for local groups.
|
||||||
|
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
|
||||||
|
const (
|
||||||
|
DOMAIN_ALIAS_RID_ADMINS = 0x220
|
||||||
|
DOMAIN_ALIAS_RID_USERS = 0x221
|
||||||
|
DOMAIN_ALIAS_RID_GUESTS = 0x222
|
||||||
|
DOMAIN_ALIAS_RID_POWER_USERS = 0x223
|
||||||
|
DOMAIN_ALIAS_RID_ACCOUNT_OPS = 0x224
|
||||||
|
DOMAIN_ALIAS_RID_SYSTEM_OPS = 0x225
|
||||||
|
DOMAIN_ALIAS_RID_PRINT_OPS = 0x226
|
||||||
|
DOMAIN_ALIAS_RID_BACKUP_OPS = 0x227
|
||||||
|
DOMAIN_ALIAS_RID_REPLICATOR = 0x228
|
||||||
|
DOMAIN_ALIAS_RID_RAS_SERVERS = 0x229
|
||||||
|
DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 0x22a
|
||||||
|
DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS = 0x22b
|
||||||
|
DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS = 0x22c
|
||||||
|
DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
|
||||||
|
DOMAIN_ALIAS_RID_MONITORING_USERS = 0x22e
|
||||||
|
DOMAIN_ALIAS_RID_LOGGING_USERS = 0x22f
|
||||||
|
DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS = 0x230
|
||||||
|
DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS = 0x231
|
||||||
|
DOMAIN_ALIAS_RID_DCOM_USERS = 0x232
|
||||||
|
DOMAIN_ALIAS_RID_IUSERS = 0x238
|
||||||
|
DOMAIN_ALIAS_RID_CRYPTO_OPERATORS = 0x239
|
||||||
|
DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP = 0x23b
|
||||||
|
DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c
|
||||||
|
DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP = 0x23d
|
||||||
|
DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP = 0x23e
|
||||||
|
)
|
||||||
|
|
||||||
|
//sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
|
||||||
|
//sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
|
||||||
|
//sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
|
||||||
|
//sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
|
||||||
|
//sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
|
||||||
|
//sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
|
||||||
|
//sys AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) = advapi32.AllocateAndInitializeSid
|
||||||
|
//sys createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) = advapi32.CreateWellKnownSid
|
||||||
|
//sys isWellKnownSid(sid *SID, sidType WELL_KNOWN_SID_TYPE) (isWellKnown bool) = advapi32.IsWellKnownSid
|
||||||
|
//sys FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
|
||||||
|
//sys EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
|
||||||
|
//sys getSidIdentifierAuthority(sid *SID) (authority *SidIdentifierAuthority) = advapi32.GetSidIdentifierAuthority
|
||||||
|
//sys getSidSubAuthorityCount(sid *SID) (count *uint8) = advapi32.GetSidSubAuthorityCount
|
||||||
|
//sys getSidSubAuthority(sid *SID, index uint32) (subAuthority *uint32) = advapi32.GetSidSubAuthority
|
||||||
|
//sys isValidSid(sid *SID) (isValid bool) = advapi32.IsValidSid
|
||||||
|
|
||||||
|
// The security identifier (SID) structure is a variable-length
|
||||||
|
// structure used to uniquely identify users or groups.
|
||||||
|
type SID struct{}
|
||||||
|
|
||||||
|
// StringToSid converts a string-format security identifier
|
||||||
|
// SID into a valid, functional SID.
|
||||||
|
func StringToSid(s string) (*SID, error) {
|
||||||
|
var sid *SID
|
||||||
|
p, e := UTF16PtrFromString(s)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
e = ConvertStringSidToSid(p, &sid)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
defer LocalFree((Handle)(unsafe.Pointer(sid)))
|
||||||
|
return sid.Copy()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupSID retrieves a security identifier SID for the account
|
||||||
|
// and the name of the domain on which the account was found.
|
||||||
|
// System specify target computer to search.
|
||||||
|
func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
|
||||||
|
if len(account) == 0 {
|
||||||
|
return nil, "", 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
acc, e := UTF16PtrFromString(account)
|
||||||
|
if e != nil {
|
||||||
|
return nil, "", 0, e
|
||||||
|
}
|
||||||
|
var sys *uint16
|
||||||
|
if len(system) > 0 {
|
||||||
|
sys, e = UTF16PtrFromString(system)
|
||||||
|
if e != nil {
|
||||||
|
return nil, "", 0, e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n := uint32(50)
|
||||||
|
dn := uint32(50)
|
||||||
|
for {
|
||||||
|
b := make([]byte, n)
|
||||||
|
db := make([]uint16, dn)
|
||||||
|
sid = (*SID)(unsafe.Pointer(&b[0]))
|
||||||
|
e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
|
||||||
|
if e == nil {
|
||||||
|
return sid, UTF16ToString(db), accType, nil
|
||||||
|
}
|
||||||
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||||
|
return nil, "", 0, e
|
||||||
|
}
|
||||||
|
if n <= uint32(len(b)) {
|
||||||
|
return nil, "", 0, e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String converts SID to a string format
|
||||||
|
// suitable for display, storage, or transmission.
|
||||||
|
func (sid *SID) String() (string, error) {
|
||||||
|
var s *uint16
|
||||||
|
e := ConvertSidToStringSid(sid, &s)
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
defer LocalFree((Handle)(unsafe.Pointer(s)))
|
||||||
|
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the length, in bytes, of a valid security identifier SID.
|
||||||
|
func (sid *SID) Len() int {
|
||||||
|
return int(GetLengthSid(sid))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy creates a duplicate of security identifier SID.
|
||||||
|
func (sid *SID) Copy() (*SID, error) {
|
||||||
|
b := make([]byte, sid.Len())
|
||||||
|
sid2 := (*SID)(unsafe.Pointer(&b[0]))
|
||||||
|
e := CopySid(uint32(len(b)), sid2, sid)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return sid2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IdentifierAuthority returns the identifier authority of the SID.
|
||||||
|
func (sid *SID) IdentifierAuthority() SidIdentifierAuthority {
|
||||||
|
return *getSidIdentifierAuthority(sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubAuthorityCount returns the number of sub-authorities in the SID.
|
||||||
|
func (sid *SID) SubAuthorityCount() uint8 {
|
||||||
|
return *getSidSubAuthorityCount(sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubAuthority returns the sub-authority of the SID as specified by
|
||||||
|
// the index, which must be less than sid.SubAuthorityCount().
|
||||||
|
func (sid *SID) SubAuthority(idx uint32) uint32 {
|
||||||
|
if idx >= uint32(sid.SubAuthorityCount()) {
|
||||||
|
panic("sub-authority index out of range")
|
||||||
|
}
|
||||||
|
return *getSidSubAuthority(sid, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid returns whether the SID has a valid revision and length.
|
||||||
|
func (sid *SID) IsValid() bool {
|
||||||
|
return isValidSid(sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equals compares two SIDs for equality.
|
||||||
|
func (sid *SID) Equals(sid2 *SID) bool {
|
||||||
|
return EqualSid(sid, sid2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsWellKnown determines whether the SID matches the well-known sidType.
|
||||||
|
func (sid *SID) IsWellKnown(sidType WELL_KNOWN_SID_TYPE) bool {
|
||||||
|
return isWellKnownSid(sid, sidType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupAccount retrieves the name of the account for this SID
|
||||||
|
// and the name of the first domain on which this SID is found.
|
||||||
|
// System specify target computer to search for.
|
||||||
|
func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
|
||||||
|
var sys *uint16
|
||||||
|
if len(system) > 0 {
|
||||||
|
sys, err = UTF16PtrFromString(system)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n := uint32(50)
|
||||||
|
dn := uint32(50)
|
||||||
|
for {
|
||||||
|
b := make([]uint16, n)
|
||||||
|
db := make([]uint16, dn)
|
||||||
|
e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
|
||||||
|
if e == nil {
|
||||||
|
return UTF16ToString(b), UTF16ToString(db), accType, nil
|
||||||
|
}
|
||||||
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||||
|
return "", "", 0, e
|
||||||
|
}
|
||||||
|
if n <= uint32(len(b)) {
|
||||||
|
return "", "", 0, e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Various types of pre-specified SIDs that can be synthesized and compared at runtime.
|
||||||
|
type WELL_KNOWN_SID_TYPE uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
WinNullSid = 0
|
||||||
|
WinWorldSid = 1
|
||||||
|
WinLocalSid = 2
|
||||||
|
WinCreatorOwnerSid = 3
|
||||||
|
WinCreatorGroupSid = 4
|
||||||
|
WinCreatorOwnerServerSid = 5
|
||||||
|
WinCreatorGroupServerSid = 6
|
||||||
|
WinNtAuthoritySid = 7
|
||||||
|
WinDialupSid = 8
|
||||||
|
WinNetworkSid = 9
|
||||||
|
WinBatchSid = 10
|
||||||
|
WinInteractiveSid = 11
|
||||||
|
WinServiceSid = 12
|
||||||
|
WinAnonymousSid = 13
|
||||||
|
WinProxySid = 14
|
||||||
|
WinEnterpriseControllersSid = 15
|
||||||
|
WinSelfSid = 16
|
||||||
|
WinAuthenticatedUserSid = 17
|
||||||
|
WinRestrictedCodeSid = 18
|
||||||
|
WinTerminalServerSid = 19
|
||||||
|
WinRemoteLogonIdSid = 20
|
||||||
|
WinLogonIdsSid = 21
|
||||||
|
WinLocalSystemSid = 22
|
||||||
|
WinLocalServiceSid = 23
|
||||||
|
WinNetworkServiceSid = 24
|
||||||
|
WinBuiltinDomainSid = 25
|
||||||
|
WinBuiltinAdministratorsSid = 26
|
||||||
|
WinBuiltinUsersSid = 27
|
||||||
|
WinBuiltinGuestsSid = 28
|
||||||
|
WinBuiltinPowerUsersSid = 29
|
||||||
|
WinBuiltinAccountOperatorsSid = 30
|
||||||
|
WinBuiltinSystemOperatorsSid = 31
|
||||||
|
WinBuiltinPrintOperatorsSid = 32
|
||||||
|
WinBuiltinBackupOperatorsSid = 33
|
||||||
|
WinBuiltinReplicatorSid = 34
|
||||||
|
WinBuiltinPreWindows2000CompatibleAccessSid = 35
|
||||||
|
WinBuiltinRemoteDesktopUsersSid = 36
|
||||||
|
WinBuiltinNetworkConfigurationOperatorsSid = 37
|
||||||
|
WinAccountAdministratorSid = 38
|
||||||
|
WinAccountGuestSid = 39
|
||||||
|
WinAccountKrbtgtSid = 40
|
||||||
|
WinAccountDomainAdminsSid = 41
|
||||||
|
WinAccountDomainUsersSid = 42
|
||||||
|
WinAccountDomainGuestsSid = 43
|
||||||
|
WinAccountComputersSid = 44
|
||||||
|
WinAccountControllersSid = 45
|
||||||
|
WinAccountCertAdminsSid = 46
|
||||||
|
WinAccountSchemaAdminsSid = 47
|
||||||
|
WinAccountEnterpriseAdminsSid = 48
|
||||||
|
WinAccountPolicyAdminsSid = 49
|
||||||
|
WinAccountRasAndIasServersSid = 50
|
||||||
|
WinNTLMAuthenticationSid = 51
|
||||||
|
WinDigestAuthenticationSid = 52
|
||||||
|
WinSChannelAuthenticationSid = 53
|
||||||
|
WinThisOrganizationSid = 54
|
||||||
|
WinOtherOrganizationSid = 55
|
||||||
|
WinBuiltinIncomingForestTrustBuildersSid = 56
|
||||||
|
WinBuiltinPerfMonitoringUsersSid = 57
|
||||||
|
WinBuiltinPerfLoggingUsersSid = 58
|
||||||
|
WinBuiltinAuthorizationAccessSid = 59
|
||||||
|
WinBuiltinTerminalServerLicenseServersSid = 60
|
||||||
|
WinBuiltinDCOMUsersSid = 61
|
||||||
|
WinBuiltinIUsersSid = 62
|
||||||
|
WinIUserSid = 63
|
||||||
|
WinBuiltinCryptoOperatorsSid = 64
|
||||||
|
WinUntrustedLabelSid = 65
|
||||||
|
WinLowLabelSid = 66
|
||||||
|
WinMediumLabelSid = 67
|
||||||
|
WinHighLabelSid = 68
|
||||||
|
WinSystemLabelSid = 69
|
||||||
|
WinWriteRestrictedCodeSid = 70
|
||||||
|
WinCreatorOwnerRightsSid = 71
|
||||||
|
WinCacheablePrincipalsGroupSid = 72
|
||||||
|
WinNonCacheablePrincipalsGroupSid = 73
|
||||||
|
WinEnterpriseReadonlyControllersSid = 74
|
||||||
|
WinAccountReadonlyControllersSid = 75
|
||||||
|
WinBuiltinEventLogReadersGroup = 76
|
||||||
|
WinNewEnterpriseReadonlyControllersSid = 77
|
||||||
|
WinBuiltinCertSvcDComAccessGroup = 78
|
||||||
|
WinMediumPlusLabelSid = 79
|
||||||
|
WinLocalLogonSid = 80
|
||||||
|
WinConsoleLogonSid = 81
|
||||||
|
WinThisOrganizationCertificateSid = 82
|
||||||
|
WinApplicationPackageAuthoritySid = 83
|
||||||
|
WinBuiltinAnyPackageSid = 84
|
||||||
|
WinCapabilityInternetClientSid = 85
|
||||||
|
WinCapabilityInternetClientServerSid = 86
|
||||||
|
WinCapabilityPrivateNetworkClientServerSid = 87
|
||||||
|
WinCapabilityPicturesLibrarySid = 88
|
||||||
|
WinCapabilityVideosLibrarySid = 89
|
||||||
|
WinCapabilityMusicLibrarySid = 90
|
||||||
|
WinCapabilityDocumentsLibrarySid = 91
|
||||||
|
WinCapabilitySharedUserCertificatesSid = 92
|
||||||
|
WinCapabilityEnterpriseAuthenticationSid = 93
|
||||||
|
WinCapabilityRemovableStorageSid = 94
|
||||||
|
WinBuiltinRDSRemoteAccessServersSid = 95
|
||||||
|
WinBuiltinRDSEndpointServersSid = 96
|
||||||
|
WinBuiltinRDSManagementServersSid = 97
|
||||||
|
WinUserModeDriversSid = 98
|
||||||
|
WinBuiltinHyperVAdminsSid = 99
|
||||||
|
WinAccountCloneableControllersSid = 100
|
||||||
|
WinBuiltinAccessControlAssistanceOperatorsSid = 101
|
||||||
|
WinBuiltinRemoteManagementUsersSid = 102
|
||||||
|
WinAuthenticationAuthorityAssertedSid = 103
|
||||||
|
WinAuthenticationServiceAssertedSid = 104
|
||||||
|
WinLocalAccountSid = 105
|
||||||
|
WinLocalAccountAndAdministratorSid = 106
|
||||||
|
WinAccountProtectedUsersSid = 107
|
||||||
|
WinCapabilityAppointmentsSid = 108
|
||||||
|
WinCapabilityContactsSid = 109
|
||||||
|
WinAccountDefaultSystemManagedSid = 110
|
||||||
|
WinBuiltinDefaultSystemManagedGroupSid = 111
|
||||||
|
WinBuiltinStorageReplicaAdminsSid = 112
|
||||||
|
WinAccountKeyAdminsSid = 113
|
||||||
|
WinAccountEnterpriseKeyAdminsSid = 114
|
||||||
|
WinAuthenticationKeyTrustSid = 115
|
||||||
|
WinAuthenticationKeyPropertyMFASid = 116
|
||||||
|
WinAuthenticationKeyPropertyAttestationSid = 117
|
||||||
|
WinAuthenticationFreshKeyAuthSid = 118
|
||||||
|
WinBuiltinDeviceOwnersSid = 119
|
||||||
|
)
|
||||||
|
|
||||||
|
// Creates a SID for a well-known predefined alias, generally using the constants of the form
|
||||||
|
// Win*Sid, for the local machine.
|
||||||
|
func CreateWellKnownSid(sidType WELL_KNOWN_SID_TYPE) (*SID, error) {
|
||||||
|
return CreateWellKnownDomainSid(sidType, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a SID for a well-known predefined alias, generally using the constants of the form
|
||||||
|
// Win*Sid, for the domain specified by the domainSid parameter.
|
||||||
|
func CreateWellKnownDomainSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID) (*SID, error) {
|
||||||
|
n := uint32(50)
|
||||||
|
for {
|
||||||
|
b := make([]byte, n)
|
||||||
|
sid := (*SID)(unsafe.Pointer(&b[0]))
|
||||||
|
err := createWellKnownSid(sidType, domainSid, sid, &n)
|
||||||
|
if err == nil {
|
||||||
|
return sid, nil
|
||||||
|
}
|
||||||
|
if err != ERROR_INSUFFICIENT_BUFFER {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if n <= uint32(len(b)) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// do not reorder
|
||||||
|
TOKEN_ASSIGN_PRIMARY = 1 << iota
|
||||||
|
TOKEN_DUPLICATE
|
||||||
|
TOKEN_IMPERSONATE
|
||||||
|
TOKEN_QUERY
|
||||||
|
TOKEN_QUERY_SOURCE
|
||||||
|
TOKEN_ADJUST_PRIVILEGES
|
||||||
|
TOKEN_ADJUST_GROUPS
|
||||||
|
TOKEN_ADJUST_DEFAULT
|
||||||
|
TOKEN_ADJUST_SESSIONID
|
||||||
|
|
||||||
|
TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
|
||||||
|
TOKEN_ASSIGN_PRIMARY |
|
||||||
|
TOKEN_DUPLICATE |
|
||||||
|
TOKEN_IMPERSONATE |
|
||||||
|
TOKEN_QUERY |
|
||||||
|
TOKEN_QUERY_SOURCE |
|
||||||
|
TOKEN_ADJUST_PRIVILEGES |
|
||||||
|
TOKEN_ADJUST_GROUPS |
|
||||||
|
TOKEN_ADJUST_DEFAULT |
|
||||||
|
TOKEN_ADJUST_SESSIONID
|
||||||
|
TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
|
||||||
|
TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
|
||||||
|
TOKEN_ADJUST_PRIVILEGES |
|
||||||
|
TOKEN_ADJUST_GROUPS |
|
||||||
|
TOKEN_ADJUST_DEFAULT
|
||||||
|
TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// do not reorder
|
||||||
|
TokenUser = 1 + iota
|
||||||
|
TokenGroups
|
||||||
|
TokenPrivileges
|
||||||
|
TokenOwner
|
||||||
|
TokenPrimaryGroup
|
||||||
|
TokenDefaultDacl
|
||||||
|
TokenSource
|
||||||
|
TokenType
|
||||||
|
TokenImpersonationLevel
|
||||||
|
TokenStatistics
|
||||||
|
TokenRestrictedSids
|
||||||
|
TokenSessionId
|
||||||
|
TokenGroupsAndPrivileges
|
||||||
|
TokenSessionReference
|
||||||
|
TokenSandBoxInert
|
||||||
|
TokenAuditPolicy
|
||||||
|
TokenOrigin
|
||||||
|
TokenElevationType
|
||||||
|
TokenLinkedToken
|
||||||
|
TokenElevation
|
||||||
|
TokenHasRestrictions
|
||||||
|
TokenAccessInformation
|
||||||
|
TokenVirtualizationAllowed
|
||||||
|
TokenVirtualizationEnabled
|
||||||
|
TokenIntegrityLevel
|
||||||
|
TokenUIAccess
|
||||||
|
TokenMandatoryPolicy
|
||||||
|
TokenLogonSid
|
||||||
|
MaxTokenInfoClass
|
||||||
|
)
|
||||||
|
|
||||||
|
// Group attributes inside of Tokengroups.Groups[i].Attributes
|
||||||
|
const (
|
||||||
|
SE_GROUP_MANDATORY = 0x00000001
|
||||||
|
SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002
|
||||||
|
SE_GROUP_ENABLED = 0x00000004
|
||||||
|
SE_GROUP_OWNER = 0x00000008
|
||||||
|
SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010
|
||||||
|
SE_GROUP_INTEGRITY = 0x00000020
|
||||||
|
SE_GROUP_INTEGRITY_ENABLED = 0x00000040
|
||||||
|
SE_GROUP_LOGON_ID = 0xC0000000
|
||||||
|
SE_GROUP_RESOURCE = 0x20000000
|
||||||
|
SE_GROUP_VALID_ATTRIBUTES = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED | SE_GROUP_OWNER | SE_GROUP_USE_FOR_DENY_ONLY | SE_GROUP_LOGON_ID | SE_GROUP_RESOURCE | SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED
|
||||||
|
)
|
||||||
|
|
||||||
|
// Privilege attributes
|
||||||
|
const (
|
||||||
|
SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
|
||||||
|
SE_PRIVILEGE_ENABLED = 0x00000002
|
||||||
|
SE_PRIVILEGE_REMOVED = 0x00000004
|
||||||
|
SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000
|
||||||
|
SE_PRIVILEGE_VALID_ATTRIBUTES = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED | SE_PRIVILEGE_USED_FOR_ACCESS
|
||||||
|
)
|
||||||
|
|
||||||
|
// Token types
|
||||||
|
const (
|
||||||
|
TokenPrimary = 1
|
||||||
|
TokenImpersonation = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Impersonation levels
|
||||||
|
const (
|
||||||
|
SecurityAnonymous = 0
|
||||||
|
SecurityIdentification = 1
|
||||||
|
SecurityImpersonation = 2
|
||||||
|
SecurityDelegation = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type LUID struct {
|
||||||
|
LowPart uint32
|
||||||
|
HighPart int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type LUIDAndAttributes struct {
|
||||||
|
Luid LUID
|
||||||
|
Attributes uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type SIDAndAttributes struct {
|
||||||
|
Sid *SID
|
||||||
|
Attributes uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tokenuser struct {
|
||||||
|
User SIDAndAttributes
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tokenprimarygroup struct {
|
||||||
|
PrimaryGroup *SID
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tokengroups struct {
|
||||||
|
GroupCount uint32
|
||||||
|
Groups [1]SIDAndAttributes // Use AllGroups() for iterating.
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllGroups returns a slice that can be used to iterate over the groups in g.
|
||||||
|
func (g *Tokengroups) AllGroups() []SIDAndAttributes {
|
||||||
|
return (*[(1 << 28) - 1]SIDAndAttributes)(unsafe.Pointer(&g.Groups[0]))[:g.GroupCount:g.GroupCount]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tokenprivileges struct {
|
||||||
|
PrivilegeCount uint32
|
||||||
|
Privileges [1]LUIDAndAttributes // Use AllPrivileges() for iterating.
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllPrivileges returns a slice that can be used to iterate over the privileges in p.
|
||||||
|
func (p *Tokenprivileges) AllPrivileges() []LUIDAndAttributes {
|
||||||
|
return (*[(1 << 27) - 1]LUIDAndAttributes)(unsafe.Pointer(&p.Privileges[0]))[:p.PrivilegeCount:p.PrivilegeCount]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tokenmandatorylabel struct {
|
||||||
|
Label SIDAndAttributes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tml *Tokenmandatorylabel) Size() uint32 {
|
||||||
|
return uint32(unsafe.Sizeof(Tokenmandatorylabel{})) + GetLengthSid(tml.Label.Sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authorization Functions
|
||||||
|
//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
|
||||||
|
//sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
|
||||||
|
//sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
|
||||||
|
//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
|
||||||
|
//sys RevertToSelf() (err error) = advapi32.RevertToSelf
|
||||||
|
//sys SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken
|
||||||
|
//sys LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW
|
||||||
|
//sys AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) = advapi32.AdjustTokenPrivileges
|
||||||
|
//sys AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) = advapi32.AdjustTokenGroups
|
||||||
|
//sys GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
|
||||||
|
//sys SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) = advapi32.SetTokenInformation
|
||||||
|
//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
|
||||||
|
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
||||||
|
//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
|
||||||
|
|
||||||
|
// An access token contains the security information for a logon session.
|
||||||
|
// The system creates an access token when a user logs on, and every
|
||||||
|
// process executed on behalf of the user has a copy of the token.
|
||||||
|
// The token identifies the user, the user's groups, and the user's
|
||||||
|
// privileges. The system uses the token to control access to securable
|
||||||
|
// objects and to control the ability of the user to perform various
|
||||||
|
// system-related operations on the local computer.
|
||||||
|
type Token Handle
|
||||||
|
|
||||||
|
// OpenCurrentProcessToken opens the access token
|
||||||
|
// associated with current process. It is a real
|
||||||
|
// token that needs to be closed, unlike
|
||||||
|
// GetCurrentProcessToken.
|
||||||
|
func OpenCurrentProcessToken() (Token, error) {
|
||||||
|
p, e := GetCurrentProcess()
|
||||||
|
if e != nil {
|
||||||
|
return 0, e
|
||||||
|
}
|
||||||
|
var t Token
|
||||||
|
e = OpenProcessToken(p, TOKEN_QUERY, &t)
|
||||||
|
if e != nil {
|
||||||
|
return 0, e
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCurrentProcessToken returns the access token associated with
|
||||||
|
// the current process. It is a pseudo token that does not need
|
||||||
|
// to be closed.
|
||||||
|
func GetCurrentProcessToken() Token {
|
||||||
|
return Token(^uintptr(4 - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCurrentThreadToken return the access token associated with
|
||||||
|
// the current thread. It is a pseudo token that does not need
|
||||||
|
// to be closed.
|
||||||
|
func GetCurrentThreadToken() Token {
|
||||||
|
return Token(^uintptr(5 - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCurrentThreadEffectiveToken returns the effective access token
|
||||||
|
// associated with the current thread. It is a pseudo token that does
|
||||||
|
// not need to be closed.
|
||||||
|
func GetCurrentThreadEffectiveToken() Token {
|
||||||
|
return Token(^uintptr(6 - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close releases access to access token.
|
||||||
|
func (t Token) Close() error {
|
||||||
|
return CloseHandle(Handle(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getInfo retrieves a specified type of information about an access token.
|
||||||
|
func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
|
||||||
|
n := uint32(initSize)
|
||||||
|
for {
|
||||||
|
b := make([]byte, n)
|
||||||
|
e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
|
||||||
|
if e == nil {
|
||||||
|
return unsafe.Pointer(&b[0]), nil
|
||||||
|
}
|
||||||
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
if n <= uint32(len(b)) {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTokenUser retrieves access token t user account information.
|
||||||
|
func (t Token) GetTokenUser() (*Tokenuser, error) {
|
||||||
|
i, e := t.getInfo(TokenUser, 50)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return (*Tokenuser)(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTokenGroups retrieves group accounts associated with access token t.
|
||||||
|
func (t Token) GetTokenGroups() (*Tokengroups, error) {
|
||||||
|
i, e := t.getInfo(TokenGroups, 50)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return (*Tokengroups)(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTokenPrimaryGroup retrieves access token t primary group information.
|
||||||
|
// A pointer to a SID structure representing a group that will become
|
||||||
|
// the primary group of any objects created by a process using this access token.
|
||||||
|
func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
|
||||||
|
i, e := t.getInfo(TokenPrimaryGroup, 50)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return (*Tokenprimarygroup)(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserProfileDirectory retrieves path to the
|
||||||
|
// root directory of the access token t user's profile.
|
||||||
|
func (t Token) GetUserProfileDirectory() (string, error) {
|
||||||
|
n := uint32(100)
|
||||||
|
for {
|
||||||
|
b := make([]uint16, n)
|
||||||
|
e := GetUserProfileDirectory(t, &b[0], &n)
|
||||||
|
if e == nil {
|
||||||
|
return UTF16ToString(b), nil
|
||||||
|
}
|
||||||
|
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
if n <= uint32(len(b)) {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsElevated returns whether the current token is elevated from a UAC perspective.
|
||||||
|
func (token Token) IsElevated() bool {
|
||||||
|
var isElevated uint32
|
||||||
|
var outLen uint32
|
||||||
|
err := GetTokenInformation(token, TokenElevation, (*byte)(unsafe.Pointer(&isElevated)), uint32(unsafe.Sizeof(isElevated)), &outLen)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return outLen == uint32(unsafe.Sizeof(isElevated)) && isElevated != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLinkedToken returns the linked token, which may be an elevated UAC token.
|
||||||
|
func (token Token) GetLinkedToken() (Token, error) {
|
||||||
|
var linkedToken Token
|
||||||
|
var outLen uint32
|
||||||
|
err := GetTokenInformation(token, TokenLinkedToken, (*byte)(unsafe.Pointer(&linkedToken)), uint32(unsafe.Sizeof(linkedToken)), &outLen)
|
||||||
|
if err != nil {
|
||||||
|
return Token(0), err
|
||||||
|
}
|
||||||
|
return linkedToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSystemDirectory retrieves path to current location of the system
|
||||||
|
// directory, which is typically, though not always, C:\Windows\System32.
|
||||||
|
func GetSystemDirectory() (string, error) {
|
||||||
|
n := uint32(MAX_PATH)
|
||||||
|
for {
|
||||||
|
b := make([]uint16, n)
|
||||||
|
l, e := getSystemDirectory(&b[0], n)
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
if l <= n {
|
||||||
|
return UTF16ToString(b[:l]), nil
|
||||||
|
}
|
||||||
|
n = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMember reports whether the access token t is a member of the provided SID.
|
||||||
|
func (t Token) IsMember(sid *SID) (bool, error) {
|
||||||
|
var b int32
|
||||||
|
if e := checkTokenMembership(t, sid, &b); e != nil {
|
||||||
|
return false, e
|
||||||
|
}
|
||||||
|
return b != 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
WTS_CONSOLE_CONNECT = 0x1
|
||||||
|
WTS_CONSOLE_DISCONNECT = 0x2
|
||||||
|
WTS_REMOTE_CONNECT = 0x3
|
||||||
|
WTS_REMOTE_DISCONNECT = 0x4
|
||||||
|
WTS_SESSION_LOGON = 0x5
|
||||||
|
WTS_SESSION_LOGOFF = 0x6
|
||||||
|
WTS_SESSION_LOCK = 0x7
|
||||||
|
WTS_SESSION_UNLOCK = 0x8
|
||||||
|
WTS_SESSION_REMOTE_CONTROL = 0x9
|
||||||
|
WTS_SESSION_CREATE = 0xa
|
||||||
|
WTS_SESSION_TERMINATE = 0xb
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WTSActive = 0
|
||||||
|
WTSConnected = 1
|
||||||
|
WTSConnectQuery = 2
|
||||||
|
WTSShadow = 3
|
||||||
|
WTSDisconnected = 4
|
||||||
|
WTSIdle = 5
|
||||||
|
WTSListen = 6
|
||||||
|
WTSReset = 7
|
||||||
|
WTSDown = 8
|
||||||
|
WTSInit = 9
|
||||||
|
)
|
||||||
|
|
||||||
|
type WTSSESSION_NOTIFICATION struct {
|
||||||
|
Size uint32
|
||||||
|
SessionID uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type WTS_SESSION_INFO struct {
|
||||||
|
SessionID uint32
|
||||||
|
WindowStationName *uint16
|
||||||
|
State uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
|
||||||
|
//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
|
||||||
|
//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
|
|
@ -0,0 +1,225 @@
|
||||||
|
// Copyright 2012 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.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
const (
|
||||||
|
SC_MANAGER_CONNECT = 1
|
||||||
|
SC_MANAGER_CREATE_SERVICE = 2
|
||||||
|
SC_MANAGER_ENUMERATE_SERVICE = 4
|
||||||
|
SC_MANAGER_LOCK = 8
|
||||||
|
SC_MANAGER_QUERY_LOCK_STATUS = 16
|
||||||
|
SC_MANAGER_MODIFY_BOOT_CONFIG = 32
|
||||||
|
SC_MANAGER_ALL_ACCESS = 0xf003f
|
||||||
|
)
|
||||||
|
|
||||||
|
//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW
|
||||||
|
|
||||||
|
const (
|
||||||
|
SERVICE_KERNEL_DRIVER = 1
|
||||||
|
SERVICE_FILE_SYSTEM_DRIVER = 2
|
||||||
|
SERVICE_ADAPTER = 4
|
||||||
|
SERVICE_RECOGNIZER_DRIVER = 8
|
||||||
|
SERVICE_WIN32_OWN_PROCESS = 16
|
||||||
|
SERVICE_WIN32_SHARE_PROCESS = 32
|
||||||
|
SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS
|
||||||
|
SERVICE_INTERACTIVE_PROCESS = 256
|
||||||
|
SERVICE_DRIVER = SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER
|
||||||
|
SERVICE_TYPE_ALL = SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS
|
||||||
|
|
||||||
|
SERVICE_BOOT_START = 0
|
||||||
|
SERVICE_SYSTEM_START = 1
|
||||||
|
SERVICE_AUTO_START = 2
|
||||||
|
SERVICE_DEMAND_START = 3
|
||||||
|
SERVICE_DISABLED = 4
|
||||||
|
|
||||||
|
SERVICE_ERROR_IGNORE = 0
|
||||||
|
SERVICE_ERROR_NORMAL = 1
|
||||||
|
SERVICE_ERROR_SEVERE = 2
|
||||||
|
SERVICE_ERROR_CRITICAL = 3
|
||||||
|
|
||||||
|
SC_STATUS_PROCESS_INFO = 0
|
||||||
|
|
||||||
|
SC_ACTION_NONE = 0
|
||||||
|
SC_ACTION_RESTART = 1
|
||||||
|
SC_ACTION_REBOOT = 2
|
||||||
|
SC_ACTION_RUN_COMMAND = 3
|
||||||
|
|
||||||
|
SERVICE_STOPPED = 1
|
||||||
|
SERVICE_START_PENDING = 2
|
||||||
|
SERVICE_STOP_PENDING = 3
|
||||||
|
SERVICE_RUNNING = 4
|
||||||
|
SERVICE_CONTINUE_PENDING = 5
|
||||||
|
SERVICE_PAUSE_PENDING = 6
|
||||||
|
SERVICE_PAUSED = 7
|
||||||
|
SERVICE_NO_CHANGE = 0xffffffff
|
||||||
|
|
||||||
|
SERVICE_ACCEPT_STOP = 1
|
||||||
|
SERVICE_ACCEPT_PAUSE_CONTINUE = 2
|
||||||
|
SERVICE_ACCEPT_SHUTDOWN = 4
|
||||||
|
SERVICE_ACCEPT_PARAMCHANGE = 8
|
||||||
|
SERVICE_ACCEPT_NETBINDCHANGE = 16
|
||||||
|
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 32
|
||||||
|
SERVICE_ACCEPT_POWEREVENT = 64
|
||||||
|
SERVICE_ACCEPT_SESSIONCHANGE = 128
|
||||||
|
|
||||||
|
SERVICE_CONTROL_STOP = 1
|
||||||
|
SERVICE_CONTROL_PAUSE = 2
|
||||||
|
SERVICE_CONTROL_CONTINUE = 3
|
||||||
|
SERVICE_CONTROL_INTERROGATE = 4
|
||||||
|
SERVICE_CONTROL_SHUTDOWN = 5
|
||||||
|
SERVICE_CONTROL_PARAMCHANGE = 6
|
||||||
|
SERVICE_CONTROL_NETBINDADD = 7
|
||||||
|
SERVICE_CONTROL_NETBINDREMOVE = 8
|
||||||
|
SERVICE_CONTROL_NETBINDENABLE = 9
|
||||||
|
SERVICE_CONTROL_NETBINDDISABLE = 10
|
||||||
|
SERVICE_CONTROL_DEVICEEVENT = 11
|
||||||
|
SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12
|
||||||
|
SERVICE_CONTROL_POWEREVENT = 13
|
||||||
|
SERVICE_CONTROL_SESSIONCHANGE = 14
|
||||||
|
|
||||||
|
SERVICE_ACTIVE = 1
|
||||||
|
SERVICE_INACTIVE = 2
|
||||||
|
SERVICE_STATE_ALL = 3
|
||||||
|
|
||||||
|
SERVICE_QUERY_CONFIG = 1
|
||||||
|
SERVICE_CHANGE_CONFIG = 2
|
||||||
|
SERVICE_QUERY_STATUS = 4
|
||||||
|
SERVICE_ENUMERATE_DEPENDENTS = 8
|
||||||
|
SERVICE_START = 16
|
||||||
|
SERVICE_STOP = 32
|
||||||
|
SERVICE_PAUSE_CONTINUE = 64
|
||||||
|
SERVICE_INTERROGATE = 128
|
||||||
|
SERVICE_USER_DEFINED_CONTROL = 256
|
||||||
|
SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_USER_DEFINED_CONTROL
|
||||||
|
|
||||||
|
SERVICE_RUNS_IN_SYSTEM_PROCESS = 1
|
||||||
|
|
||||||
|
SERVICE_CONFIG_DESCRIPTION = 1
|
||||||
|
SERVICE_CONFIG_FAILURE_ACTIONS = 2
|
||||||
|
SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3
|
||||||
|
SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4
|
||||||
|
SERVICE_CONFIG_SERVICE_SID_INFO = 5
|
||||||
|
SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 6
|
||||||
|
SERVICE_CONFIG_PRESHUTDOWN_INFO = 7
|
||||||
|
SERVICE_CONFIG_TRIGGER_INFO = 8
|
||||||
|
SERVICE_CONFIG_PREFERRED_NODE = 9
|
||||||
|
SERVICE_CONFIG_LAUNCH_PROTECTED = 12
|
||||||
|
|
||||||
|
SERVICE_SID_TYPE_NONE = 0
|
||||||
|
SERVICE_SID_TYPE_UNRESTRICTED = 1
|
||||||
|
SERVICE_SID_TYPE_RESTRICTED = 2 | SERVICE_SID_TYPE_UNRESTRICTED
|
||||||
|
|
||||||
|
SC_ENUM_PROCESS_INFO = 0
|
||||||
|
|
||||||
|
SERVICE_NOTIFY_STATUS_CHANGE = 2
|
||||||
|
SERVICE_NOTIFY_STOPPED = 0x00000001
|
||||||
|
SERVICE_NOTIFY_START_PENDING = 0x00000002
|
||||||
|
SERVICE_NOTIFY_STOP_PENDING = 0x00000004
|
||||||
|
SERVICE_NOTIFY_RUNNING = 0x00000008
|
||||||
|
SERVICE_NOTIFY_CONTINUE_PENDING = 0x00000010
|
||||||
|
SERVICE_NOTIFY_PAUSE_PENDING = 0x00000020
|
||||||
|
SERVICE_NOTIFY_PAUSED = 0x00000040
|
||||||
|
SERVICE_NOTIFY_CREATED = 0x00000080
|
||||||
|
SERVICE_NOTIFY_DELETED = 0x00000100
|
||||||
|
SERVICE_NOTIFY_DELETE_PENDING = 0x00000200
|
||||||
|
)
|
||||||
|
|
||||||
|
type SERVICE_STATUS struct {
|
||||||
|
ServiceType uint32
|
||||||
|
CurrentState uint32
|
||||||
|
ControlsAccepted uint32
|
||||||
|
Win32ExitCode uint32
|
||||||
|
ServiceSpecificExitCode uint32
|
||||||
|
CheckPoint uint32
|
||||||
|
WaitHint uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type SERVICE_TABLE_ENTRY struct {
|
||||||
|
ServiceName *uint16
|
||||||
|
ServiceProc uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type QUERY_SERVICE_CONFIG struct {
|
||||||
|
ServiceType uint32
|
||||||
|
StartType uint32
|
||||||
|
ErrorControl uint32
|
||||||
|
BinaryPathName *uint16
|
||||||
|
LoadOrderGroup *uint16
|
||||||
|
TagId uint32
|
||||||
|
Dependencies *uint16
|
||||||
|
ServiceStartName *uint16
|
||||||
|
DisplayName *uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type SERVICE_DESCRIPTION struct {
|
||||||
|
Description *uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type SERVICE_STATUS_PROCESS struct {
|
||||||
|
ServiceType uint32
|
||||||
|
CurrentState uint32
|
||||||
|
ControlsAccepted uint32
|
||||||
|
Win32ExitCode uint32
|
||||||
|
ServiceSpecificExitCode uint32
|
||||||
|
CheckPoint uint32
|
||||||
|
WaitHint uint32
|
||||||
|
ProcessId uint32
|
||||||
|
ServiceFlags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ENUM_SERVICE_STATUS_PROCESS struct {
|
||||||
|
ServiceName *uint16
|
||||||
|
DisplayName *uint16
|
||||||
|
ServiceStatusProcess SERVICE_STATUS_PROCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
type SERVICE_NOTIFY struct {
|
||||||
|
Version uint32
|
||||||
|
NotifyCallback uintptr
|
||||||
|
Context uintptr
|
||||||
|
NotificationStatus uint32
|
||||||
|
ServiceStatus SERVICE_STATUS_PROCESS
|
||||||
|
NotificationTriggered uint32
|
||||||
|
ServiceNames *uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type SERVICE_FAILURE_ACTIONS struct {
|
||||||
|
ResetPeriod uint32
|
||||||
|
RebootMsg *uint16
|
||||||
|
Command *uint16
|
||||||
|
ActionsCount uint32
|
||||||
|
Actions *SC_ACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
type SC_ACTION struct {
|
||||||
|
Type uint32
|
||||||
|
Delay uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type QUERY_SERVICE_LOCK_STATUS struct {
|
||||||
|
IsLocked uint32
|
||||||
|
LockOwner *uint16
|
||||||
|
LockDuration uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle
|
||||||
|
//sys CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) [failretval==0] = advapi32.CreateServiceW
|
||||||
|
//sys OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW
|
||||||
|
//sys DeleteService(service Handle) (err error) = advapi32.DeleteService
|
||||||
|
//sys StartService(service Handle, numArgs uint32, argVectors **uint16) (err error) = advapi32.StartServiceW
|
||||||
|
//sys QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) = advapi32.QueryServiceStatus
|
||||||
|
//sys QueryServiceLockStatus(mgr Handle, lockStatus *QUERY_SERVICE_LOCK_STATUS, bufSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceLockStatusW
|
||||||
|
//sys ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err error) = advapi32.ControlService
|
||||||
|
//sys StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) = advapi32.StartServiceCtrlDispatcherW
|
||||||
|
//sys SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) = advapi32.SetServiceStatus
|
||||||
|
//sys ChangeServiceConfig(service Handle, serviceType uint32, startType uint32, errorControl uint32, binaryPathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16, displayName *uint16) (err error) = advapi32.ChangeServiceConfigW
|
||||||
|
//sys QueryServiceConfig(service Handle, serviceConfig *QUERY_SERVICE_CONFIG, bufSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceConfigW
|
||||||
|
//sys ChangeServiceConfig2(service Handle, infoLevel uint32, info *byte) (err error) = advapi32.ChangeServiceConfig2W
|
||||||
|
//sys QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceConfig2W
|
||||||
|
//sys EnumServicesStatusEx(mgr Handle, infoLevel uint32, serviceType uint32, serviceState uint32, services *byte, bufSize uint32, bytesNeeded *uint32, servicesReturned *uint32, resumeHandle *uint32, groupName *uint16) (err error) = advapi32.EnumServicesStatusExW
|
||||||
|
//sys QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceStatusEx
|
||||||
|
//sys NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) = advapi32.NotifyServiceStatusChangeW
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2009 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.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
|
||||||
|
if val < 0 {
|
||||||
|
return "-" + itoa(-val)
|
||||||
|
}
|
||||||
|
var buf [32]byte // big enough for int64
|
||||||
|
i := len(buf) - 1
|
||||||
|
for val >= 10 {
|
||||||
|
buf[i] = byte(val%10 + '0')
|
||||||
|
i--
|
||||||
|
val /= 10
|
||||||
|
}
|
||||||
|
buf[i] = byte(val + '0')
|
||||||
|
return string(buf[i:])
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright 2009 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.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
// Package windows contains an interface to the low-level operating system
|
||||||
|
// primitives. OS details vary depending on the underlying system, and
|
||||||
|
// by default, godoc will display the OS-specific documentation for the current
|
||||||
|
// system. If you want godoc to display syscall documentation for another
|
||||||
|
// system, set $GOOS and $GOARCH to the desired system. For example, if
|
||||||
|
// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
|
||||||
|
// to freebsd and $GOARCH to arm.
|
||||||
|
//
|
||||||
|
// The primary use of this package is inside other packages that provide a more
|
||||||
|
// portable interface to the system, such as "os", "time" and "net". Use
|
||||||
|
// those packages rather than this one if you can.
|
||||||
|
//
|
||||||
|
// For details of the functions and data types in this package consult
|
||||||
|
// the manuals for the appropriate operating system.
|
||||||
|
//
|
||||||
|
// These calls return err == nil to indicate success; otherwise
|
||||||
|
// err represents an operating system error describing the failure and
|
||||||
|
// holds a value of type syscall.Errno.
|
||||||
|
package windows // import "golang.org/x/sys/windows"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
||||||
|
// containing the text of s. If s contains a NUL byte at any
|
||||||
|
// location, it returns (nil, syscall.EINVAL).
|
||||||
|
func ByteSliceFromString(s string) ([]byte, error) {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] == 0 {
|
||||||
|
return nil, syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a := make([]byte, len(s)+1)
|
||||||
|
copy(a, s)
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytePtrFromString returns a pointer to a NUL-terminated array of
|
||||||
|
// bytes containing the text of s. If s contains a NUL byte at any
|
||||||
|
// location, it returns (nil, syscall.EINVAL).
|
||||||
|
func BytePtrFromString(s string) (*byte, error) {
|
||||||
|
a, err := ByteSliceFromString(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &a[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
||||||
|
// See mksyscall.pl.
|
||||||
|
var _zero uintptr
|
||||||
|
|
||||||
|
func (ts *Timespec) Unix() (sec int64, nsec int64) {
|
||||||
|
return int64(ts.Sec), int64(ts.Nsec)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tv *Timeval) Unix() (sec int64, nsec int64) {
|
||||||
|
return int64(tv.Sec), int64(tv.Usec) * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts *Timespec) Nano() int64 {
|
||||||
|
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tv *Timeval) Nano() int64 {
|
||||||
|
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2011 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.
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
type WSAData struct {
|
||||||
|
Version uint16
|
||||||
|
HighVersion uint16
|
||||||
|
Description [WSADESCRIPTION_LEN + 1]byte
|
||||||
|
SystemStatus [WSASYS_STATUS_LEN + 1]byte
|
||||||
|
MaxSockets uint16
|
||||||
|
MaxUdpDg uint16
|
||||||
|
VendorInfo *byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Servent struct {
|
||||||
|
Name *byte
|
||||||
|
Aliases **byte
|
||||||
|
Port uint16
|
||||||
|
Proto *byte
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2011 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.
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
type WSAData struct {
|
||||||
|
Version uint16
|
||||||
|
HighVersion uint16
|
||||||
|
MaxSockets uint16
|
||||||
|
MaxUdpDg uint16
|
||||||
|
VendorInfo *byte
|
||||||
|
Description [WSADESCRIPTION_LEN + 1]byte
|
||||||
|
SystemStatus [WSASYS_STATUS_LEN + 1]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Servent struct {
|
||||||
|
Name *byte
|
||||||
|
Aliases **byte
|
||||||
|
Proto *byte
|
||||||
|
Port uint16
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
type WSAData struct {
|
||||||
|
Version uint16
|
||||||
|
HighVersion uint16
|
||||||
|
Description [WSADESCRIPTION_LEN + 1]byte
|
||||||
|
SystemStatus [WSASYS_STATUS_LEN + 1]byte
|
||||||
|
MaxSockets uint16
|
||||||
|
MaxUdpDg uint16
|
||||||
|
VendorInfo *byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Servent struct {
|
||||||
|
Name *byte
|
||||||
|
Aliases **byte
|
||||||
|
Port uint16
|
||||||
|
Proto *byte
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,149 @@
|
||||||
|
// Code generated by 'mkknownfolderids.bash'; DO NOT EDIT.
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
type KNOWNFOLDERID GUID
|
||||||
|
|
||||||
|
var (
|
||||||
|
FOLDERID_NetworkFolder = &KNOWNFOLDERID{0xd20beec4, 0x5ca8, 0x4905, [8]byte{0xae, 0x3b, 0xbf, 0x25, 0x1e, 0xa0, 0x9b, 0x53}}
|
||||||
|
FOLDERID_ComputerFolder = &KNOWNFOLDERID{0x0ac0837c, 0xbbf8, 0x452a, [8]byte{0x85, 0x0d, 0x79, 0xd0, 0x8e, 0x66, 0x7c, 0xa7}}
|
||||||
|
FOLDERID_InternetFolder = &KNOWNFOLDERID{0x4d9f7874, 0x4e0c, 0x4904, [8]byte{0x96, 0x7b, 0x40, 0xb0, 0xd2, 0x0c, 0x3e, 0x4b}}
|
||||||
|
FOLDERID_ControlPanelFolder = &KNOWNFOLDERID{0x82a74aeb, 0xaeb4, 0x465c, [8]byte{0xa0, 0x14, 0xd0, 0x97, 0xee, 0x34, 0x6d, 0x63}}
|
||||||
|
FOLDERID_PrintersFolder = &KNOWNFOLDERID{0x76fc4e2d, 0xd6ad, 0x4519, [8]byte{0xa6, 0x63, 0x37, 0xbd, 0x56, 0x06, 0x81, 0x85}}
|
||||||
|
FOLDERID_SyncManagerFolder = &KNOWNFOLDERID{0x43668bf8, 0xc14e, 0x49b2, [8]byte{0x97, 0xc9, 0x74, 0x77, 0x84, 0xd7, 0x84, 0xb7}}
|
||||||
|
FOLDERID_SyncSetupFolder = &KNOWNFOLDERID{0x0f214138, 0xb1d3, 0x4a90, [8]byte{0xbb, 0xa9, 0x27, 0xcb, 0xc0, 0xc5, 0x38, 0x9a}}
|
||||||
|
FOLDERID_ConflictFolder = &KNOWNFOLDERID{0x4bfefb45, 0x347d, 0x4006, [8]byte{0xa5, 0xbe, 0xac, 0x0c, 0xb0, 0x56, 0x71, 0x92}}
|
||||||
|
FOLDERID_SyncResultsFolder = &KNOWNFOLDERID{0x289a9a43, 0xbe44, 0x4057, [8]byte{0xa4, 0x1b, 0x58, 0x7a, 0x76, 0xd7, 0xe7, 0xf9}}
|
||||||
|
FOLDERID_RecycleBinFolder = &KNOWNFOLDERID{0xb7534046, 0x3ecb, 0x4c18, [8]byte{0xbe, 0x4e, 0x64, 0xcd, 0x4c, 0xb7, 0xd6, 0xac}}
|
||||||
|
FOLDERID_ConnectionsFolder = &KNOWNFOLDERID{0x6f0cd92b, 0x2e97, 0x45d1, [8]byte{0x88, 0xff, 0xb0, 0xd1, 0x86, 0xb8, 0xde, 0xdd}}
|
||||||
|
FOLDERID_Fonts = &KNOWNFOLDERID{0xfd228cb7, 0xae11, 0x4ae3, [8]byte{0x86, 0x4c, 0x16, 0xf3, 0x91, 0x0a, 0xb8, 0xfe}}
|
||||||
|
FOLDERID_Desktop = &KNOWNFOLDERID{0xb4bfcc3a, 0xdb2c, 0x424c, [8]byte{0xb0, 0x29, 0x7f, 0xe9, 0x9a, 0x87, 0xc6, 0x41}}
|
||||||
|
FOLDERID_Startup = &KNOWNFOLDERID{0xb97d20bb, 0xf46a, 0x4c97, [8]byte{0xba, 0x10, 0x5e, 0x36, 0x08, 0x43, 0x08, 0x54}}
|
||||||
|
FOLDERID_Programs = &KNOWNFOLDERID{0xa77f5d77, 0x2e2b, 0x44c3, [8]byte{0xa6, 0xa2, 0xab, 0xa6, 0x01, 0x05, 0x4a, 0x51}}
|
||||||
|
FOLDERID_StartMenu = &KNOWNFOLDERID{0x625b53c3, 0xab48, 0x4ec1, [8]byte{0xba, 0x1f, 0xa1, 0xef, 0x41, 0x46, 0xfc, 0x19}}
|
||||||
|
FOLDERID_Recent = &KNOWNFOLDERID{0xae50c081, 0xebd2, 0x438a, [8]byte{0x86, 0x55, 0x8a, 0x09, 0x2e, 0x34, 0x98, 0x7a}}
|
||||||
|
FOLDERID_SendTo = &KNOWNFOLDERID{0x8983036c, 0x27c0, 0x404b, [8]byte{0x8f, 0x08, 0x10, 0x2d, 0x10, 0xdc, 0xfd, 0x74}}
|
||||||
|
FOLDERID_Documents = &KNOWNFOLDERID{0xfdd39ad0, 0x238f, 0x46af, [8]byte{0xad, 0xb4, 0x6c, 0x85, 0x48, 0x03, 0x69, 0xc7}}
|
||||||
|
FOLDERID_Favorites = &KNOWNFOLDERID{0x1777f761, 0x68ad, 0x4d8a, [8]byte{0x87, 0xbd, 0x30, 0xb7, 0x59, 0xfa, 0x33, 0xdd}}
|
||||||
|
FOLDERID_NetHood = &KNOWNFOLDERID{0xc5abbf53, 0xe17f, 0x4121, [8]byte{0x89, 0x00, 0x86, 0x62, 0x6f, 0xc2, 0xc9, 0x73}}
|
||||||
|
FOLDERID_PrintHood = &KNOWNFOLDERID{0x9274bd8d, 0xcfd1, 0x41c3, [8]byte{0xb3, 0x5e, 0xb1, 0x3f, 0x55, 0xa7, 0x58, 0xf4}}
|
||||||
|
FOLDERID_Templates = &KNOWNFOLDERID{0xa63293e8, 0x664e, 0x48db, [8]byte{0xa0, 0x79, 0xdf, 0x75, 0x9e, 0x05, 0x09, 0xf7}}
|
||||||
|
FOLDERID_CommonStartup = &KNOWNFOLDERID{0x82a5ea35, 0xd9cd, 0x47c5, [8]byte{0x96, 0x29, 0xe1, 0x5d, 0x2f, 0x71, 0x4e, 0x6e}}
|
||||||
|
FOLDERID_CommonPrograms = &KNOWNFOLDERID{0x0139d44e, 0x6afe, 0x49f2, [8]byte{0x86, 0x90, 0x3d, 0xaf, 0xca, 0xe6, 0xff, 0xb8}}
|
||||||
|
FOLDERID_CommonStartMenu = &KNOWNFOLDERID{0xa4115719, 0xd62e, 0x491d, [8]byte{0xaa, 0x7c, 0xe7, 0x4b, 0x8b, 0xe3, 0xb0, 0x67}}
|
||||||
|
FOLDERID_PublicDesktop = &KNOWNFOLDERID{0xc4aa340d, 0xf20f, 0x4863, [8]byte{0xaf, 0xef, 0xf8, 0x7e, 0xf2, 0xe6, 0xba, 0x25}}
|
||||||
|
FOLDERID_ProgramData = &KNOWNFOLDERID{0x62ab5d82, 0xfdc1, 0x4dc3, [8]byte{0xa9, 0xdd, 0x07, 0x0d, 0x1d, 0x49, 0x5d, 0x97}}
|
||||||
|
FOLDERID_CommonTemplates = &KNOWNFOLDERID{0xb94237e7, 0x57ac, 0x4347, [8]byte{0x91, 0x51, 0xb0, 0x8c, 0x6c, 0x32, 0xd1, 0xf7}}
|
||||||
|
FOLDERID_PublicDocuments = &KNOWNFOLDERID{0xed4824af, 0xdce4, 0x45a8, [8]byte{0x81, 0xe2, 0xfc, 0x79, 0x65, 0x08, 0x36, 0x34}}
|
||||||
|
FOLDERID_RoamingAppData = &KNOWNFOLDERID{0x3eb685db, 0x65f9, 0x4cf6, [8]byte{0xa0, 0x3a, 0xe3, 0xef, 0x65, 0x72, 0x9f, 0x3d}}
|
||||||
|
FOLDERID_LocalAppData = &KNOWNFOLDERID{0xf1b32785, 0x6fba, 0x4fcf, [8]byte{0x9d, 0x55, 0x7b, 0x8e, 0x7f, 0x15, 0x70, 0x91}}
|
||||||
|
FOLDERID_LocalAppDataLow = &KNOWNFOLDERID{0xa520a1a4, 0x1780, 0x4ff6, [8]byte{0xbd, 0x18, 0x16, 0x73, 0x43, 0xc5, 0xaf, 0x16}}
|
||||||
|
FOLDERID_InternetCache = &KNOWNFOLDERID{0x352481e8, 0x33be, 0x4251, [8]byte{0xba, 0x85, 0x60, 0x07, 0xca, 0xed, 0xcf, 0x9d}}
|
||||||
|
FOLDERID_Cookies = &KNOWNFOLDERID{0x2b0f765d, 0xc0e9, 0x4171, [8]byte{0x90, 0x8e, 0x08, 0xa6, 0x11, 0xb8, 0x4f, 0xf6}}
|
||||||
|
FOLDERID_History = &KNOWNFOLDERID{0xd9dc8a3b, 0xb784, 0x432e, [8]byte{0xa7, 0x81, 0x5a, 0x11, 0x30, 0xa7, 0x59, 0x63}}
|
||||||
|
FOLDERID_System = &KNOWNFOLDERID{0x1ac14e77, 0x02e7, 0x4e5d, [8]byte{0xb7, 0x44, 0x2e, 0xb1, 0xae, 0x51, 0x98, 0xb7}}
|
||||||
|
FOLDERID_SystemX86 = &KNOWNFOLDERID{0xd65231b0, 0xb2f1, 0x4857, [8]byte{0xa4, 0xce, 0xa8, 0xe7, 0xc6, 0xea, 0x7d, 0x27}}
|
||||||
|
FOLDERID_Windows = &KNOWNFOLDERID{0xf38bf404, 0x1d43, 0x42f2, [8]byte{0x93, 0x05, 0x67, 0xde, 0x0b, 0x28, 0xfc, 0x23}}
|
||||||
|
FOLDERID_Profile = &KNOWNFOLDERID{0x5e6c858f, 0x0e22, 0x4760, [8]byte{0x9a, 0xfe, 0xea, 0x33, 0x17, 0xb6, 0x71, 0x73}}
|
||||||
|
FOLDERID_Pictures = &KNOWNFOLDERID{0x33e28130, 0x4e1e, 0x4676, [8]byte{0x83, 0x5a, 0x98, 0x39, 0x5c, 0x3b, 0xc3, 0xbb}}
|
||||||
|
FOLDERID_ProgramFilesX86 = &KNOWNFOLDERID{0x7c5a40ef, 0xa0fb, 0x4bfc, [8]byte{0x87, 0x4a, 0xc0, 0xf2, 0xe0, 0xb9, 0xfa, 0x8e}}
|
||||||
|
FOLDERID_ProgramFilesCommonX86 = &KNOWNFOLDERID{0xde974d24, 0xd9c6, 0x4d3e, [8]byte{0xbf, 0x91, 0xf4, 0x45, 0x51, 0x20, 0xb9, 0x17}}
|
||||||
|
FOLDERID_ProgramFilesX64 = &KNOWNFOLDERID{0x6d809377, 0x6af0, 0x444b, [8]byte{0x89, 0x57, 0xa3, 0x77, 0x3f, 0x02, 0x20, 0x0e}}
|
||||||
|
FOLDERID_ProgramFilesCommonX64 = &KNOWNFOLDERID{0x6365d5a7, 0x0f0d, 0x45e5, [8]byte{0x87, 0xf6, 0x0d, 0xa5, 0x6b, 0x6a, 0x4f, 0x7d}}
|
||||||
|
FOLDERID_ProgramFiles = &KNOWNFOLDERID{0x905e63b6, 0xc1bf, 0x494e, [8]byte{0xb2, 0x9c, 0x65, 0xb7, 0x32, 0xd3, 0xd2, 0x1a}}
|
||||||
|
FOLDERID_ProgramFilesCommon = &KNOWNFOLDERID{0xf7f1ed05, 0x9f6d, 0x47a2, [8]byte{0xaa, 0xae, 0x29, 0xd3, 0x17, 0xc6, 0xf0, 0x66}}
|
||||||
|
FOLDERID_UserProgramFiles = &KNOWNFOLDERID{0x5cd7aee2, 0x2219, 0x4a67, [8]byte{0xb8, 0x5d, 0x6c, 0x9c, 0xe1, 0x56, 0x60, 0xcb}}
|
||||||
|
FOLDERID_UserProgramFilesCommon = &KNOWNFOLDERID{0xbcbd3057, 0xca5c, 0x4622, [8]byte{0xb4, 0x2d, 0xbc, 0x56, 0xdb, 0x0a, 0xe5, 0x16}}
|
||||||
|
FOLDERID_AdminTools = &KNOWNFOLDERID{0x724ef170, 0xa42d, 0x4fef, [8]byte{0x9f, 0x26, 0xb6, 0x0e, 0x84, 0x6f, 0xba, 0x4f}}
|
||||||
|
FOLDERID_CommonAdminTools = &KNOWNFOLDERID{0xd0384e7d, 0xbac3, 0x4797, [8]byte{0x8f, 0x14, 0xcb, 0xa2, 0x29, 0xb3, 0x92, 0xb5}}
|
||||||
|
FOLDERID_Music = &KNOWNFOLDERID{0x4bd8d571, 0x6d19, 0x48d3, [8]byte{0xbe, 0x97, 0x42, 0x22, 0x20, 0x08, 0x0e, 0x43}}
|
||||||
|
FOLDERID_Videos = &KNOWNFOLDERID{0x18989b1d, 0x99b5, 0x455b, [8]byte{0x84, 0x1c, 0xab, 0x7c, 0x74, 0xe4, 0xdd, 0xfc}}
|
||||||
|
FOLDERID_Ringtones = &KNOWNFOLDERID{0xc870044b, 0xf49e, 0x4126, [8]byte{0xa9, 0xc3, 0xb5, 0x2a, 0x1f, 0xf4, 0x11, 0xe8}}
|
||||||
|
FOLDERID_PublicPictures = &KNOWNFOLDERID{0xb6ebfb86, 0x6907, 0x413c, [8]byte{0x9a, 0xf7, 0x4f, 0xc2, 0xab, 0xf0, 0x7c, 0xc5}}
|
||||||
|
FOLDERID_PublicMusic = &KNOWNFOLDERID{0x3214fab5, 0x9757, 0x4298, [8]byte{0xbb, 0x61, 0x92, 0xa9, 0xde, 0xaa, 0x44, 0xff}}
|
||||||
|
FOLDERID_PublicVideos = &KNOWNFOLDERID{0x2400183a, 0x6185, 0x49fb, [8]byte{0xa2, 0xd8, 0x4a, 0x39, 0x2a, 0x60, 0x2b, 0xa3}}
|
||||||
|
FOLDERID_PublicRingtones = &KNOWNFOLDERID{0xe555ab60, 0x153b, 0x4d17, [8]byte{0x9f, 0x04, 0xa5, 0xfe, 0x99, 0xfc, 0x15, 0xec}}
|
||||||
|
FOLDERID_ResourceDir = &KNOWNFOLDERID{0x8ad10c31, 0x2adb, 0x4296, [8]byte{0xa8, 0xf7, 0xe4, 0x70, 0x12, 0x32, 0xc9, 0x72}}
|
||||||
|
FOLDERID_LocalizedResourcesDir = &KNOWNFOLDERID{0x2a00375e, 0x224c, 0x49de, [8]byte{0xb8, 0xd1, 0x44, 0x0d, 0xf7, 0xef, 0x3d, 0xdc}}
|
||||||
|
FOLDERID_CommonOEMLinks = &KNOWNFOLDERID{0xc1bae2d0, 0x10df, 0x4334, [8]byte{0xbe, 0xdd, 0x7a, 0xa2, 0x0b, 0x22, 0x7a, 0x9d}}
|
||||||
|
FOLDERID_CDBurning = &KNOWNFOLDERID{0x9e52ab10, 0xf80d, 0x49df, [8]byte{0xac, 0xb8, 0x43, 0x30, 0xf5, 0x68, 0x78, 0x55}}
|
||||||
|
FOLDERID_UserProfiles = &KNOWNFOLDERID{0x0762d272, 0xc50a, 0x4bb0, [8]byte{0xa3, 0x82, 0x69, 0x7d, 0xcd, 0x72, 0x9b, 0x80}}
|
||||||
|
FOLDERID_Playlists = &KNOWNFOLDERID{0xde92c1c7, 0x837f, 0x4f69, [8]byte{0xa3, 0xbb, 0x86, 0xe6, 0x31, 0x20, 0x4a, 0x23}}
|
||||||
|
FOLDERID_SamplePlaylists = &KNOWNFOLDERID{0x15ca69b3, 0x30ee, 0x49c1, [8]byte{0xac, 0xe1, 0x6b, 0x5e, 0xc3, 0x72, 0xaf, 0xb5}}
|
||||||
|
FOLDERID_SampleMusic = &KNOWNFOLDERID{0xb250c668, 0xf57d, 0x4ee1, [8]byte{0xa6, 0x3c, 0x29, 0x0e, 0xe7, 0xd1, 0xaa, 0x1f}}
|
||||||
|
FOLDERID_SamplePictures = &KNOWNFOLDERID{0xc4900540, 0x2379, 0x4c75, [8]byte{0x84, 0x4b, 0x64, 0xe6, 0xfa, 0xf8, 0x71, 0x6b}}
|
||||||
|
FOLDERID_SampleVideos = &KNOWNFOLDERID{0x859ead94, 0x2e85, 0x48ad, [8]byte{0xa7, 0x1a, 0x09, 0x69, 0xcb, 0x56, 0xa6, 0xcd}}
|
||||||
|
FOLDERID_PhotoAlbums = &KNOWNFOLDERID{0x69d2cf90, 0xfc33, 0x4fb7, [8]byte{0x9a, 0x0c, 0xeb, 0xb0, 0xf0, 0xfc, 0xb4, 0x3c}}
|
||||||
|
FOLDERID_Public = &KNOWNFOLDERID{0xdfdf76a2, 0xc82a, 0x4d63, [8]byte{0x90, 0x6a, 0x56, 0x44, 0xac, 0x45, 0x73, 0x85}}
|
||||||
|
FOLDERID_ChangeRemovePrograms = &KNOWNFOLDERID{0xdf7266ac, 0x9274, 0x4867, [8]byte{0x8d, 0x55, 0x3b, 0xd6, 0x61, 0xde, 0x87, 0x2d}}
|
||||||
|
FOLDERID_AppUpdates = &KNOWNFOLDERID{0xa305ce99, 0xf527, 0x492b, [8]byte{0x8b, 0x1a, 0x7e, 0x76, 0xfa, 0x98, 0xd6, 0xe4}}
|
||||||
|
FOLDERID_AddNewPrograms = &KNOWNFOLDERID{0xde61d971, 0x5ebc, 0x4f02, [8]byte{0xa3, 0xa9, 0x6c, 0x82, 0x89, 0x5e, 0x5c, 0x04}}
|
||||||
|
FOLDERID_Downloads = &KNOWNFOLDERID{0x374de290, 0x123f, 0x4565, [8]byte{0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}}
|
||||||
|
FOLDERID_PublicDownloads = &KNOWNFOLDERID{0x3d644c9b, 0x1fb8, 0x4f30, [8]byte{0x9b, 0x45, 0xf6, 0x70, 0x23, 0x5f, 0x79, 0xc0}}
|
||||||
|
FOLDERID_SavedSearches = &KNOWNFOLDERID{0x7d1d3a04, 0xdebb, 0x4115, [8]byte{0x95, 0xcf, 0x2f, 0x29, 0xda, 0x29, 0x20, 0xda}}
|
||||||
|
FOLDERID_QuickLaunch = &KNOWNFOLDERID{0x52a4f021, 0x7b75, 0x48a9, [8]byte{0x9f, 0x6b, 0x4b, 0x87, 0xa2, 0x10, 0xbc, 0x8f}}
|
||||||
|
FOLDERID_Contacts = &KNOWNFOLDERID{0x56784854, 0xc6cb, 0x462b, [8]byte{0x81, 0x69, 0x88, 0xe3, 0x50, 0xac, 0xb8, 0x82}}
|
||||||
|
FOLDERID_SidebarParts = &KNOWNFOLDERID{0xa75d362e, 0x50fc, 0x4fb7, [8]byte{0xac, 0x2c, 0xa8, 0xbe, 0xaa, 0x31, 0x44, 0x93}}
|
||||||
|
FOLDERID_SidebarDefaultParts = &KNOWNFOLDERID{0x7b396e54, 0x9ec5, 0x4300, [8]byte{0xbe, 0x0a, 0x24, 0x82, 0xeb, 0xae, 0x1a, 0x26}}
|
||||||
|
FOLDERID_PublicGameTasks = &KNOWNFOLDERID{0xdebf2536, 0xe1a8, 0x4c59, [8]byte{0xb6, 0xa2, 0x41, 0x45, 0x86, 0x47, 0x6a, 0xea}}
|
||||||
|
FOLDERID_GameTasks = &KNOWNFOLDERID{0x054fae61, 0x4dd8, 0x4787, [8]byte{0x80, 0xb6, 0x09, 0x02, 0x20, 0xc4, 0xb7, 0x00}}
|
||||||
|
FOLDERID_SavedGames = &KNOWNFOLDERID{0x4c5c32ff, 0xbb9d, 0x43b0, [8]byte{0xb5, 0xb4, 0x2d, 0x72, 0xe5, 0x4e, 0xaa, 0xa4}}
|
||||||
|
FOLDERID_Games = &KNOWNFOLDERID{0xcac52c1a, 0xb53d, 0x4edc, [8]byte{0x92, 0xd7, 0x6b, 0x2e, 0x8a, 0xc1, 0x94, 0x34}}
|
||||||
|
FOLDERID_SEARCH_MAPI = &KNOWNFOLDERID{0x98ec0e18, 0x2098, 0x4d44, [8]byte{0x86, 0x44, 0x66, 0x97, 0x93, 0x15, 0xa2, 0x81}}
|
||||||
|
FOLDERID_SEARCH_CSC = &KNOWNFOLDERID{0xee32e446, 0x31ca, 0x4aba, [8]byte{0x81, 0x4f, 0xa5, 0xeb, 0xd2, 0xfd, 0x6d, 0x5e}}
|
||||||
|
FOLDERID_Links = &KNOWNFOLDERID{0xbfb9d5e0, 0xc6a9, 0x404c, [8]byte{0xb2, 0xb2, 0xae, 0x6d, 0xb6, 0xaf, 0x49, 0x68}}
|
||||||
|
FOLDERID_UsersFiles = &KNOWNFOLDERID{0xf3ce0f7c, 0x4901, 0x4acc, [8]byte{0x86, 0x48, 0xd5, 0xd4, 0x4b, 0x04, 0xef, 0x8f}}
|
||||||
|
FOLDERID_UsersLibraries = &KNOWNFOLDERID{0xa302545d, 0xdeff, 0x464b, [8]byte{0xab, 0xe8, 0x61, 0xc8, 0x64, 0x8d, 0x93, 0x9b}}
|
||||||
|
FOLDERID_SearchHome = &KNOWNFOLDERID{0x190337d1, 0xb8ca, 0x4121, [8]byte{0xa6, 0x39, 0x6d, 0x47, 0x2d, 0x16, 0x97, 0x2a}}
|
||||||
|
FOLDERID_OriginalImages = &KNOWNFOLDERID{0x2c36c0aa, 0x5812, 0x4b87, [8]byte{0xbf, 0xd0, 0x4c, 0xd0, 0xdf, 0xb1, 0x9b, 0x39}}
|
||||||
|
FOLDERID_DocumentsLibrary = &KNOWNFOLDERID{0x7b0db17d, 0x9cd2, 0x4a93, [8]byte{0x97, 0x33, 0x46, 0xcc, 0x89, 0x02, 0x2e, 0x7c}}
|
||||||
|
FOLDERID_MusicLibrary = &KNOWNFOLDERID{0x2112ab0a, 0xc86a, 0x4ffe, [8]byte{0xa3, 0x68, 0x0d, 0xe9, 0x6e, 0x47, 0x01, 0x2e}}
|
||||||
|
FOLDERID_PicturesLibrary = &KNOWNFOLDERID{0xa990ae9f, 0xa03b, 0x4e80, [8]byte{0x94, 0xbc, 0x99, 0x12, 0xd7, 0x50, 0x41, 0x04}}
|
||||||
|
FOLDERID_VideosLibrary = &KNOWNFOLDERID{0x491e922f, 0x5643, 0x4af4, [8]byte{0xa7, 0xeb, 0x4e, 0x7a, 0x13, 0x8d, 0x81, 0x74}}
|
||||||
|
FOLDERID_RecordedTVLibrary = &KNOWNFOLDERID{0x1a6fdba2, 0xf42d, 0x4358, [8]byte{0xa7, 0x98, 0xb7, 0x4d, 0x74, 0x59, 0x26, 0xc5}}
|
||||||
|
FOLDERID_HomeGroup = &KNOWNFOLDERID{0x52528a6b, 0xb9e3, 0x4add, [8]byte{0xb6, 0x0d, 0x58, 0x8c, 0x2d, 0xba, 0x84, 0x2d}}
|
||||||
|
FOLDERID_HomeGroupCurrentUser = &KNOWNFOLDERID{0x9b74b6a3, 0x0dfd, 0x4f11, [8]byte{0x9e, 0x78, 0x5f, 0x78, 0x00, 0xf2, 0xe7, 0x72}}
|
||||||
|
FOLDERID_DeviceMetadataStore = &KNOWNFOLDERID{0x5ce4a5e9, 0xe4eb, 0x479d, [8]byte{0xb8, 0x9f, 0x13, 0x0c, 0x02, 0x88, 0x61, 0x55}}
|
||||||
|
FOLDERID_Libraries = &KNOWNFOLDERID{0x1b3ea5dc, 0xb587, 0x4786, [8]byte{0xb4, 0xef, 0xbd, 0x1d, 0xc3, 0x32, 0xae, 0xae}}
|
||||||
|
FOLDERID_PublicLibraries = &KNOWNFOLDERID{0x48daf80b, 0xe6cf, 0x4f4e, [8]byte{0xb8, 0x00, 0x0e, 0x69, 0xd8, 0x4e, 0xe3, 0x84}}
|
||||||
|
FOLDERID_UserPinned = &KNOWNFOLDERID{0x9e3995ab, 0x1f9c, 0x4f13, [8]byte{0xb8, 0x27, 0x48, 0xb2, 0x4b, 0x6c, 0x71, 0x74}}
|
||||||
|
FOLDERID_ImplicitAppShortcuts = &KNOWNFOLDERID{0xbcb5256f, 0x79f6, 0x4cee, [8]byte{0xb7, 0x25, 0xdc, 0x34, 0xe4, 0x02, 0xfd, 0x46}}
|
||||||
|
FOLDERID_AccountPictures = &KNOWNFOLDERID{0x008ca0b1, 0x55b4, 0x4c56, [8]byte{0xb8, 0xa8, 0x4d, 0xe4, 0xb2, 0x99, 0xd3, 0xbe}}
|
||||||
|
FOLDERID_PublicUserTiles = &KNOWNFOLDERID{0x0482af6c, 0x08f1, 0x4c34, [8]byte{0x8c, 0x90, 0xe1, 0x7e, 0xc9, 0x8b, 0x1e, 0x17}}
|
||||||
|
FOLDERID_AppsFolder = &KNOWNFOLDERID{0x1e87508d, 0x89c2, 0x42f0, [8]byte{0x8a, 0x7e, 0x64, 0x5a, 0x0f, 0x50, 0xca, 0x58}}
|
||||||
|
FOLDERID_StartMenuAllPrograms = &KNOWNFOLDERID{0xf26305ef, 0x6948, 0x40b9, [8]byte{0xb2, 0x55, 0x81, 0x45, 0x3d, 0x09, 0xc7, 0x85}}
|
||||||
|
FOLDERID_CommonStartMenuPlaces = &KNOWNFOLDERID{0xa440879f, 0x87a0, 0x4f7d, [8]byte{0xb7, 0x00, 0x02, 0x07, 0xb9, 0x66, 0x19, 0x4a}}
|
||||||
|
FOLDERID_ApplicationShortcuts = &KNOWNFOLDERID{0xa3918781, 0xe5f2, 0x4890, [8]byte{0xb3, 0xd9, 0xa7, 0xe5, 0x43, 0x32, 0x32, 0x8c}}
|
||||||
|
FOLDERID_RoamingTiles = &KNOWNFOLDERID{0x00bcfc5a, 0xed94, 0x4e48, [8]byte{0x96, 0xa1, 0x3f, 0x62, 0x17, 0xf2, 0x19, 0x90}}
|
||||||
|
FOLDERID_RoamedTileImages = &KNOWNFOLDERID{0xaaa8d5a5, 0xf1d6, 0x4259, [8]byte{0xba, 0xa8, 0x78, 0xe7, 0xef, 0x60, 0x83, 0x5e}}
|
||||||
|
FOLDERID_Screenshots = &KNOWNFOLDERID{0xb7bede81, 0xdf94, 0x4682, [8]byte{0xa7, 0xd8, 0x57, 0xa5, 0x26, 0x20, 0xb8, 0x6f}}
|
||||||
|
FOLDERID_CameraRoll = &KNOWNFOLDERID{0xab5fb87b, 0x7ce2, 0x4f83, [8]byte{0x91, 0x5d, 0x55, 0x08, 0x46, 0xc9, 0x53, 0x7b}}
|
||||||
|
FOLDERID_SkyDrive = &KNOWNFOLDERID{0xa52bba46, 0xe9e1, 0x435f, [8]byte{0xb3, 0xd9, 0x28, 0xda, 0xa6, 0x48, 0xc0, 0xf6}}
|
||||||
|
FOLDERID_OneDrive = &KNOWNFOLDERID{0xa52bba46, 0xe9e1, 0x435f, [8]byte{0xb3, 0xd9, 0x28, 0xda, 0xa6, 0x48, 0xc0, 0xf6}}
|
||||||
|
FOLDERID_SkyDriveDocuments = &KNOWNFOLDERID{0x24d89e24, 0x2f19, 0x4534, [8]byte{0x9d, 0xde, 0x6a, 0x66, 0x71, 0xfb, 0xb8, 0xfe}}
|
||||||
|
FOLDERID_SkyDrivePictures = &KNOWNFOLDERID{0x339719b5, 0x8c47, 0x4894, [8]byte{0x94, 0xc2, 0xd8, 0xf7, 0x7a, 0xdd, 0x44, 0xa6}}
|
||||||
|
FOLDERID_SkyDriveMusic = &KNOWNFOLDERID{0xc3f2459e, 0x80d6, 0x45dc, [8]byte{0xbf, 0xef, 0x1f, 0x76, 0x9f, 0x2b, 0xe7, 0x30}}
|
||||||
|
FOLDERID_SkyDriveCameraRoll = &KNOWNFOLDERID{0x767e6811, 0x49cb, 0x4273, [8]byte{0x87, 0xc2, 0x20, 0xf3, 0x55, 0xe1, 0x08, 0x5b}}
|
||||||
|
FOLDERID_SearchHistory = &KNOWNFOLDERID{0x0d4c3db6, 0x03a3, 0x462f, [8]byte{0xa0, 0xe6, 0x08, 0x92, 0x4c, 0x41, 0xb5, 0xd4}}
|
||||||
|
FOLDERID_SearchTemplates = &KNOWNFOLDERID{0x7e636bfe, 0xdfa9, 0x4d5e, [8]byte{0xb4, 0x56, 0xd7, 0xb3, 0x98, 0x51, 0xd8, 0xa9}}
|
||||||
|
FOLDERID_CameraRollLibrary = &KNOWNFOLDERID{0x2b20df75, 0x1eda, 0x4039, [8]byte{0x80, 0x97, 0x38, 0x79, 0x82, 0x27, 0xd5, 0xb7}}
|
||||||
|
FOLDERID_SavedPictures = &KNOWNFOLDERID{0x3b193882, 0xd3ad, 0x4eab, [8]byte{0x96, 0x5a, 0x69, 0x82, 0x9d, 0x1f, 0xb5, 0x9f}}
|
||||||
|
FOLDERID_SavedPicturesLibrary = &KNOWNFOLDERID{0xe25b5812, 0xbe88, 0x4bd9, [8]byte{0x94, 0xb0, 0x29, 0x23, 0x34, 0x77, 0xb6, 0xc3}}
|
||||||
|
FOLDERID_RetailDemo = &KNOWNFOLDERID{0x12d4c69e, 0x24ad, 0x4923, [8]byte{0xbe, 0x19, 0x31, 0x32, 0x1c, 0x43, 0xa7, 0x67}}
|
||||||
|
FOLDERID_Device = &KNOWNFOLDERID{0x1c2ac1dc, 0x4358, 0x4b6c, [8]byte{0x97, 0x33, 0xaf, 0x21, 0x15, 0x65, 0x76, 0xf0}}
|
||||||
|
FOLDERID_DevelopmentFiles = &KNOWNFOLDERID{0xdbe8e08e, 0x3053, 0x4bbc, [8]byte{0xb1, 0x83, 0x2a, 0x7b, 0x2b, 0x19, 0x1e, 0x59}}
|
||||||
|
FOLDERID_Objects3D = &KNOWNFOLDERID{0x31c0dd25, 0x9439, 0x4f12, [8]byte{0xbf, 0x41, 0x7f, 0xf4, 0xed, 0xa3, 0x87, 0x22}}
|
||||||
|
FOLDERID_AppCaptures = &KNOWNFOLDERID{0xedc0fe71, 0x98d8, 0x4f4a, [8]byte{0xb9, 0x20, 0xc8, 0xdc, 0x13, 0x3c, 0xb1, 0x65}}
|
||||||
|
FOLDERID_LocalDocuments = &KNOWNFOLDERID{0xf42ee2d3, 0x909f, 0x4907, [8]byte{0x88, 0x71, 0x4c, 0x22, 0xfc, 0x0b, 0xf7, 0x56}}
|
||||||
|
FOLDERID_LocalPictures = &KNOWNFOLDERID{0x0ddd015d, 0xb06c, 0x45d5, [8]byte{0x8c, 0x4c, 0xf5, 0x97, 0x13, 0x85, 0x46, 0x39}}
|
||||||
|
FOLDERID_LocalVideos = &KNOWNFOLDERID{0x35286a68, 0x3c57, 0x41a1, [8]byte{0xbb, 0xb1, 0x0e, 0xae, 0x73, 0xd7, 0x6c, 0x95}}
|
||||||
|
FOLDERID_LocalMusic = &KNOWNFOLDERID{0xa0c69a99, 0x21c8, 0x4671, [8]byte{0x87, 0x03, 0x79, 0x34, 0x16, 0x2f, 0xcf, 0x1d}}
|
||||||
|
FOLDERID_LocalDownloads = &KNOWNFOLDERID{0x7d83ee9b, 0x2244, 0x4e70, [8]byte{0xb1, 0xf5, 0x53, 0x93, 0x04, 0x2a, 0xf1, 0xe4}}
|
||||||
|
FOLDERID_RecordedCalls = &KNOWNFOLDERID{0x2f8b40c2, 0x83ed, 0x48ee, [8]byte{0xb3, 0x83, 0xa1, 0xf1, 0x57, 0xec, 0x6f, 0x9a}}
|
||||||
|
FOLDERID_AllAppMods = &KNOWNFOLDERID{0x7ad67899, 0x66af, 0x43ba, [8]byte{0x91, 0x56, 0x6a, 0xad, 0x42, 0xe6, 0xc5, 0x96}}
|
||||||
|
FOLDERID_CurrentAppMods = &KNOWNFOLDERID{0x3db40b20, 0x2a30, 0x4dbe, [8]byte{0x91, 0x7e, 0x77, 0x1d, 0xd2, 0x1d, 0xd0, 0x99}}
|
||||||
|
FOLDERID_AppDataDesktop = &KNOWNFOLDERID{0xb2c5e279, 0x7add, 0x439f, [8]byte{0xb2, 0x8c, 0xc4, 0x1f, 0xe1, 0xbb, 0xf6, 0x72}}
|
||||||
|
FOLDERID_AppDataDocuments = &KNOWNFOLDERID{0x7be16610, 0x1f7f, 0x44ac, [8]byte{0xbf, 0xf0, 0x83, 0xe1, 0x5f, 0x2f, 0xfc, 0xa1}}
|
||||||
|
FOLDERID_AppDataFavorites = &KNOWNFOLDERID{0x7cfbefbc, 0xde1f, 0x45aa, [8]byte{0xb8, 0x43, 0xa5, 0x42, 0xac, 0x53, 0x6c, 0xc9}}
|
||||||
|
FOLDERID_AppDataProgramData = &KNOWNFOLDERID{0x559d40a3, 0xa036, 0x40fa, [8]byte{0xaf, 0x61, 0x84, 0xcb, 0x43, 0x0a, 0x4d, 0x34}}
|
||||||
|
)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
# git.rootprojects.org/root/go-gitver v1.1.3
|
||||||
|
git.rootprojects.org/root/go-gitver
|
||||||
|
git.rootprojects.org/root/go-gitver/gitver
|
||||||
|
# golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7
|
||||||
|
golang.org/x/sys/windows/registry
|
||||||
|
golang.org/x/sys/windows
|
Loading…
Reference in New Issue