AJ ONeal
5 years ago
43 changed files with 16941 additions and 0 deletions
@ -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
File diff suppressed because it is too large
@ -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
@ -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
@ -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