mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
Desktop integration (#2073)
* Open stash in system tray on Windows/MacOS * Add desktop notifications * MacOS Bundling * Add binary icon Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
parent
e48b2ba3e8
commit
0e514183a7
306 changed files with 29542 additions and 4792 deletions
21
.github/workflows/build.yml
vendored
21
.github/workflows/build.yml
vendored
|
|
@ -13,7 +13,7 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
COMPILER_IMAGE: stashapp/compiler:5
|
COMPILER_IMAGE: stashapp/compiler:6
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
@ -91,12 +91,11 @@ jobs:
|
||||||
- name: Compile for all supported platforms
|
- name: Compile for all supported platforms
|
||||||
run: |
|
run: |
|
||||||
docker exec -t build /bin/bash -c "make cross-compile-windows"
|
docker exec -t build /bin/bash -c "make cross-compile-windows"
|
||||||
docker exec -t build /bin/bash -c "make cross-compile-osx-intel"
|
docker exec -t build /bin/bash -c "make cross-compile-macos"
|
||||||
docker exec -t build /bin/bash -c "make cross-compile-osx-applesilicon"
|
|
||||||
docker exec -t build /bin/bash -c "make cross-compile-linux"
|
docker exec -t build /bin/bash -c "make cross-compile-linux"
|
||||||
docker exec -t build /bin/bash -c "make cross-compile-linux-arm64v8"
|
docker exec -t build /bin/bash -c "make cross-compile-linux-arm64v8"
|
||||||
docker exec -t build /bin/bash -c "make cross-compile-linux-arm32v7"
|
docker exec -t build /bin/bash -c "make cross-compile-linux-arm32v7"
|
||||||
docker exec -t build /bin/bash -c "make cross-compile-pi"
|
docker exec -t build /bin/bash -c "make cross-compile-linux-arm32v6"
|
||||||
|
|
||||||
- name: Cleanup build container
|
- name: Cleanup build container
|
||||||
run: docker rm -f -v build
|
run: docker rm -f -v build
|
||||||
|
|
@ -121,8 +120,8 @@ jobs:
|
||||||
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
|
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: stash-osx
|
name: Stash-macos.zip
|
||||||
path: dist/stash-osx
|
path: dist/Stash-macos.zip
|
||||||
|
|
||||||
- name: Upload Linux binary
|
- name: Upload Linux binary
|
||||||
# only upload binaries for pull requests
|
# only upload binaries for pull requests
|
||||||
|
|
@ -145,13 +144,12 @@ jobs:
|
||||||
automatic_release_tag: latest_develop
|
automatic_release_tag: latest_develop
|
||||||
title: "${{ env.STASH_VERSION }}: Latest development build"
|
title: "${{ env.STASH_VERSION }}: Latest development build"
|
||||||
files: |
|
files: |
|
||||||
dist/stash-osx
|
dist/Stash-macos.zip
|
||||||
dist/stash-osx-applesilicon
|
|
||||||
dist/stash-win.exe
|
dist/stash-win.exe
|
||||||
dist/stash-linux
|
dist/stash-linux
|
||||||
dist/stash-linux-arm64v8
|
dist/stash-linux-arm64v8
|
||||||
dist/stash-linux-arm32v7
|
dist/stash-linux-arm32v7
|
||||||
dist/stash-pi
|
dist/stash-linux-arm32v6
|
||||||
CHECKSUMS_SHA1
|
CHECKSUMS_SHA1
|
||||||
|
|
||||||
- name: Master release
|
- name: Master release
|
||||||
|
|
@ -161,13 +159,12 @@ jobs:
|
||||||
token: "${{ secrets.GITHUB_TOKEN }}"
|
token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
allow_override: true
|
allow_override: true
|
||||||
files: |
|
files: |
|
||||||
dist/stash-osx
|
dist/Stash-macos.zip
|
||||||
dist/stash-osx-applesilicon
|
|
||||||
dist/stash-win.exe
|
dist/stash-win.exe
|
||||||
dist/stash-linux
|
dist/stash-linux
|
||||||
dist/stash-linux-arm64v8
|
dist/stash-linux-arm64v8
|
||||||
dist/stash-linux-arm32v7
|
dist/stash-linux-arm32v7
|
||||||
dist/stash-pi
|
dist/stash-linux-arm32v6
|
||||||
CHECKSUMS_SHA1
|
CHECKSUMS_SHA1
|
||||||
gzip: false
|
gzip: false
|
||||||
|
|
||||||
|
|
|
||||||
2
.github/workflows/golangci-lint.yml
vendored
2
.github/workflows/golangci-lint.yml
vendored
|
|
@ -9,7 +9,7 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
COMPILER_IMAGE: stashapp/compiler:5
|
COMPILER_IMAGE: stashapp/compiler:6
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
golangci:
|
golangci:
|
||||||
|
|
|
||||||
77
Makefile
77
Makefile
|
|
@ -1,12 +1,12 @@
|
||||||
IS_WIN =
|
IS_WIN_SHELL =
|
||||||
ifeq (${SHELL}, sh.exe)
|
ifeq (${SHELL}, sh.exe)
|
||||||
IS_WIN = true
|
IS_WIN_SHELL = true
|
||||||
endif
|
endif
|
||||||
ifeq (${SHELL}, cmd)
|
ifeq (${SHELL}, cmd)
|
||||||
IS_WIN = true
|
IS_WIN_SHELL = true
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef IS_WIN
|
ifdef IS_WIN_SHELL
|
||||||
SEPARATOR := &&
|
SEPARATOR := &&
|
||||||
SET := set
|
SET := set
|
||||||
else
|
else
|
||||||
|
|
@ -14,6 +14,11 @@ else
|
||||||
SET := export
|
SET := export
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
IS_WIN_OS =
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
IS_WIN_OS = true
|
||||||
|
endif
|
||||||
|
|
||||||
# set LDFLAGS environment variable to any extra ldflags required
|
# set LDFLAGS environment variable to any extra ldflags required
|
||||||
# set OUTPUT to generate a specific binary name
|
# set OUTPUT to generate a specific binary name
|
||||||
|
|
||||||
|
|
@ -46,9 +51,13 @@ ifndef OFFICIAL_BUILD
|
||||||
endif
|
endif
|
||||||
|
|
||||||
build: pre-build
|
build: pre-build
|
||||||
|
ifdef IS_WIN_OS
|
||||||
|
PLATFORM_SPECIFIC_LDFLAGS := -H windowsgui
|
||||||
|
endif
|
||||||
|
build:
|
||||||
$(eval LDFLAGS := $(LDFLAGS) -X 'github.com/stashapp/stash/pkg/api.version=$(STASH_VERSION)' -X 'github.com/stashapp/stash/pkg/api.buildstamp=$(BUILD_DATE)' -X 'github.com/stashapp/stash/pkg/api.githash=$(GITHASH)')
|
$(eval LDFLAGS := $(LDFLAGS) -X 'github.com/stashapp/stash/pkg/api.version=$(STASH_VERSION)' -X 'github.com/stashapp/stash/pkg/api.buildstamp=$(BUILD_DATE)' -X 'github.com/stashapp/stash/pkg/api.githash=$(GITHASH)')
|
||||||
$(eval LDFLAGS := $(LDFLAGS) -X 'github.com/stashapp/stash/pkg/api.officialBuild=$(OFFICIAL_BUILD)')
|
$(eval LDFLAGS := $(LDFLAGS) -X 'github.com/stashapp/stash/pkg/manager/config.officialBuild=$(OFFICIAL_BUILD)')
|
||||||
go build $(OUTPUT) -mod=vendor -v -tags "sqlite_omit_load_extension osusergo netgo" $(GO_BUILD_FLAGS) -ldflags "$(LDFLAGS) $(EXTRA_LDFLAGS)"
|
go build $(OUTPUT) -mod=vendor -v -tags "sqlite_omit_load_extension osusergo netgo" $(GO_BUILD_FLAGS) -ldflags "$(LDFLAGS) $(EXTRA_LDFLAGS) $(PLATFORM_SPECIFIC_LDFLAGS)"
|
||||||
|
|
||||||
# strips debug symbols from the release build
|
# strips debug symbols from the release build
|
||||||
build-release: EXTRA_LDFLAGS := -s -w
|
build-release: EXTRA_LDFLAGS := -s -w
|
||||||
|
|
@ -65,23 +74,38 @@ cross-compile-windows: export GOARCH := amd64
|
||||||
cross-compile-windows: export CC := x86_64-w64-mingw32-gcc
|
cross-compile-windows: export CC := x86_64-w64-mingw32-gcc
|
||||||
cross-compile-windows: export CXX := x86_64-w64-mingw32-g++
|
cross-compile-windows: export CXX := x86_64-w64-mingw32-g++
|
||||||
cross-compile-windows: OUTPUT := -o dist/stash-win.exe
|
cross-compile-windows: OUTPUT := -o dist/stash-win.exe
|
||||||
|
cross-compile-windows: PLATFORM_SPECIFIC_LDFLAGS := -H windowsgui
|
||||||
cross-compile-windows: build-release-static
|
cross-compile-windows: build-release-static
|
||||||
|
|
||||||
cross-compile-osx-intel: export GOOS := darwin
|
cross-compile-macos-intel: export GOOS := darwin
|
||||||
cross-compile-osx-intel: export GOARCH := amd64
|
cross-compile-macos-intel: export GOARCH := amd64
|
||||||
cross-compile-osx-intel: export CC := o64-clang
|
cross-compile-macos-intel: export CC := o64-clang
|
||||||
cross-compile-osx-intel: export CXX := o64-clang++
|
cross-compile-macos-intel: export CXX := o64-clang++
|
||||||
cross-compile-osx-intel: OUTPUT := -o dist/stash-osx
|
cross-compile-macos-intel: OUTPUT := -o dist/stash-macos-intel
|
||||||
# can't use static build for OSX
|
# can't use static build for OSX
|
||||||
cross-compile-osx-intel: build-release
|
cross-compile-macos-intel: build-release
|
||||||
|
|
||||||
cross-compile-osx-applesilicon: export GOOS := darwin
|
cross-compile-macos-applesilicon: export GOOS := darwin
|
||||||
cross-compile-osx-applesilicon: export GOARCH := arm64
|
cross-compile-macos-applesilicon: export GOARCH := arm64
|
||||||
cross-compile-osx-applesilicon: export CC := oa64e-clang
|
cross-compile-macos-applesilicon: export CC := oa64e-clang
|
||||||
cross-compile-osx-applesilicon: export CXX := oa64e-clang++
|
cross-compile-macos-applesilicon: export CXX := oa64e-clang++
|
||||||
cross-compile-osx-applesilicon: OUTPUT := -o dist/stash-osx-applesilicon
|
cross-compile-macos-applesilicon: OUTPUT := -o dist/stash-macos-applesilicon
|
||||||
# can't use static build for OSX
|
# can't use static build for OSX
|
||||||
cross-compile-osx-applesilicon: build-release
|
cross-compile-macos-applesilicon: build-release
|
||||||
|
|
||||||
|
cross-compile-macos:
|
||||||
|
rm -rf dist/Stash.app dist/Stash-macos.zip
|
||||||
|
make cross-compile-macos-applesilicon
|
||||||
|
make cross-compile-macos-intel
|
||||||
|
# Combine into one universal binary
|
||||||
|
lipo -create -output dist/stash-macos-universal dist/stash-macos-intel dist/stash-macos-applesilicon
|
||||||
|
rm dist/stash-macos-intel dist/stash-macos-applesilicon
|
||||||
|
# Place into bundle and zip up
|
||||||
|
cp -R scripts/macos-bundle dist/Stash.app
|
||||||
|
mkdir dist/Stash.app/Contents/MacOS
|
||||||
|
mv dist/stash-macos-universal dist/Stash.app/Contents/MacOS/stash
|
||||||
|
cd dist && zip -r Stash-macos.zip Stash.app && cd ..
|
||||||
|
rm -rf dist/Stash.app
|
||||||
|
|
||||||
cross-compile-linux: export GOOS := linux
|
cross-compile-linux: export GOOS := linux
|
||||||
cross-compile-linux: export GOARCH := amd64
|
cross-compile-linux: export GOARCH := amd64
|
||||||
|
|
@ -101,21 +125,20 @@ cross-compile-linux-arm32v7: export CC := arm-linux-gnueabihf-gcc
|
||||||
cross-compile-linux-arm32v7: OUTPUT := -o dist/stash-linux-arm32v7
|
cross-compile-linux-arm32v7: OUTPUT := -o dist/stash-linux-arm32v7
|
||||||
cross-compile-linux-arm32v7: build-release-static
|
cross-compile-linux-arm32v7: build-release-static
|
||||||
|
|
||||||
cross-compile-pi: export GOOS := linux
|
cross-compile-linux-arm32v6: export GOOS := linux
|
||||||
cross-compile-pi: export GOARCH := arm
|
cross-compile-linux-arm32v6: export GOARCH := arm
|
||||||
cross-compile-pi: export GOARM := 6
|
cross-compile-linux-arm32v6: export GOARM := 6
|
||||||
cross-compile-pi: export CC := arm-linux-gnueabi-gcc
|
cross-compile-linux-arm32v6: export CC := arm-linux-gnueabi-gcc
|
||||||
cross-compile-pi: OUTPUT := -o dist/stash-pi
|
cross-compile-linux-arm32v6: OUTPUT := -o dist/stash-linux-arm32v6
|
||||||
cross-compile-pi: build-release-static
|
cross-compile-linux-arm32v6: build-release-static
|
||||||
|
|
||||||
cross-compile-all:
|
cross-compile-all:
|
||||||
make cross-compile-windows
|
make cross-compile-windows
|
||||||
make cross-compile-osx-intel
|
make cross-compile-macos
|
||||||
make cross-compile-osx-applesilicon
|
|
||||||
make cross-compile-linux
|
make cross-compile-linux
|
||||||
make cross-compile-linux-arm64v8
|
make cross-compile-linux-arm64v8
|
||||||
make cross-compile-linux-arm32v7
|
make cross-compile-linux-arm32v7
|
||||||
make cross-compile-pi
|
make cross-compile-linux-arm32v6
|
||||||
|
|
||||||
# Regenerates GraphQL files
|
# Regenerates GraphQL files
|
||||||
generate: generate-backend generate-frontend
|
generate: generate-backend generate-frontend
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,14 @@ For further information you can [read the in-app manual](ui/v2.5/src/docs/en).
|
||||||
|
|
||||||
<img src="docs/readme_assets/windows_logo.svg" width="100%" height="75"> Windows | <img src="docs/readme_assets/mac_logo.svg" width="100%" height="75"> MacOS| <img src="docs/readme_assets/linux_logo.svg" width="100%" height="75"> Linux | <img src="docs/readme_assets/docker_logo.svg" width="100%" height="75"> Docker
|
<img src="docs/readme_assets/windows_logo.svg" width="100%" height="75"> Windows | <img src="docs/readme_assets/mac_logo.svg" width="100%" height="75"> MacOS| <img src="docs/readme_assets/linux_logo.svg" width="100%" height="75"> Linux | <img src="docs/readme_assets/docker_logo.svg" width="100%" height="75"> Docker
|
||||||
:---:|:---:|:---:|:---:
|
:---:|:---:|:---:|:---:
|
||||||
[Latest Release](https://github.com/stashapp/stash/releases/latest/download/stash-win.exe) <br /> <sup><sub>[Development Preview](https://github.com/stashapp/stash/releases/download/latest_develop/stash-win.exe)</sub></sup> | [Latest Release (Apple Silicon)](https://github.com/stashapp/stash/releases/latest/download/stash-osx-applesilicon) <br /> <sup><sub>[Development Preview (Apple Silicon)](https://github.com/stashapp/stash/releases/download/latest_develop/stash-osx-applesilicon)</sub></sup> <br>[Latest Release (Intel)](https://github.com/stashapp/stash/releases/latest/download/stash-osx) <br /> <sup><sub>[Development Preview (Intel)](https://github.com/stashapp/stash/releases/download/latest_develop/stash-osx)</sub></sup> | [Latest Release (amd64)](https://github.com/stashapp/stash/releases/latest/download/stash-linux) <br /> <sup><sub>[Development Preview (amd64)](https://github.com/stashapp/stash/releases/download/latest_develop/stash-linux)</sub></sup> <br /> [More Architectures...](https://github.com/stashapp/stash/releases/latest) | [Instructions](docker/production/README.md) <br /> <sup><sub> [Sample docker-compose.yml](docker/production/docker-compose.yml)</sub></sup>
|
[Latest Release](https://github.com/stashapp/stash/releases/latest/download/stash-win.exe) <br /> <sup><sub>[Development Preview](https://github.com/stashapp/stash/releases/download/latest_develop/stash-win.exe)</sub></sup> | [Latest Release](https://github.com/stashapp/stash/releases/latest/download/Stash-macos.app.zip) <br /> <sup><sub>[Development Preview](https://github.com/stashapp/stash/releases/download/latest_develop/Stash-macos.app.zip)</sub></sup> | [Latest Release (amd64)](https://github.com/stashapp/stash/releases/latest/download/stash-linux) <br /> <sup><sub>[Development Preview (amd64)](https://github.com/stashapp/stash/releases/download/latest_develop/stash-linux)</sub></sup> <br /> [More Architectures...](https://github.com/stashapp/stash/releases/latest) | [Instructions](docker/production/README.md) <br /> <sup><sub> [Sample docker-compose.yml](docker/production/docker-compose.yml)</sub></sup>
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
Run the executable (double click the exe on windows or run `./stash-osx` / `./stash-linux` from the terminal on macOS / Linux) to get started.
|
Run the executable by double-clicking it.
|
||||||
|
|
||||||
*Note for Windows users:* Running the app might present a security prompt since the binary isn't yet signed. Bypass this by clicking "more info" and then the "run anyway" button.
|
*Note for Mac users:* Running the app will present a security prompt since the binary isn't yet signed. Bypass this by right (ctrl) clicking on the app and hitting "Open", then "Open" in the next popup.
|
||||||
|
|
||||||
|
*Note for Windows users:* Running the app might present a security prompt since the binary isn't yet signed. Bypass this by clicking "more info" and then the "run anyway" button.
|
||||||
|
|
||||||
#### FFMPEG
|
#### FFMPEG
|
||||||
Stash requires ffmpeg. If you don't have it installed, Stash will download a copy for you. It is recommended that Linux users install `ffmpeg` from their distro's package manager.
|
Stash requires ffmpeg. If you don't have it installed, Stash will download a copy for you. It is recommended that Linux users install `ffmpeg` from their distro's package manager.
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ RUN apt-get update && \
|
||||||
gcc-arm-linux-gnueabi libc-dev-armel-cross linux-libc-dev-armel-cross \
|
gcc-arm-linux-gnueabi libc-dev-armel-cross linux-libc-dev-armel-cross \
|
||||||
gcc-arm-linux-gnueabihf libc-dev-armhf-cross \
|
gcc-arm-linux-gnueabihf libc-dev-armhf-cross \
|
||||||
gcc-aarch64-linux-gnu libc-dev-arm64-cross \
|
gcc-aarch64-linux-gnu libc-dev-arm64-cross \
|
||||||
nodejs yarn --no-install-recommends || exit 1; \
|
nodejs yarn zip --no-install-recommends || exit 1; \
|
||||||
rm -rf /var/lib/apt/lists/*;
|
rm -rf /var/lib/apt/lists/*;
|
||||||
|
|
||||||
# Cross compile setup
|
# Cross compile setup
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
user=stashapp
|
user=stashapp
|
||||||
repo=compiler
|
repo=compiler
|
||||||
version=5
|
version=6
|
||||||
|
|
||||||
latest:
|
latest:
|
||||||
docker build -t ${user}/${repo}:latest .
|
docker build -t ${user}/${repo}:latest .
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
Modified from https://github.com/bep/dockerfiles/tree/master/ci-goreleaser
|
Modified from https://github.com/bep/dockerfiles/tree/master/ci-goreleaser
|
||||||
|
|
||||||
When the dockerfile is changed, the version number should be incremented in the Makefile and the new version tag should be pushed to docker hub. The `scripts/cross-compile.sh` script should also be updated to use the new version number tag, and `.travis.yml` needs to be updated to pull the correct image tag.
|
When the dockerfile is changed, the version number should be incremented in the Makefile and the new version tag should be pushed to docker hub. The `scripts/cross-compile.sh` script should also be updated to use the new version number tag, and the github workflow files need to be updated to pull the correct image tag.
|
||||||
|
|
||||||
A MacOS univeral binary can be created using `lipo -create -output stash-osx-universal stash-osx stash-osx-applesilicon`, available in the image.
|
|
||||||
|
|
|
||||||
14
go.mod
14
go.mod
|
|
@ -38,8 +38,8 @@ require (
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
|
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
|
||||||
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9
|
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b
|
||||||
golang.org/x/text v0.3.7
|
golang.org/x/text v0.3.7
|
||||||
golang.org/x/tools v0.1.5 // indirect
|
golang.org/x/tools v0.1.5 // indirect
|
||||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||||
|
|
@ -47,6 +47,11 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/apenwarr/fixconsole v0.0.0-20191012055117-5a9f6489cc29
|
||||||
|
github.com/go-chi/httplog v0.2.1
|
||||||
|
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4
|
||||||
|
github.com/kermieisinthehouse/gosx-notifier v0.1.1
|
||||||
|
github.com/kermieisinthehouse/systray v1.2.3
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||||
github.com/vearutop/statigz v1.1.6
|
github.com/vearutop/statigz v1.1.6
|
||||||
github.com/vektah/gqlparser/v2 v2.0.1
|
github.com/vektah/gqlparser/v2 v2.0.1
|
||||||
|
|
@ -55,10 +60,12 @@ require (
|
||||||
require (
|
require (
|
||||||
github.com/agnivade/levenshtein v1.1.0 // indirect
|
github.com/agnivade/levenshtein v1.1.0 // indirect
|
||||||
github.com/antchfx/xpath v1.2.0 // indirect
|
github.com/antchfx/xpath v1.2.0 // indirect
|
||||||
|
github.com/apenwarr/w32 v0.0.0-20190407065021-aa00fece76ab // indirect
|
||||||
github.com/chromedp/sysutil v1.0.0 // indirect
|
github.com/chromedp/sysutil v1.0.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||||
|
github.com/go-chi/chi/v5 v5.0.0 // indirect
|
||||||
github.com/gobwas/httphead v0.1.0 // indirect
|
github.com/gobwas/httphead v0.1.0 // indirect
|
||||||
github.com/gobwas/pool v0.2.1 // indirect
|
github.com/gobwas/pool v0.2.1 // indirect
|
||||||
github.com/gobwas/ws v1.1.0-rc.5 // indirect
|
github.com/gobwas/ws v1.1.0-rc.5 // indirect
|
||||||
|
|
@ -77,10 +84,11 @@ require (
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||||
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rs/zerolog v1.18.0 // indirect
|
github.com/rs/zerolog v1.18.1-0.20200514152719-663cbb4c8469 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||||
github.com/spf13/cast v1.4.1 // indirect
|
github.com/spf13/cast v1.4.1 // indirect
|
||||||
|
|
|
||||||
24
go.sum
24
go.sum
|
|
@ -88,6 +88,10 @@ github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwq
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0=
|
github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0=
|
||||||
github.com/apache/arrow/go/arrow v0.0.0-20210521153258-78c88a9f517b/go.mod h1:R4hW3Ug0s+n4CUsWHKOj00Pu01ZqU4x/hSF5kXUcXKQ=
|
github.com/apache/arrow/go/arrow v0.0.0-20210521153258-78c88a9f517b/go.mod h1:R4hW3Ug0s+n4CUsWHKOj00Pu01ZqU4x/hSF5kXUcXKQ=
|
||||||
|
github.com/apenwarr/fixconsole v0.0.0-20191012055117-5a9f6489cc29 h1:muXWUcay7DDy1/hEQWrYlBy+g0EuwT70sBHg65SeUc4=
|
||||||
|
github.com/apenwarr/fixconsole v0.0.0-20191012055117-5a9f6489cc29/go.mod h1:JYWahgHer+Z2xbsgHPtaDYVWzeHDminu+YIBWkxpCAY=
|
||||||
|
github.com/apenwarr/w32 v0.0.0-20190407065021-aa00fece76ab h1:CMGzRRCjnD50RjUFSArBLuCxiDvdp7b8YPAcikBEQ+k=
|
||||||
|
github.com/apenwarr/w32 v0.0.0-20190407065021-aa00fece76ab/go.mod h1:nfFtvHn2Hgs9G1u0/J6LHQv//EksNC+7G8vXmd1VTJ8=
|
||||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
|
|
@ -214,6 +218,10 @@ github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1T
|
||||||
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||||
github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=
|
github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=
|
||||||
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||||
|
github.com/go-chi/chi/v5 v5.0.0 h1:DBPx88FjZJH3FsICfDAfIfnb7XxKIYVGG6lOPlhENAg=
|
||||||
|
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||||
|
github.com/go-chi/httplog v0.2.1 h1:KgCtIUkYNlfIsUPzE3utxd1KDKOvCrnAKaqdo0rmrh0=
|
||||||
|
github.com/go-chi/httplog v0.2.1/go.mod h1:JyHOFO9twSfGoTin/RoP25Lx2a9Btq10ug+sgxe0+bo=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
|
@ -224,6 +232,8 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 h1:qZNfIGkIANxGv/OqtnntR4DfOY2+BgwR60cAcu/i3SE=
|
||||||
|
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4/go.mod h1:kW3HQ4UdaAyrUCSSDR4xUzBKW6O2iA4uHhk7AtyYp10=
|
||||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
||||||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
|
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
|
||||||
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
|
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
|
||||||
|
|
@ -484,6 +494,10 @@ github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALr
|
||||||
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
|
github.com/kermieisinthehouse/gosx-notifier v0.1.1 h1:lVXyKsa1c1RUkckp3KayloNLoI//fUwVYye3RPSPtEw=
|
||||||
|
github.com/kermieisinthehouse/gosx-notifier v0.1.1/go.mod h1:xyWT07azFtUOcHl96qMVvKhvKzsMcS7rKTHQyv8WTho=
|
||||||
|
github.com/kermieisinthehouse/systray v1.2.3 h1:tawLahcam/Ccs/F2n6EOQo8qJnSTD2hLzOYqTGsUsbA=
|
||||||
|
github.com/kermieisinthehouse/systray v1.2.3/go.mod h1:axh6C/jNuSyC0QGtidZJURc9h+h41HNoMySoLVrhVR4=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
|
@ -576,6 +590,8 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||||
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||||
|
|
@ -633,8 +649,9 @@ github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||||
github.com/rs/zerolog v1.18.0 h1:CbAm3kP2Tptby1i9sYy2MGRg0uxIN9cyDb59Ys7W8z8=
|
|
||||||
github.com/rs/zerolog v1.18.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I=
|
github.com/rs/zerolog v1.18.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I=
|
||||||
|
github.com/rs/zerolog v1.18.1-0.20200514152719-663cbb4c8469 h1:DuXsEWHUTO5lsxxzKM4KUKGDIOi7nawNDs6d+AiulEA=
|
||||||
|
github.com/rs/zerolog v1.18.1-0.20200514152719-663cbb4c8469/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
|
|
@ -661,6 +678,7 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
|
@ -917,6 +935,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190415145633-3fd5a3612ccd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190415145633-3fd5a3612ccd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
@ -984,8 +1003,9 @@ golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
|
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ fragment ConfigInterfaceData on ConfigInterfaceResult {
|
||||||
wallPlayback
|
wallPlayback
|
||||||
maximumLoopDuration
|
maximumLoopDuration
|
||||||
noBrowser
|
noBrowser
|
||||||
|
notificationsEnabled
|
||||||
autostartVideo
|
autostartVideo
|
||||||
autostartVideoOnPlaySelected
|
autostartVideoOnPlaySelected
|
||||||
continuePlaylistDefault
|
continuePlaylistDefault
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,8 @@ input ConfigInterfaceInput {
|
||||||
funscriptOffset: Int
|
funscriptOffset: Int
|
||||||
"""True if we should not auto-open a browser window on startup"""
|
"""True if we should not auto-open a browser window on startup"""
|
||||||
noBrowser: Boolean
|
noBrowser: Boolean
|
||||||
|
"""True if we should send notifications to the desktop"""
|
||||||
|
notificationsEnabled: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigDisableDropdownCreate {
|
type ConfigDisableDropdownCreate {
|
||||||
|
|
@ -261,8 +263,10 @@ type ConfigInterfaceResult {
|
||||||
|
|
||||||
"""Maximum duration (in seconds) in which a scene video will loop in the scene player"""
|
"""Maximum duration (in seconds) in which a scene video will loop in the scene player"""
|
||||||
maximumLoopDuration: Int
|
maximumLoopDuration: Int
|
||||||
""""True if we should not auto-open a browser window on startup"""
|
"""True if we should not auto-open a browser window on startup"""
|
||||||
noBrowser: Boolean
|
noBrowser: Boolean
|
||||||
|
"""True if we should send desktop notifications"""
|
||||||
|
notificationsEnabled: Boolean
|
||||||
"""If true, video will autostart on load in the scene player"""
|
"""If true, video will autostart on load in the scene player"""
|
||||||
autostartVideo: Boolean
|
autostartVideo: Boolean
|
||||||
"""If true, video will autostart when loading from play random or play selected"""
|
"""If true, video will autostart when loading from play random or play selected"""
|
||||||
|
|
|
||||||
16
main.go
16
main.go
|
|
@ -3,13 +3,14 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/apenwarr/fixconsole"
|
||||||
"github.com/stashapp/stash/pkg/api"
|
"github.com/stashapp/stash/pkg/api"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
|
||||||
"github.com/stashapp/stash/pkg/manager"
|
"github.com/stashapp/stash/pkg/manager"
|
||||||
|
|
||||||
_ "github.com/golang-migrate/migrate/v4/database/sqlite3"
|
_ "github.com/golang-migrate/migrate/v4/database/sqlite3"
|
||||||
|
|
@ -22,6 +23,14 @@ var uiBox embed.FS
|
||||||
//go:embed ui/login
|
//go:embed ui/login
|
||||||
var loginUIBox embed.FS
|
var loginUIBox embed.FS
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// On Windows, attach to parent shell
|
||||||
|
err := fixconsole.FixConsoleIfNeeded()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("FixConsoleOutput: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
manager.Initialize()
|
manager.Initialize()
|
||||||
api.Start(uiBox, loginUIBox)
|
api.Start(uiBox, loginUIBox)
|
||||||
|
|
@ -30,10 +39,7 @@ func main() {
|
||||||
defer pprof.StopCPUProfile()
|
defer pprof.StopCPUProfile()
|
||||||
blockForever()
|
blockForever()
|
||||||
|
|
||||||
err := manager.GetInstance().Shutdown()
|
manager.GetInstance().Shutdown(0)
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("Error when closing: %s", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func blockForever() {
|
func blockForever() {
|
||||||
|
|
|
||||||
|
|
@ -130,9 +130,4 @@ func securityActivateTripwireAccessedFromInternetWithoutAuth(c *config.Instance,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = manager.GetInstance().Shutdown()
|
|
||||||
if err != nil {
|
|
||||||
logger.Error(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
pkg/api/favicon.go
Normal file
28
pkg/api/favicon.go
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
const faviconDir = "ui/v2.5/build/"
|
||||||
|
|
||||||
|
type FaviconProvider struct {
|
||||||
|
uiBox embed.FS
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *FaviconProvider) GetFavicon() []byte {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
faviconPath := faviconDir + "favicon.ico"
|
||||||
|
ret, _ := p.uiBox.ReadFile(faviconPath)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.GetFaviconPng()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *FaviconProvider) GetFaviconPng() []byte {
|
||||||
|
faviconPath := faviconDir + "favicon.png"
|
||||||
|
ret, _ := p.uiBox.ReadFile(faviconPath)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
@ -294,6 +294,8 @@ func (r *mutationResolver) ConfigureInterface(ctx context.Context, input models.
|
||||||
|
|
||||||
setBool(config.NoBrowser, input.NoBrowser)
|
setBool(config.NoBrowser, input.NoBrowser)
|
||||||
|
|
||||||
|
setBool(config.NotificationsEnabled, input.NotificationsEnabled)
|
||||||
|
|
||||||
if input.WallPlayback != nil {
|
if input.WallPlayback != nil {
|
||||||
c.Set(config.WallPlayback, *input.WallPlayback)
|
c.Set(config.WallPlayback, *input.WallPlayback)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ func makeConfigInterfaceResult() *models.ConfigInterfaceResult {
|
||||||
wallShowTitle := config.GetWallShowTitle()
|
wallShowTitle := config.GetWallShowTitle()
|
||||||
wallPlayback := config.GetWallPlayback()
|
wallPlayback := config.GetWallPlayback()
|
||||||
noBrowser := config.GetNoBrowser()
|
noBrowser := config.GetNoBrowser()
|
||||||
|
notificationsEnabled := config.GetNotificationsEnabled()
|
||||||
maximumLoopDuration := config.GetMaximumLoopDuration()
|
maximumLoopDuration := config.GetMaximumLoopDuration()
|
||||||
autostartVideo := config.GetAutostartVideo()
|
autostartVideo := config.GetAutostartVideo()
|
||||||
autostartVideoOnPlaySelected := config.GetAutostartVideoOnPlaySelected()
|
autostartVideoOnPlaySelected := config.GetAutostartVideoOnPlaySelected()
|
||||||
|
|
@ -133,6 +134,7 @@ func makeConfigInterfaceResult() *models.ConfigInterfaceResult {
|
||||||
WallPlayback: &wallPlayback,
|
WallPlayback: &wallPlayback,
|
||||||
MaximumLoopDuration: &maximumLoopDuration,
|
MaximumLoopDuration: &maximumLoopDuration,
|
||||||
NoBrowser: &noBrowser,
|
NoBrowser: &noBrowser,
|
||||||
|
NotificationsEnabled: ¬ificationsEnabled,
|
||||||
AutostartVideo: &autostartVideo,
|
AutostartVideo: &autostartVideo,
|
||||||
ShowStudioAsText: &showStudioAsText,
|
ShowStudioAsText: &showStudioAsText,
|
||||||
AutostartVideoOnPlaySelected: &autostartVideoOnPlaySelected,
|
AutostartVideoOnPlaySelected: &autostartVideoOnPlaySelected,
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,10 @@ import (
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
"github.com/go-chi/chi/middleware"
|
"github.com/go-chi/chi/middleware"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/pkg/browser"
|
|
||||||
|
"github.com/go-chi/httplog"
|
||||||
"github.com/rs/cors"
|
"github.com/rs/cors"
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/manager"
|
"github.com/stashapp/stash/pkg/manager"
|
||||||
"github.com/stashapp/stash/pkg/manager/config"
|
"github.com/stashapp/stash/pkg/manager/config"
|
||||||
|
|
@ -36,7 +38,6 @@ import (
|
||||||
var version string
|
var version string
|
||||||
var buildstamp string
|
var buildstamp string
|
||||||
var githash string
|
var githash string
|
||||||
var officialBuild string
|
|
||||||
|
|
||||||
func Start(uiBox embed.FS, loginUIBox embed.FS) {
|
func Start(uiBox embed.FS, loginUIBox embed.FS) {
|
||||||
initialiseImages()
|
initialiseImages()
|
||||||
|
|
@ -52,7 +53,10 @@ func Start(uiBox embed.FS, loginUIBox embed.FS) {
|
||||||
|
|
||||||
c := config.GetInstance()
|
c := config.GetInstance()
|
||||||
if c.GetLogAccess() {
|
if c.GetLogAccess() {
|
||||||
r.Use(middleware.Logger)
|
httpLogger := httplog.NewLogger("Stash", httplog.Options{
|
||||||
|
Concise: true,
|
||||||
|
})
|
||||||
|
r.Use(httplog.RequestLogger(httpLogger))
|
||||||
}
|
}
|
||||||
r.Use(SecurityHeadersMiddleware)
|
r.Use(SecurityHeadersMiddleware)
|
||||||
r.Use(middleware.DefaultCompress)
|
r.Use(middleware.DefaultCompress)
|
||||||
|
|
@ -246,25 +250,16 @@ func Start(uiBox embed.FS, loginUIBox embed.FS) {
|
||||||
TLSConfig: tlsConfig,
|
TLSConfig: tlsConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printVersion()
|
||||||
|
go printLatestVersion(context.TODO())
|
||||||
|
logger.Infof("stash is listening on " + address)
|
||||||
|
if tlsConfig != nil {
|
||||||
|
displayAddress = "https://" + displayAddress + "/"
|
||||||
|
} else {
|
||||||
|
displayAddress = "http://" + displayAddress + "/"
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
printVersion()
|
|
||||||
printLatestVersion(context.TODO())
|
|
||||||
logger.Infof("stash is listening on " + address)
|
|
||||||
if tlsConfig != nil {
|
|
||||||
displayAddress = "https://" + displayAddress + "/"
|
|
||||||
} else {
|
|
||||||
displayAddress = "http://" + displayAddress + "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
// This can be done before actually starting the server, as modern browsers will
|
|
||||||
// automatically reload the page if a local port is closed at page load and then opened.
|
|
||||||
if !c.GetNoBrowser() && manager.GetInstance().IsDesktop() {
|
|
||||||
err = browser.OpenURL(displayAddress)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("Could not open browser: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tlsConfig != nil {
|
if tlsConfig != nil {
|
||||||
logger.Infof("stash is running at " + displayAddress)
|
logger.Infof("stash is running at " + displayAddress)
|
||||||
logger.Error(server.ListenAndServeTLS("", ""))
|
logger.Error(server.ListenAndServeTLS("", ""))
|
||||||
|
|
@ -272,12 +267,14 @@ func Start(uiBox embed.FS, loginUIBox embed.FS) {
|
||||||
logger.Infof("stash is running at " + displayAddress)
|
logger.Infof("stash is running at " + displayAddress)
|
||||||
logger.Error(server.ListenAndServe())
|
logger.Error(server.ListenAndServe())
|
||||||
}
|
}
|
||||||
|
manager.GetInstance().Shutdown(0)
|
||||||
}()
|
}()
|
||||||
|
desktop.Start(manager.GetInstance(), &FaviconProvider{uiBox: uiBox})
|
||||||
}
|
}
|
||||||
|
|
||||||
func printVersion() {
|
func printVersion() {
|
||||||
versionString := githash
|
versionString := githash
|
||||||
if IsOfficialBuild() {
|
if config.IsOfficialBuild() {
|
||||||
versionString += " - Official Build"
|
versionString += " - Official Build"
|
||||||
} else {
|
} else {
|
||||||
versionString += " - Unofficial Build"
|
versionString += " - Unofficial Build"
|
||||||
|
|
@ -288,10 +285,6 @@ func printVersion() {
|
||||||
fmt.Printf("stash version: %s - %s\n", versionString, buildstamp)
|
fmt.Printf("stash version: %s - %s\n", versionString, buildstamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsOfficialBuild() bool {
|
|
||||||
return officialBuild == "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetVersion() (string, string, string) {
|
func GetVersion() (string, string, string) {
|
||||||
return version, githash, buildstamp
|
return version, githash, buildstamp
|
||||||
}
|
}
|
||||||
|
|
|
||||||
170
pkg/desktop/desktop.go
Normal file
170
pkg/desktop/desktop.go
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
package desktop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/browser"
|
||||||
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
|
"github.com/stashapp/stash/pkg/manager/config"
|
||||||
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
|
"golang.org/x/term"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ShutdownHandler interface {
|
||||||
|
Shutdown(code int)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FaviconProvider interface {
|
||||||
|
GetFavicon() []byte
|
||||||
|
GetFaviconPng() []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start(shutdownHandler ShutdownHandler, faviconProvider FaviconProvider) {
|
||||||
|
if IsDesktop() {
|
||||||
|
c := config.GetInstance()
|
||||||
|
if !c.GetNoBrowser() {
|
||||||
|
openURLInBrowser("")
|
||||||
|
}
|
||||||
|
writeStashIcon(faviconProvider)
|
||||||
|
startSystray(shutdownHandler, faviconProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// openURLInBrowser opens a browser to the Stash UI. Path can be an empty string for main page.
|
||||||
|
func openURLInBrowser(path string) {
|
||||||
|
// This can be done before actually starting the server, as modern browsers will
|
||||||
|
// automatically reload the page if a local port is closed at page load and then opened.
|
||||||
|
serverAddress := getServerURL(path)
|
||||||
|
|
||||||
|
err := browser.OpenURL(serverAddress)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Could not open browser: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendNotification(title string, text string) {
|
||||||
|
if IsDesktop() {
|
||||||
|
c := config.GetInstance()
|
||||||
|
if c.GetNotificationsEnabled() {
|
||||||
|
sendNotification(title, text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsDesktop() bool {
|
||||||
|
// Check if running under root
|
||||||
|
if os.Getuid() == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Check if stdin is a terminal
|
||||||
|
if term.IsTerminal(int(os.Stdin.Fd())) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if isService() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if IsServerDockerized() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsServerDockerized() bool {
|
||||||
|
return isServerDockerized()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a command to execute in the background, instead of spawning a shell window
|
||||||
|
func HideExecShell(cmd *exec.Cmd) {
|
||||||
|
hideExecShell(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeStashIcon writes the current stash logo to config/icon.png
|
||||||
|
func writeStashIcon(faviconProvider FaviconProvider) {
|
||||||
|
c := config.GetInstance()
|
||||||
|
if !c.IsNewSystem() {
|
||||||
|
iconPath := path.Join(c.GetConfigPath(), "icon.png")
|
||||||
|
err := ioutil.WriteFile(iconPath, faviconProvider.GetFaviconPng(), 0644)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Couldn't write icon file: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAllowedAutoUpdate tries to determine if the stash binary was installed from a
|
||||||
|
// package manager or if touching the executable is otherwise a bad idea
|
||||||
|
func IsAllowedAutoUpdate() bool {
|
||||||
|
|
||||||
|
// Only try to update if downloaded from official sources
|
||||||
|
if !config.IsOfficialBuild() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid updating if installed from package manager
|
||||||
|
if runtime.GOOS == "linux" {
|
||||||
|
executablePath, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Cannot get executable path: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
executablePath, err = filepath.EvalSymlinks(executablePath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Cannot get executable path: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if utils.IsPathInDir("/usr", executablePath) || utils.IsPathInDir("/opt", executablePath) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if isServerDockerized() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIconPath() string {
|
||||||
|
return path.Join(config.GetInstance().GetConfigPath(), "icon.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
func RevealInFileManager(path string) {
|
||||||
|
exists, err := utils.FileExists(path)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Error checking file: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if exists && IsDesktop() {
|
||||||
|
revealInFileManager(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getServerURL(path string) string {
|
||||||
|
c := config.GetInstance()
|
||||||
|
serverAddress := c.GetHost()
|
||||||
|
if serverAddress == "0.0.0.0" {
|
||||||
|
serverAddress = "localhost"
|
||||||
|
}
|
||||||
|
serverAddress = serverAddress + ":" + strconv.Itoa(c.GetPort())
|
||||||
|
|
||||||
|
proto := ""
|
||||||
|
if c.HasTLSConfig() {
|
||||||
|
proto = "https://"
|
||||||
|
} else {
|
||||||
|
proto = "http://"
|
||||||
|
}
|
||||||
|
serverAddress = proto + serverAddress + "/"
|
||||||
|
|
||||||
|
if path != "" {
|
||||||
|
serverAddress += strings.TrimPrefix(path, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
return serverAddress
|
||||||
|
}
|
||||||
40
pkg/desktop/desktop_platform_darwin.go
Normal file
40
pkg/desktop/desktop_platform_darwin.go
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
//go:build darwin
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package desktop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/kermieisinthehouse/gosx-notifier"
|
||||||
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isService() bool {
|
||||||
|
// MacOS /does/ support services, using launchd, but there is no straightforward way to check if it was used.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isServerDockerized() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func hideExecShell(cmd *exec.Cmd) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendNotification(notificationTitle string, notificationText string) {
|
||||||
|
notification := gosxnotifier.NewNotification(notificationText)
|
||||||
|
notification.Title = notificationTitle
|
||||||
|
notification.AppIcon = getIconPath()
|
||||||
|
notification.Link = getServerURL("")
|
||||||
|
err := notification.Push()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Could not send MacOS notification: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func revealInFileManager(path string) {
|
||||||
|
exec.Command(`open`, `-R`, path)
|
||||||
|
}
|
||||||
43
pkg/desktop/desktop_platform_linux.go
Normal file
43
pkg/desktop/desktop_platform_linux.go
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package desktop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// isService checks if started by init, e.g. stash is a *nix systemd service
|
||||||
|
func isService() bool {
|
||||||
|
return os.Getppid() == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func isServerDockerized() bool {
|
||||||
|
_, dockerEnvErr := os.Stat("/.dockerenv")
|
||||||
|
cgroups, _ := ioutil.ReadFile("/proc/self/cgroup")
|
||||||
|
if !os.IsNotExist(dockerEnvErr) || strings.Contains(string(cgroups), "docker") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func hideExecShell(cmd *exec.Cmd) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendNotification(notificationTitle string, notificationText string) {
|
||||||
|
err := exec.Command("notify-send", "-i", getIconPath(), notificationTitle, notificationText, "-a", "Stash").Run()
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Error sending notification on Linux: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func revealInFileManager(path string) {
|
||||||
|
|
||||||
|
}
|
||||||
56
pkg/desktop/desktop_platform_windows.go
Normal file
56
pkg/desktop/desktop_platform_windows.go
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package desktop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
|
||||||
|
"github.com/go-toast/toast"
|
||||||
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
|
"golang.org/x/sys/windows/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isService() bool {
|
||||||
|
result, err := svc.IsWindowsService()
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Encountered error checking if running as Windows service: %s", err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func isServerDockerized() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// On Windows, calling exec.Cmd.Start() will create a cmd window, even if we live in the taskbar.
|
||||||
|
// We don't want every ffmpeg / plugin to pop up a window.
|
||||||
|
func hideExecShell(cmd *exec.Cmd) {
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: windows.DETACHED_PROCESS}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendNotification(notificationTitle string, notificationText string) {
|
||||||
|
notification := toast.Notification{
|
||||||
|
AppID: "Stash",
|
||||||
|
Title: notificationTitle,
|
||||||
|
Message: notificationText,
|
||||||
|
Icon: getIconPath(),
|
||||||
|
Actions: []toast.Action{{
|
||||||
|
Type: "protocol",
|
||||||
|
Label: "Open Stash",
|
||||||
|
Arguments: getServerURL(""),
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
err := notification.Push()
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Error creating Windows notification: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func revealInFileManager(path string) {
|
||||||
|
exec.Command(`explorer`, `\select`, path)
|
||||||
|
}
|
||||||
BIN
pkg/desktop/icon_windows.syso
Normal file
BIN
pkg/desktop/icon_windows.syso
Normal file
Binary file not shown.
10
pkg/desktop/systray_linux.go
Normal file
10
pkg/desktop/systray_linux.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package desktop
|
||||||
|
|
||||||
|
func startSystray(shutdownHandler ShutdownHandler, favicon FaviconProvider) {
|
||||||
|
// The systray is not available on linux because the required libraries (libappindicator3 and gtk+3.0)
|
||||||
|
// are not able to be statically compiled. Technically, the systray works perfectly fine when dynamically
|
||||||
|
// linked, but we cannot distribute it for compatibility reasons.
|
||||||
|
}
|
||||||
94
pkg/desktop/systray_nonlinux.go
Normal file
94
pkg/desktop/systray_nonlinux.go
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
//go:build windows || darwin || !linux
|
||||||
|
// +build windows darwin !linux
|
||||||
|
|
||||||
|
package desktop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/kermieisinthehouse/systray"
|
||||||
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
|
"github.com/stashapp/stash/pkg/manager/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MUST be run on the main goroutine or will have no effect on macOS
|
||||||
|
func startSystray(shutdownHandler ShutdownHandler, faviconProvider FaviconProvider) {
|
||||||
|
|
||||||
|
// Shows a small notification to inform that Stash will no longer show a terminal window,
|
||||||
|
// and instead will be available in the tray. Will only show the first time a pre-desktop integration
|
||||||
|
// system is started from a non-terminal method, e.g. double-clicking an icon.
|
||||||
|
c := config.GetInstance()
|
||||||
|
if c.GetShowOneTimeMovedNotification() {
|
||||||
|
SendNotification("Stash has moved!", "Stash now runs in your tray, instead of a terminal window.")
|
||||||
|
c.Set(config.ShowOneTimeMovedNotification, false)
|
||||||
|
if err := c.Write(); err != nil {
|
||||||
|
logger.Errorf("Error while writing configuration file: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for changes to rerender systray
|
||||||
|
// TODO: This is disabled for now. The systray package does not clean up all of its resources when Quit() is called.
|
||||||
|
// TODO: This results in this only working once, or changes being ignored. Our fork of systray fixes a crash(!) on macOS here.
|
||||||
|
// go func() {
|
||||||
|
// for {
|
||||||
|
// <-config.GetInstance().GetConfigUpdatesChannel()
|
||||||
|
// systray.Quit()
|
||||||
|
// }
|
||||||
|
// }()
|
||||||
|
|
||||||
|
for {
|
||||||
|
systray.Run(func() {
|
||||||
|
systrayInitialize(shutdownHandler, faviconProvider)
|
||||||
|
}, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func systrayInitialize(shutdownHandler ShutdownHandler, faviconProvider FaviconProvider) {
|
||||||
|
favicon := faviconProvider.GetFavicon()
|
||||||
|
systray.SetTemplateIcon(favicon, favicon)
|
||||||
|
systray.SetTooltip("🟢 Stash is Running.")
|
||||||
|
|
||||||
|
openStashButton := systray.AddMenuItem("Open Stash", "Open a browser window to Stash")
|
||||||
|
var menuItems []string
|
||||||
|
systray.AddSeparator()
|
||||||
|
c := config.GetInstance()
|
||||||
|
if !c.IsNewSystem() {
|
||||||
|
menuItems = c.GetMenuItems()
|
||||||
|
for _, item := range menuItems {
|
||||||
|
titleCaseItem := strings.Title(strings.ToLower(item))
|
||||||
|
curr := systray.AddMenuItem(titleCaseItem, "Open to "+titleCaseItem)
|
||||||
|
go func(item string) {
|
||||||
|
for {
|
||||||
|
<-curr.ClickedCh
|
||||||
|
if item == "markers" {
|
||||||
|
item = "scenes/markers"
|
||||||
|
}
|
||||||
|
if c.GetNoBrowser() {
|
||||||
|
openURLInBrowser(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(item)
|
||||||
|
}
|
||||||
|
systray.AddSeparator()
|
||||||
|
// TODO - Some ideas for future expansions
|
||||||
|
// systray.AddMenuItem("Start a Scan", "Scan all libraries with default settings")
|
||||||
|
// systray.AddMenuItem("Start Auto Tagging", "Auto Tag all libraries")
|
||||||
|
// systray.AddMenuItem("Check for updates", "Check for a new Stash release")
|
||||||
|
// systray.AddSeparator()
|
||||||
|
}
|
||||||
|
|
||||||
|
quitStashButton := systray.AddMenuItem("Quit Stash Server", "Quits the Stash server")
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-openStashButton.ClickedCh:
|
||||||
|
if !c.GetNoBrowser() {
|
||||||
|
openURLInBrowser("")
|
||||||
|
}
|
||||||
|
case <-quitStashButton.ClickedCh:
|
||||||
|
shutdownHandler.Shutdown(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
@ -202,7 +203,9 @@ func pathBinaryHasCorrectFlags() bool {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
bytes, _ := exec.Command(ffmpegPath).CombinedOutput()
|
cmd := exec.Command(ffmpegPath)
|
||||||
|
desktop.HideExecShell(cmd)
|
||||||
|
bytes, _ := cmd.CombinedOutput()
|
||||||
output := string(bytes)
|
output := string(bytes)
|
||||||
hasOpus := strings.Contains(output, "--enable-libopus")
|
hasOpus := strings.Contains(output, "--enable-libopus")
|
||||||
hasVpx := strings.Contains(output, "--enable-libvpx")
|
hasVpx := strings.Contains(output, "--enable-libvpx")
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -90,6 +91,7 @@ func (e *Encoder) runTranscode(probeResult VideoFile, args []string) (string, er
|
||||||
logger.Error("FFMPEG stdout not available: " + err.Error())
|
logger.Error("FFMPEG stdout not available: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
desktop.HideExecShell(cmd)
|
||||||
if err = cmd.Start(); err != nil {
|
if err = cmd.Start(); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -141,6 +143,7 @@ func (e *Encoder) run(sourcePath string, args []string, stdin io.Reader) (string
|
||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
cmd.Stdin = stdin
|
cmd.Stdin = stdin
|
||||||
|
|
||||||
|
desktop.HideExecShell(cmd)
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -229,7 +230,9 @@ type FFProbe string
|
||||||
// Execute exec command and bind result to struct.
|
// Execute exec command and bind result to struct.
|
||||||
func (f *FFProbe) NewVideoFile(videoPath string, stripExt bool) (*VideoFile, error) {
|
func (f *FFProbe) NewVideoFile(videoPath string, stripExt bool) (*VideoFile, error) {
|
||||||
args := []string{"-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", "-show_error", videoPath}
|
args := []string{"-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", "-show_error", videoPath}
|
||||||
out, err := exec.Command(string(*f), args...).Output()
|
cmd := exec.Command(string(*f), args...)
|
||||||
|
desktop.HideExecShell(cmd)
|
||||||
|
out, err := cmd.Output()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("FFProbe encountered an error with <%s>.\nError JSON:\n%s\nError: %s", videoPath, string(out), err.Error())
|
return nil, fmt.Errorf("FFProbe encountered an error with <%s>.\nError JSON:\n%s\nError: %s", videoPath, string(out), err.Error())
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
@ -220,6 +221,7 @@ func (e *Encoder) stream(probeResult VideoFile, options TranscodeStreamOptions)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
desktop.HideExecShell(cmd)
|
||||||
if err = cmd.Start(); err != nil {
|
if err = cmd.Start(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -32,6 +33,7 @@ func (e *vipsEncoder) run(args []string, stdin *bytes.Buffer) (string, error) {
|
||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
cmd.Stdin = stdin
|
cmd.Stdin = stdin
|
||||||
|
|
||||||
|
desktop.HideExecShell(cmd)
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,13 @@ package job
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -204,9 +208,14 @@ func (m *Manager) onJobFinish(job *Job) {
|
||||||
} else {
|
} else {
|
||||||
job.Status = StatusFinished
|
job.Status = StatusFinished
|
||||||
}
|
}
|
||||||
|
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
job.EndTime = &t
|
job.EndTime = &t
|
||||||
|
cleanDesc := strings.TrimRight(job.Description, ".")
|
||||||
|
timeElapsed := job.EndTime.Sub(*job.StartTime)
|
||||||
|
hours := fmt.Sprintf("%+02s", strconv.FormatFloat(timeElapsed.Hours(), 'f', 0, 64))
|
||||||
|
minutes := fmt.Sprintf("%+02s", strconv.FormatFloat(timeElapsed.Minutes(), 'f', 0, 64))
|
||||||
|
seconds := fmt.Sprintf("%+02s", strconv.FormatFloat(timeElapsed.Seconds(), 'f', 0, 64))
|
||||||
|
desktop.SendNotification("Task Finished", "Task \""+cleanDesc+"\" is finished in "+hours+":"+minutes+":"+seconds+".")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) removeJob(job *Job) {
|
func (m *Manager) removeJob(job *Job) {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ func Init(logFile string, logOut bool, logLevel string) {
|
||||||
customFormatter.TimestampFormat = "2006-01-02 15:04:05"
|
customFormatter.TimestampFormat = "2006-01-02 15:04:05"
|
||||||
customFormatter.ForceColors = true
|
customFormatter.ForceColors = true
|
||||||
customFormatter.FullTimestamp = true
|
customFormatter.FullTimestamp = true
|
||||||
|
logger.SetOutput(os.Stderr)
|
||||||
logger.SetFormatter(customFormatter)
|
logger.SetFormatter(customFormatter)
|
||||||
|
|
||||||
// #1837 - trigger the console to use color-mode since it won't be
|
// #1837 - trigger the console to use color-mode since it won't be
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ import (
|
||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var officialBuild string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Stash = "stash"
|
Stash = "stash"
|
||||||
Cache = "cache"
|
Cache = "cache"
|
||||||
|
|
@ -178,8 +180,12 @@ const (
|
||||||
deleteGeneratedDefaultDefault = true
|
deleteGeneratedDefaultDefault = true
|
||||||
|
|
||||||
// Desktop Integration Options
|
// Desktop Integration Options
|
||||||
NoBrowser = "noBrowser"
|
NoBrowser = "noBrowser"
|
||||||
NoBrowserDefault = false
|
NoBrowserDefault = false
|
||||||
|
NotificationsEnabled = "notifications_enabled"
|
||||||
|
NotificationsEnabledDefault = true
|
||||||
|
ShowOneTimeMovedNotification = "show_one_time_moved_notification"
|
||||||
|
ShowOneTimeMovedNotificationDefault = false
|
||||||
|
|
||||||
// File upload options
|
// File upload options
|
||||||
MaxUploadSize = "max_upload_size"
|
MaxUploadSize = "max_upload_size"
|
||||||
|
|
@ -211,6 +217,10 @@ func (s *StashBoxError) Error() string {
|
||||||
return "Stash-box: " + s.msg
|
return "Stash-box: " + s.msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsOfficialBuild() bool {
|
||||||
|
return officialBuild == "true"
|
||||||
|
}
|
||||||
|
|
||||||
type Instance struct {
|
type Instance struct {
|
||||||
// main instance - backed by config file
|
// main instance - backed by config file
|
||||||
main *viper.Viper
|
main *viper.Viper
|
||||||
|
|
@ -221,8 +231,9 @@ type Instance struct {
|
||||||
|
|
||||||
cpuProfilePath string
|
cpuProfilePath string
|
||||||
isNewSystem bool
|
isNewSystem bool
|
||||||
certFile string
|
// configUpdates chan int
|
||||||
keyFile string
|
certFile string
|
||||||
|
keyFile string
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
// deadlock.RWMutex // for deadlock testing/issues
|
// deadlock.RWMutex // for deadlock testing/issues
|
||||||
}
|
}
|
||||||
|
|
@ -270,7 +281,25 @@ func (i *Instance) GetNoBrowser() bool {
|
||||||
return i.getBool(NoBrowser)
|
return i.getBool(NoBrowser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Instance) GetNotificationsEnabled() bool {
|
||||||
|
return i.getBool(NotificationsEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (i *Instance) GetConfigUpdatesChannel() chan int {
|
||||||
|
// return i.configUpdates
|
||||||
|
// }
|
||||||
|
|
||||||
|
// GetShowOneTimeMovedNotification shows whether a small notification to inform the user that Stash
|
||||||
|
// will no longer show a terminal window, and instead will be available in the tray, should be shown.
|
||||||
|
// It is true when an existing system is started after upgrading, and set to false forever after it is shown.
|
||||||
|
func (i *Instance) GetShowOneTimeMovedNotification() bool {
|
||||||
|
return i.getBool(ShowOneTimeMovedNotification)
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Instance) Set(key string, value interface{}) {
|
func (i *Instance) Set(key string, value interface{}) {
|
||||||
|
// if key == MenuItems {
|
||||||
|
// i.configUpdates <- 0
|
||||||
|
// }
|
||||||
i.Lock()
|
i.Lock()
|
||||||
defer i.Unlock()
|
defer i.Unlock()
|
||||||
i.main.Set(key, value)
|
i.main.Set(key, value)
|
||||||
|
|
@ -1184,6 +1213,8 @@ func (i *Instance) setDefaultValues(write bool) error {
|
||||||
i.main.SetDefault(Generated, i.main.GetString(Metadata))
|
i.main.SetDefault(Generated, i.main.GetString(Metadata))
|
||||||
|
|
||||||
i.main.SetDefault(NoBrowser, NoBrowserDefault)
|
i.main.SetDefault(NoBrowser, NoBrowserDefault)
|
||||||
|
i.main.SetDefault(NotificationsEnabled, NotificationsEnabledDefault)
|
||||||
|
i.main.SetDefault(ShowOneTimeMovedNotification, ShowOneTimeMovedNotificationDefault)
|
||||||
|
|
||||||
// Set default scrapers and plugins paths
|
// Set default scrapers and plugins paths
|
||||||
i.main.SetDefault(ScrapersPath, defaultScrapersPath)
|
i.main.SetDefault(ScrapersPath, defaultScrapersPath)
|
||||||
|
|
@ -1210,6 +1241,12 @@ func (i *Instance) setExistingSystemDefaults() error {
|
||||||
i.main.Set(NoBrowser, true)
|
i.main.Set(NoBrowser, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Existing systems as of the introduction of the taskbar should inform users.
|
||||||
|
if !i.main.InConfig(ShowOneTimeMovedNotification) {
|
||||||
|
configDirtied = true
|
||||||
|
i.main.Set(ShowOneTimeMovedNotification, true)
|
||||||
|
}
|
||||||
|
|
||||||
if configDirtied {
|
if configDirtied {
|
||||||
return i.main.WriteConfig()
|
return i.main.WriteConfig()
|
||||||
}
|
}
|
||||||
|
|
@ -1247,4 +1284,5 @@ func (i *Instance) setInitialConfig(write bool) error {
|
||||||
|
|
||||||
func (i *Instance) FinalizeSetup() {
|
func (i *Instance) FinalizeSetup() {
|
||||||
i.isNewSystem = false
|
i.isNewSystem = false
|
||||||
|
// i.configUpdates <- 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ func Initialize() (*Instance, error) {
|
||||||
_ = GetInstance()
|
_ = GetInstance()
|
||||||
instance.overrides = overrides
|
instance.overrides = overrides
|
||||||
instance.cpuProfilePath = flags.cpuProfilePath
|
instance.cpuProfilePath = flags.cpuProfilePath
|
||||||
|
// instance.configUpdates = make(chan int)
|
||||||
|
|
||||||
if err = initConfig(instance, flags); err != nil {
|
if err = initConfig(instance, flags); err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/ffmpeg"
|
"github.com/stashapp/stash/pkg/ffmpeg"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
|
|
@ -72,6 +73,7 @@ func (g *GeneratorInfo) calculateFrameRate(videoStream *ffmpeg.FFProbeStream) er
|
||||||
}
|
}
|
||||||
|
|
||||||
command := exec.Command(string(instance.FFMPEG), args...)
|
command := exec.Command(string(instance.FFMPEG), args...)
|
||||||
|
desktop.HideExecShell(command)
|
||||||
var stdErrBuffer bytes.Buffer
|
var stdErrBuffer bytes.Buffer
|
||||||
command.Stderr = &stdErrBuffer // Frames go to stderr rather than stdout
|
command.Stderr = &stdErrBuffer // Frames go to stderr rather than stdout
|
||||||
if err := command.Run(); err == nil {
|
if err := command.Run(); err == nil {
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,9 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -407,34 +404,6 @@ func (s *singleton) Migrate(ctx context.Context, input models.MigrateInput) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *singleton) IsDesktop() bool {
|
|
||||||
// check if running under root
|
|
||||||
if os.Getuid() == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// check if started by init, e.g. stash is a *nix systemd service / MacOS launchd service
|
|
||||||
if os.Getppid() == 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if IsServerDockerized() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsServerDockerized() bool {
|
|
||||||
if runtime.GOOS == "linux" {
|
|
||||||
_, dockerEnvErr := os.Stat("/.dockerenv")
|
|
||||||
cgroups, _ := ioutil.ReadFile("/proc/self/cgroup")
|
|
||||||
if os.IsExist(dockerEnvErr) || strings.Contains(string(cgroups), "docker") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *singleton) GetSystemStatus() *models.SystemStatus {
|
func (s *singleton) GetSystemStatus() *models.SystemStatus {
|
||||||
status := models.SystemStatusEnumOk
|
status := models.SystemStatusEnumOk
|
||||||
dbSchema := int(database.Version())
|
dbSchema := int(database.Version())
|
||||||
|
|
@ -458,8 +427,15 @@ func (s *singleton) GetSystemStatus() *models.SystemStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown gracefully stops the manager
|
// Shutdown gracefully stops the manager
|
||||||
func (s *singleton) Shutdown() error {
|
func (s *singleton) Shutdown(code int) {
|
||||||
// TODO: Each part of the manager needs to gracefully stop at some point
|
// TODO: Each part of the manager needs to gracefully stop at some point
|
||||||
// for now, we just close the database.
|
// for now, we just close the database.
|
||||||
return database.Close()
|
err := database.Close()
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Error closing database: %s", err)
|
||||||
|
if code == 0 {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/plugin/common"
|
"github.com/stashapp/stash/pkg/plugin/common"
|
||||||
)
|
)
|
||||||
|
|
@ -87,6 +88,7 @@ func (t *rawPluginTask) Start() error {
|
||||||
|
|
||||||
t.waitGroup.Add(1)
|
t.waitGroup.Add(1)
|
||||||
t.done = make(chan bool, 1)
|
t.done = make(chan bool, 1)
|
||||||
|
desktop.HideExecShell(cmd)
|
||||||
if err = cmd.Start(); err != nil {
|
if err = cmd.Start(); err != nil {
|
||||||
return fmt.Errorf("error running plugin: %v", err)
|
return fmt.Errorf("error running plugin: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/desktop"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
@ -66,6 +67,7 @@ func (s *scriptScraper) runScraperScript(inString string, out interface{}) error
|
||||||
logger.Error("Scraper stdout not available: " + err.Error())
|
logger.Error("Scraper stdout not available: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
desktop.HideExecShell(cmd)
|
||||||
if err = cmd.Start(); err != nil {
|
if err = cmd.Start(); err != nil {
|
||||||
logger.Error("Error running scraper script: " + err.Error())
|
logger.Error("Error running scraper script: " + err.Error())
|
||||||
return errors.New("error running scraper script")
|
return errors.New("error running scraper script")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# "stashapp/compiler:develop" "stashapp/compiler:4"
|
COMPILER_CONTAINER="stashapp/compiler:6"
|
||||||
COMPILER_CONTAINER="stashapp/compiler:5"
|
|
||||||
|
|
||||||
BUILD_DATE=`go run -mod=vendor scripts/getDate.go`
|
BUILD_DATE=`go run -mod=vendor scripts/getDate.go`
|
||||||
GITHASH=`git rev-parse --short HEAD`
|
GITHASH=`git rev-parse --short HEAD`
|
||||||
|
|
@ -10,8 +9,8 @@ STASH_VERSION=`git describe --tags --exclude latest_develop`
|
||||||
SETENV="BUILD_DATE=\"$BUILD_DATE\" GITHASH=$GITHASH STASH_VERSION=\"$STASH_VERSION\""
|
SETENV="BUILD_DATE=\"$BUILD_DATE\" GITHASH=$GITHASH STASH_VERSION=\"$STASH_VERSION\""
|
||||||
SETUP="export CGO_ENABLED=1;"
|
SETUP="export CGO_ENABLED=1;"
|
||||||
WINDOWS="echo '=== Building Windows binary ==='; $SETENV make cross-compile-windows;"
|
WINDOWS="echo '=== Building Windows binary ==='; $SETENV make cross-compile-windows;"
|
||||||
DARWIN="echo '=== Building OSX binary ==='; $SETENV make cross-compile-osx-intel;"
|
DARWIN="echo '=== Building OSX binary ==='; $SETENV make cross-compile-macos-intel;"
|
||||||
DARWIN_ARM64="echo '=== Building OSX (arm64) binary ==='; $SETENV make cross-compile-osx-applesilicon;"
|
DARWIN_ARM64="echo '=== Building OSX (arm64) binary ==='; $SETENV make cross-compile-macos-applesilicon;"
|
||||||
LINUX_AMD64="echo '=== Building Linux (amd64) binary ==='; $SETENV make cross-compile-linux;"
|
LINUX_AMD64="echo '=== Building Linux (amd64) binary ==='; $SETENV make cross-compile-linux;"
|
||||||
LINUX_ARM64v8="echo '=== Building Linux (armv8/arm64) binary ==='; $SETENV make cross-compile-linux-arm64v8;"
|
LINUX_ARM64v8="echo '=== Building Linux (armv8/arm64) binary ==='; $SETENV make cross-compile-linux-arm64v8;"
|
||||||
LINUX_ARM32v7="echo '=== Building Linux (armv7/armhf) binary ==='; $SETENV make cross-compile-linux-arm32v7;"
|
LINUX_ARM32v7="echo '=== Building Linux (armv7/armhf) binary ==='; $SETENV make cross-compile-linux-arm32v7;"
|
||||||
|
|
|
||||||
50
scripts/generate_icons.sh
Executable file
50
scripts/generate_icons.sh
Executable file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Update the Stash icon throughout the project from a master stash-logo.png
|
||||||
|
|
||||||
|
# Imagemagick, and go packages icns and rsrc are required.
|
||||||
|
# Copy a high-resolution stash-logo.png to this stash/scripts folder
|
||||||
|
# and run this script from said folder, commit the result.
|
||||||
|
|
||||||
|
if [ ! -f "stash-logo.png" ]; then
|
||||||
|
echo "stash-logo.png not found."
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$GOPATH" ]; then
|
||||||
|
echo "GOPATH environment variable not set"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e "$GOPATH/bin/rsrc" ]; then
|
||||||
|
echo "Missing Dependency:"
|
||||||
|
echo "Please run the following /outside/ of the stash folder:"
|
||||||
|
echo "go install github.com/akavel/rsrc@latest"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e "$GOPATH/bin/icnsify" ]; then
|
||||||
|
echo "Missing Dependency:"
|
||||||
|
echo "Please run the following /outside/ of the stash folder:"
|
||||||
|
echo "go install github.com/jackmordaunt/icns/v2/cmd/icnsify@latest"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Favicon, used for web favicon, windows systray icon, windows executable icon
|
||||||
|
convert stash-logo.png -define icon:auto-resize=256,64,48,32,16 favicon.ico
|
||||||
|
cp favicon.ico ../ui/v2.5/public/
|
||||||
|
|
||||||
|
# Build .syso for Windows icon, consumed by linker while building stash-win.exe
|
||||||
|
"$GOPATH"/bin/rsrc -ico favicon.ico -o icon_windows.syso
|
||||||
|
mv icon_windows.syso ../pkg/desktop/
|
||||||
|
|
||||||
|
# *nixes systray icon
|
||||||
|
convert stash-logo.png -resize x256 favicon.png
|
||||||
|
cp favicon.png ../ui/v2.5/public/
|
||||||
|
|
||||||
|
# MacOS, used for bundle icon
|
||||||
|
# https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html
|
||||||
|
"$GOPATH"/bin/icnsify -i stash-logo.png -o icon.icns
|
||||||
|
mv icon.icns macos-bundle/Contents/Resources/icon.icns
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
rm favicon.png favicon.ico
|
||||||
18
scripts/macos-bundle/Contents/Info.plist
Normal file
18
scripts/macos-bundle/Contents/Info.plist
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>stash</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>icon.icns</string>
|
||||||
|
<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>icon.icns</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.stashapp.stash</string>
|
||||||
|
<key>NSHighResolutionCapable</key>
|
||||||
|
<string>True</string>
|
||||||
|
<key>LSUIElement</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
BIN
scripts/macos-bundle/Contents/Resources/icon.icns
Normal file
BIN
scripts/macos-bundle/Contents/Resources/icon.icns
Normal file
Binary file not shown.
BIN
scripts/stash-logo.png
Normal file
BIN
scripts/stash-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 41 KiB |
BIN
ui/v2.5/public/favicon.png
Normal file
BIN
ui/v2.5/public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
|
|
@ -8,7 +8,8 @@
|
||||||
"type": "image/x-icon"
|
"type": "image/x-icon"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_url": ".",
|
"start_url": "/",
|
||||||
|
"scope": ".",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"theme_color": "#000000",
|
"theme_color": "#000000",
|
||||||
"background_color": "#ffffff"
|
"background_color": "#ffffff"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
### ✨ New Features
|
### ✨ New Features
|
||||||
|
* Open stash in system tray on Windows/MacOS when not running via terminal. ([#2073](https://github.com/stashapp/stash/pull/2073))
|
||||||
|
* Optionally send desktop notifications when a task completes. ([#2073](https://github.com/stashapp/stash/pull/2073))
|
||||||
* Added button to image card to view image in Lightbox. ([#2275](https://github.com/stashapp/stash/pull/2275))
|
* Added button to image card to view image in Lightbox. ([#2275](https://github.com/stashapp/stash/pull/2275))
|
||||||
* Added support for submitting performer/scene drafts to stash-box. ([#2234](https://github.com/stashapp/stash/pull/2234))
|
* Added support for submitting performer/scene drafts to stash-box. ([#2234](https://github.com/stashapp/stash/pull/2234))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,13 @@ export const SettingsInterfacePanel: React.FC = () => {
|
||||||
checked={iface.noBrowser ?? undefined}
|
checked={iface.noBrowser ?? undefined}
|
||||||
onChange={(v) => saveInterface({ noBrowser: v })}
|
onChange={(v) => saveInterface({ noBrowser: v })}
|
||||||
/>
|
/>
|
||||||
|
<BooleanSetting
|
||||||
|
id="notifications-enabled"
|
||||||
|
headingID="config.ui.desktop_integration.notifications_enabled"
|
||||||
|
subHeadingID="config.ui.desktop_integration.send_desktop_notifications_for_events"
|
||||||
|
checked={iface.notificationsEnabled ?? undefined}
|
||||||
|
onChange={(v) => saveInterface({ notificationsEnabled: v })}
|
||||||
|
/>
|
||||||
</SettingSection>
|
</SettingSection>
|
||||||
|
|
||||||
<SettingSection headingID="config.ui.scene_wall.heading">
|
<SettingSection headingID="config.ui.scene_wall.heading">
|
||||||
|
|
|
||||||
|
|
@ -414,7 +414,9 @@
|
||||||
"desktop_integration": {
|
"desktop_integration": {
|
||||||
"desktop_integration": "Desktop Integration",
|
"desktop_integration": "Desktop Integration",
|
||||||
"skip_opening_browser": "Skip Opening Browser",
|
"skip_opening_browser": "Skip Opening Browser",
|
||||||
"skip_opening_browser_on_startup": "Skip auto-opening browser during startup"
|
"skip_opening_browser_on_startup": "Skip auto-opening browser during startup",
|
||||||
|
"notifications_enabled": "Enable Notifications",
|
||||||
|
"send_desktop_notifications_for_events": "Send desktop notifications for events"
|
||||||
},
|
},
|
||||||
"editing": {
|
"editing": {
|
||||||
"disable_dropdown_create": {
|
"disable_dropdown_create": {
|
||||||
|
|
|
||||||
1
vendor/github.com/apenwarr/fixconsole/.gitignore
generated
vendored
Normal file
1
vendor/github.com/apenwarr/fixconsole/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
*~
|
||||||
202
vendor/github.com/apenwarr/fixconsole/LICENSE
generated
vendored
Normal file
202
vendor/github.com/apenwarr/fixconsole/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor 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, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
14
vendor/github.com/apenwarr/fixconsole/fixconsole_default.go
generated
vendored
Normal file
14
vendor/github.com/apenwarr/fixconsole/fixconsole_default.go
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package fixconsole
|
||||||
|
|
||||||
|
// On non-windows platforms, we don't need to do anything. The console
|
||||||
|
// starts off attached already, if it exists.
|
||||||
|
|
||||||
|
func AttachConsole() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FixConsoleIfNeeded() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
132
vendor/github.com/apenwarr/fixconsole/fixconsole_windows.go
generated
vendored
Normal file
132
vendor/github.com/apenwarr/fixconsole/fixconsole_windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
package fixconsole
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/apenwarr/w32"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AttachConsole() error {
|
||||||
|
const ATTACH_PARENT_PROCESS = ^uintptr(0)
|
||||||
|
proc := syscall.MustLoadDLL("kernel32.dll").MustFindProc("AttachConsole")
|
||||||
|
r1, _, err := proc.Call(ATTACH_PARENT_PROCESS)
|
||||||
|
if r1 == 0 {
|
||||||
|
errno, ok := err.(syscall.Errno)
|
||||||
|
if ok && errno == w32.ERROR_INVALID_HANDLE {
|
||||||
|
// console handle doesn't exist; not a real
|
||||||
|
// error, but the console handle will be
|
||||||
|
// invalid.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldStdin, oldStdout, oldStderr *os.File
|
||||||
|
|
||||||
|
// Windows console output is a mess.
|
||||||
|
//
|
||||||
|
// If you compile as "-H windows", then if you launch your program without
|
||||||
|
// a console, Windows forcibly creates one to use as your stdin/stdout, which
|
||||||
|
// is silly for a GUI app, so we can't do that.
|
||||||
|
//
|
||||||
|
// If you compile as "-H windowsgui", then it doesn't create a console for
|
||||||
|
// your app... but also doesn't provide a working stdin/stdout/stderr even if
|
||||||
|
// you *did* launch from the console. However, you can use AttachConsole()
|
||||||
|
// to get a handle to your parent process's console, if any, and then
|
||||||
|
// os.NewFile() to turn that handle into a fd usable as stdout/stderr.
|
||||||
|
//
|
||||||
|
// However, then you have the problem that if you redirect stdout or stderr
|
||||||
|
// from the shell, you end up ignoring the redirection by forcing it to the
|
||||||
|
// console.
|
||||||
|
//
|
||||||
|
// To fix *that*, we have to detect whether there was a pre-existing stdout
|
||||||
|
// or not. We can check GetStdHandle(), which returns 0 for "should be
|
||||||
|
// console" and nonzero for "already pointing at a file."
|
||||||
|
//
|
||||||
|
// Be careful though! As soon as you run AttachConsole(), it resets *all*
|
||||||
|
// the GetStdHandle() handles to point them at the console instead, thus
|
||||||
|
// throwing away the original file redirects. So we have to GetStdHandle()
|
||||||
|
// *before* AttachConsole().
|
||||||
|
//
|
||||||
|
// For some reason, powershell redirections provide a valid file handle, but
|
||||||
|
// writing to that handle doesn't write to the file. I haven't found a way
|
||||||
|
// to work around that. (Windows 10.0.17763.379)
|
||||||
|
//
|
||||||
|
// Net result is as follows.
|
||||||
|
// Before:
|
||||||
|
// SHELL NON-REDIRECTED REDIRECTED
|
||||||
|
// explorer.exe no console n/a
|
||||||
|
// cmd.exe broken works
|
||||||
|
// powershell broken broken
|
||||||
|
// WSL bash broken works
|
||||||
|
// After
|
||||||
|
// SHELL NON-REDIRECTED REDIRECTED
|
||||||
|
// explorer.exe no console n/a
|
||||||
|
// cmd.exe works works
|
||||||
|
// powershell works broken
|
||||||
|
// WSL bash works works
|
||||||
|
//
|
||||||
|
// We don't seem to make anything worse, at least.
|
||||||
|
func FixConsoleIfNeeded() error {
|
||||||
|
// Retain the original console objects, to prevent Go from automatically
|
||||||
|
// closing their file descriptors when they get garbage collected.
|
||||||
|
// You never want to close file descriptors 0, 1, and 2.
|
||||||
|
oldStdin, oldStdout, oldStderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
|
|
||||||
|
stdin, _ := syscall.GetStdHandle(syscall.STD_INPUT_HANDLE)
|
||||||
|
stdout, _ := syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE)
|
||||||
|
stderr, _ := syscall.GetStdHandle(syscall.STD_ERROR_HANDLE)
|
||||||
|
|
||||||
|
var invalid syscall.Handle
|
||||||
|
con := invalid
|
||||||
|
|
||||||
|
if stdin == invalid || stdout == invalid || stderr == invalid {
|
||||||
|
err := AttachConsole()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("attachconsole: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stdin == invalid {
|
||||||
|
stdin, _ = syscall.GetStdHandle(syscall.STD_INPUT_HANDLE)
|
||||||
|
}
|
||||||
|
if stdout == invalid {
|
||||||
|
stdout, _ = syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE)
|
||||||
|
con = stdout
|
||||||
|
}
|
||||||
|
if stderr == invalid {
|
||||||
|
stderr, _ = syscall.GetStdHandle(syscall.STD_ERROR_HANDLE)
|
||||||
|
con = stderr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if con != invalid {
|
||||||
|
// Make sure the console is configured to convert
|
||||||
|
// \n to \r\n, like Go programs expect.
|
||||||
|
h := windows.Handle(con)
|
||||||
|
var st uint32
|
||||||
|
err := windows.GetConsoleMode(h, &st)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetConsoleMode: %v", err)
|
||||||
|
}
|
||||||
|
err = windows.SetConsoleMode(h, st&^windows.DISABLE_NEWLINE_AUTO_RETURN)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SetConsoleMode: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if stdin != invalid {
|
||||||
|
os.Stdin = os.NewFile(uintptr(stdin), "stdin")
|
||||||
|
}
|
||||||
|
if stdout != invalid {
|
||||||
|
os.Stdout = os.NewFile(uintptr(stdout), "stdout")
|
||||||
|
}
|
||||||
|
if stderr != invalid {
|
||||||
|
os.Stderr = os.NewFile(uintptr(stderr), "stderr")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
19
vendor/github.com/apenwarr/w32/AUTHORS
generated
vendored
Normal file
19
vendor/github.com/apenwarr/w32/AUTHORS
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# This is the official list of 'w32' authors for copyright purposes.
|
||||||
|
|
||||||
|
# Names should be added to this file as
|
||||||
|
# Name or Organization <email address>
|
||||||
|
# The email address is not required for organizations.
|
||||||
|
|
||||||
|
# Please keep the list sorted.
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
# ============
|
||||||
|
|
||||||
|
Allen Dang <allengnr@gmail.com>
|
||||||
|
Benny Siegert <bsiegert@gmail.com>
|
||||||
|
Bruno Bigras <bigras.bruno@gmail.com>
|
||||||
|
Daniel Joos
|
||||||
|
Gerald Rosenberg <gerald.rosenberg@gmail.com>
|
||||||
|
Liam Bowen <liambowen@gmail.com>
|
||||||
|
Michael Henke
|
||||||
|
Paul Maddox <paul.maddox@gmail.com>
|
||||||
23
vendor/github.com/apenwarr/w32/LICENSE
generated
vendored
Normal file
23
vendor/github.com/apenwarr/w32/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
Copyright (c) 2010-2012 The w32 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:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. 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.
|
||||||
|
3. The names of the authors may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||||
33
vendor/github.com/apenwarr/w32/README.md
generated
vendored
Normal file
33
vendor/github.com/apenwarr/w32/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
About w32
|
||||||
|
==========
|
||||||
|
|
||||||
|
w32 is a wrapper of windows apis for the Go Programming Language.
|
||||||
|
|
||||||
|
It wraps win32 apis to "Go style" to make them easier to use.
|
||||||
|
|
||||||
|
Setup
|
||||||
|
=====
|
||||||
|
|
||||||
|
1. Make sure you have a working Go installation and build environment,
|
||||||
|
see this go-nuts post for details:
|
||||||
|
http://groups.google.com/group/golang-nuts/msg/5c87630a84f4fd0c
|
||||||
|
|
||||||
|
Updated versions of the Windows Go build are available here:
|
||||||
|
http://code.google.com/p/gomingw/downloads/list
|
||||||
|
|
||||||
|
2. Create a "gopath" directory if you do not have one yet and set the
|
||||||
|
GOPATH variable accordingly. For example:
|
||||||
|
mkdir -p go-externals/src
|
||||||
|
export GOPATH=${PWD}/go-externals
|
||||||
|
|
||||||
|
3. go get github.com/AllenDang/w32
|
||||||
|
|
||||||
|
4. go install github.com/AllenDang/w32...
|
||||||
|
|
||||||
|
Contribute
|
||||||
|
==========
|
||||||
|
|
||||||
|
Contributions in form of design, code, documentation, bug reporting or other
|
||||||
|
ways you see fit are very welcome.
|
||||||
|
|
||||||
|
Thank You!
|
||||||
389
vendor/github.com/apenwarr/w32/advapi32.go
generated
vendored
Normal file
389
vendor/github.com/apenwarr/w32/advapi32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,389 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
|
||||||
|
|
||||||
|
// procRegSetKeyValue = modadvapi32.NewProc("RegSetKeyValueW")
|
||||||
|
procCloseEventLog = modadvapi32.NewProc("CloseEventLog")
|
||||||
|
procCloseServiceHandle = modadvapi32.NewProc("CloseServiceHandle")
|
||||||
|
procControlService = modadvapi32.NewProc("ControlService")
|
||||||
|
procControlTrace = modadvapi32.NewProc("ControlTraceW")
|
||||||
|
procInitializeSecurityDescriptor = modadvapi32.NewProc("InitializeSecurityDescriptor")
|
||||||
|
procOpenEventLog = modadvapi32.NewProc("OpenEventLogW")
|
||||||
|
procOpenSCManager = modadvapi32.NewProc("OpenSCManagerW")
|
||||||
|
procOpenService = modadvapi32.NewProc("OpenServiceW")
|
||||||
|
procReadEventLog = modadvapi32.NewProc("ReadEventLogW")
|
||||||
|
procRegCloseKey = modadvapi32.NewProc("RegCloseKey")
|
||||||
|
procRegCreateKeyEx = modadvapi32.NewProc("RegCreateKeyExW")
|
||||||
|
procRegEnumKeyEx = modadvapi32.NewProc("RegEnumKeyExW")
|
||||||
|
procRegGetValue = modadvapi32.NewProc("RegGetValueW")
|
||||||
|
procRegOpenKeyEx = modadvapi32.NewProc("RegOpenKeyExW")
|
||||||
|
procRegSetValueEx = modadvapi32.NewProc("RegSetValueExW")
|
||||||
|
procSetSecurityDescriptorDacl = modadvapi32.NewProc("SetSecurityDescriptorDacl")
|
||||||
|
procStartService = modadvapi32.NewProc("StartServiceW")
|
||||||
|
procStartTrace = modadvapi32.NewProc("StartTraceW")
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
SystemTraceControlGuid = GUID{
|
||||||
|
0x9e814aad,
|
||||||
|
0x3204,
|
||||||
|
0x11d2,
|
||||||
|
[8]byte{0x9a, 0x82, 0x00, 0x60, 0x08, 0xa8, 0x69, 0x39},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegCreateKey(hKey HKEY, subKey string) HKEY {
|
||||||
|
var result HKEY
|
||||||
|
ret, _, _ := procRegCreateKeyEx.Call(
|
||||||
|
uintptr(hKey),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))),
|
||||||
|
uintptr(0),
|
||||||
|
uintptr(0),
|
||||||
|
uintptr(0),
|
||||||
|
uintptr(KEY_ALL_ACCESS),
|
||||||
|
uintptr(0),
|
||||||
|
uintptr(unsafe.Pointer(&result)),
|
||||||
|
uintptr(0))
|
||||||
|
_ = ret
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegOpenKeyEx(hKey HKEY, subKey string, samDesired uint32) HKEY {
|
||||||
|
var result HKEY
|
||||||
|
ret, _, _ := procRegOpenKeyEx.Call(
|
||||||
|
uintptr(hKey),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))),
|
||||||
|
uintptr(0),
|
||||||
|
uintptr(samDesired),
|
||||||
|
uintptr(unsafe.Pointer(&result)))
|
||||||
|
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
panic(fmt.Sprintf("RegOpenKeyEx(%d, %s, %d) failed", hKey, subKey, samDesired))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegCloseKey(hKey HKEY) error {
|
||||||
|
var err error
|
||||||
|
ret, _, _ := procRegCloseKey.Call(
|
||||||
|
uintptr(hKey))
|
||||||
|
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
err = errors.New("RegCloseKey failed")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegGetRaw(hKey HKEY, subKey string, value string) []byte {
|
||||||
|
var bufLen uint32
|
||||||
|
var valptr unsafe.Pointer
|
||||||
|
if len(value) > 0 {
|
||||||
|
valptr = unsafe.Pointer(syscall.StringToUTF16Ptr(value))
|
||||||
|
}
|
||||||
|
procRegGetValue.Call(
|
||||||
|
uintptr(hKey),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))),
|
||||||
|
uintptr(valptr),
|
||||||
|
uintptr(RRF_RT_ANY),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(&bufLen)))
|
||||||
|
|
||||||
|
if bufLen == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, bufLen)
|
||||||
|
ret, _, _ := procRegGetValue.Call(
|
||||||
|
uintptr(hKey),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))),
|
||||||
|
uintptr(valptr),
|
||||||
|
uintptr(RRF_RT_ANY),
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
|
uintptr(unsafe.Pointer(&bufLen)))
|
||||||
|
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegSetBinary(hKey HKEY, subKey string, value []byte) (errno int) {
|
||||||
|
var lptr, vptr unsafe.Pointer
|
||||||
|
if len(subKey) > 0 {
|
||||||
|
lptr = unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))
|
||||||
|
}
|
||||||
|
if len(value) > 0 {
|
||||||
|
vptr = unsafe.Pointer(&value[0])
|
||||||
|
}
|
||||||
|
ret, _, _ := procRegSetValueEx.Call(
|
||||||
|
uintptr(hKey),
|
||||||
|
uintptr(lptr),
|
||||||
|
uintptr(0),
|
||||||
|
uintptr(REG_BINARY),
|
||||||
|
uintptr(vptr),
|
||||||
|
uintptr(len(value)))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegGetString(hKey HKEY, subKey string, value string) string {
|
||||||
|
var bufLen uint32
|
||||||
|
procRegGetValue.Call(
|
||||||
|
uintptr(hKey),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(value))),
|
||||||
|
uintptr(RRF_RT_REG_SZ),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(&bufLen)))
|
||||||
|
|
||||||
|
if bufLen == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]uint16, bufLen)
|
||||||
|
ret, _, _ := procRegGetValue.Call(
|
||||||
|
uintptr(hKey),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(value))),
|
||||||
|
uintptr(RRF_RT_REG_SZ),
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
|
uintptr(unsafe.Pointer(&bufLen)))
|
||||||
|
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return syscall.UTF16ToString(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func RegSetKeyValue(hKey HKEY, subKey string, valueName string, dwType uint32, data uintptr, cbData uint16) (errno int) {
|
||||||
|
ret, _, _ := procRegSetKeyValue.Call(
|
||||||
|
uintptr(hKey),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(valueName))),
|
||||||
|
uintptr(dwType),
|
||||||
|
data,
|
||||||
|
uintptr(cbData))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func RegEnumKeyEx(hKey HKEY, index uint32) string {
|
||||||
|
var bufLen uint32 = 255
|
||||||
|
buf := make([]uint16, bufLen)
|
||||||
|
procRegEnumKeyEx.Call(
|
||||||
|
uintptr(hKey),
|
||||||
|
uintptr(index),
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
|
uintptr(unsafe.Pointer(&bufLen)),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
return syscall.UTF16ToString(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func OpenEventLog(servername string, sourcename string) HANDLE {
|
||||||
|
ret, _, _ := procOpenEventLog.Call(
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(servername))),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(sourcename))))
|
||||||
|
|
||||||
|
return HANDLE(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadEventLog(eventlog HANDLE, readflags, recordoffset uint32, buffer []byte, numberofbytestoread uint32, bytesread, minnumberofbytesneeded *uint32) bool {
|
||||||
|
ret, _, _ := procReadEventLog.Call(
|
||||||
|
uintptr(eventlog),
|
||||||
|
uintptr(readflags),
|
||||||
|
uintptr(recordoffset),
|
||||||
|
uintptr(unsafe.Pointer(&buffer[0])),
|
||||||
|
uintptr(numberofbytestoread),
|
||||||
|
uintptr(unsafe.Pointer(bytesread)),
|
||||||
|
uintptr(unsafe.Pointer(minnumberofbytesneeded)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func CloseEventLog(eventlog HANDLE) bool {
|
||||||
|
ret, _, _ := procCloseEventLog.Call(
|
||||||
|
uintptr(eventlog))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func OpenSCManager(lpMachineName, lpDatabaseName string, dwDesiredAccess uint32) (HANDLE, error) {
|
||||||
|
var p1, p2 uintptr
|
||||||
|
if len(lpMachineName) > 0 {
|
||||||
|
p1 = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpMachineName)))
|
||||||
|
}
|
||||||
|
if len(lpDatabaseName) > 0 {
|
||||||
|
p2 = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDatabaseName)))
|
||||||
|
}
|
||||||
|
ret, _, _ := procOpenSCManager.Call(
|
||||||
|
p1,
|
||||||
|
p2,
|
||||||
|
uintptr(dwDesiredAccess))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
return 0, syscall.GetLastError()
|
||||||
|
}
|
||||||
|
|
||||||
|
return HANDLE(ret), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CloseServiceHandle(hSCObject HANDLE) error {
|
||||||
|
ret, _, _ := procCloseServiceHandle.Call(uintptr(hSCObject))
|
||||||
|
if ret == 0 {
|
||||||
|
return syscall.GetLastError()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func OpenService(hSCManager HANDLE, lpServiceName string, dwDesiredAccess uint32) (HANDLE, error) {
|
||||||
|
ret, _, _ := procOpenService.Call(
|
||||||
|
uintptr(hSCManager),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpServiceName))),
|
||||||
|
uintptr(dwDesiredAccess))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
return 0, syscall.GetLastError()
|
||||||
|
}
|
||||||
|
|
||||||
|
return HANDLE(ret), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartService(hService HANDLE, lpServiceArgVectors []string) error {
|
||||||
|
l := len(lpServiceArgVectors)
|
||||||
|
var ret uintptr
|
||||||
|
if l == 0 {
|
||||||
|
ret, _, _ = procStartService.Call(
|
||||||
|
uintptr(hService),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
} else {
|
||||||
|
lpArgs := make([]uintptr, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
lpArgs[i] = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpServiceArgVectors[i])))
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, _ = procStartService.Call(
|
||||||
|
uintptr(hService),
|
||||||
|
uintptr(l),
|
||||||
|
uintptr(unsafe.Pointer(&lpArgs[0])))
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
return syscall.GetLastError()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ControlService(hService HANDLE, dwControl uint32, lpServiceStatus *SERVICE_STATUS) bool {
|
||||||
|
if lpServiceStatus == nil {
|
||||||
|
panic("ControlService:lpServiceStatus cannot be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, _ := procControlService.Call(
|
||||||
|
uintptr(hService),
|
||||||
|
uintptr(dwControl),
|
||||||
|
uintptr(unsafe.Pointer(lpServiceStatus)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ControlTrace(hTrace TRACEHANDLE, lpSessionName string, props *EVENT_TRACE_PROPERTIES, dwControl uint32) (success bool, e error) {
|
||||||
|
|
||||||
|
ret, _, _ := procControlTrace.Call(
|
||||||
|
uintptr(unsafe.Pointer(hTrace)),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpSessionName))),
|
||||||
|
uintptr(unsafe.Pointer(props)),
|
||||||
|
uintptr(dwControl))
|
||||||
|
|
||||||
|
if ret == ERROR_SUCCESS {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
e = errors.New(fmt.Sprintf("error: 0x%x", ret))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartTrace(lpSessionName string, props *EVENT_TRACE_PROPERTIES) (hTrace TRACEHANDLE, e error) {
|
||||||
|
|
||||||
|
ret, _, _ := procStartTrace.Call(
|
||||||
|
uintptr(unsafe.Pointer(&hTrace)),
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpSessionName))),
|
||||||
|
uintptr(unsafe.Pointer(props)))
|
||||||
|
|
||||||
|
if ret == ERROR_SUCCESS {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e = errors.New(fmt.Sprintf("error: 0x%x", ret))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa378863(v=vs.85).aspx
|
||||||
|
func InitializeSecurityDescriptor(rev uint16) (pSecurityDescriptor *SECURITY_DESCRIPTOR, e error) {
|
||||||
|
|
||||||
|
pSecurityDescriptor = &SECURITY_DESCRIPTOR{}
|
||||||
|
|
||||||
|
ret, _, _ := procInitializeSecurityDescriptor.Call(
|
||||||
|
uintptr(unsafe.Pointer(pSecurityDescriptor)),
|
||||||
|
uintptr(rev),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e = syscall.GetLastError()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa379583(v=vs.85).aspx
|
||||||
|
func SetSecurityDescriptorDacl(pSecurityDescriptor *SECURITY_DESCRIPTOR, pDacl *ACL) (e error) {
|
||||||
|
|
||||||
|
if pSecurityDescriptor == nil {
|
||||||
|
return errors.New("null descriptor")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret uintptr
|
||||||
|
if pDacl == nil {
|
||||||
|
ret, _, _ = procSetSecurityDescriptorDacl.Call(
|
||||||
|
uintptr(unsafe.Pointer(pSecurityDescriptor)),
|
||||||
|
uintptr(1), // DaclPresent
|
||||||
|
uintptr(0), // pDacl
|
||||||
|
uintptr(0), // DaclDefaulted
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ret, _, _ = procSetSecurityDescriptorDacl.Call(
|
||||||
|
uintptr(unsafe.Pointer(pSecurityDescriptor)),
|
||||||
|
uintptr(1), // DaclPresent
|
||||||
|
uintptr(unsafe.Pointer(pDacl)),
|
||||||
|
uintptr(0), //DaclDefaulted
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e = syscall.GetLastError()
|
||||||
|
return
|
||||||
|
}
|
||||||
300
vendor/github.com/apenwarr/w32/advapi32_constants.go
generated
vendored
Normal file
300
vendor/github.com/apenwarr/w32/advapi32_constants.go
generated
vendored
Normal file
|
|
@ -0,0 +1,300 @@
|
||||||
|
package w32
|
||||||
|
|
||||||
|
// Registry predefined keys
|
||||||
|
const (
|
||||||
|
HKEY_CLASSES_ROOT HKEY = 0x80000000
|
||||||
|
HKEY_CURRENT_USER HKEY = 0x80000001
|
||||||
|
HKEY_LOCAL_MACHINE HKEY = 0x80000002
|
||||||
|
HKEY_USERS HKEY = 0x80000003
|
||||||
|
HKEY_PERFORMANCE_DATA HKEY = 0x80000004
|
||||||
|
HKEY_CURRENT_CONFIG HKEY = 0x80000005
|
||||||
|
HKEY_DYN_DATA HKEY = 0x80000006
|
||||||
|
)
|
||||||
|
|
||||||
|
// Registry Key Security and Access Rights
|
||||||
|
const (
|
||||||
|
KEY_ALL_ACCESS = 0xF003F
|
||||||
|
KEY_CREATE_SUB_KEY = 0x0004
|
||||||
|
KEY_ENUMERATE_SUB_KEYS = 0x0008
|
||||||
|
KEY_NOTIFY = 0x0010
|
||||||
|
KEY_QUERY_VALUE = 0x0001
|
||||||
|
KEY_SET_VALUE = 0x0002
|
||||||
|
KEY_READ = 0x20019
|
||||||
|
KEY_WRITE = 0x20006
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NFR_ANSI = 1
|
||||||
|
NFR_UNICODE = 2
|
||||||
|
NF_QUERY = 3
|
||||||
|
NF_REQUERY = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// Registry value types
|
||||||
|
const (
|
||||||
|
RRF_RT_REG_NONE = 0x00000001
|
||||||
|
RRF_RT_REG_SZ = 0x00000002
|
||||||
|
RRF_RT_REG_EXPAND_SZ = 0x00000004
|
||||||
|
RRF_RT_REG_BINARY = 0x00000008
|
||||||
|
RRF_RT_REG_DWORD = 0x00000010
|
||||||
|
RRF_RT_REG_MULTI_SZ = 0x00000020
|
||||||
|
RRF_RT_REG_QWORD = 0x00000040
|
||||||
|
RRF_RT_DWORD = (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD)
|
||||||
|
RRF_RT_QWORD = (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD)
|
||||||
|
RRF_RT_ANY = 0x0000ffff
|
||||||
|
RRF_NOEXPAND = 0x10000000
|
||||||
|
RRF_ZEROONFAILURE = 0x20000000
|
||||||
|
REG_PROCESS_APPKEY = 0x00000001
|
||||||
|
REG_MUI_STRING_TRUNCATE = 0x00000001
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service Control Manager object specific access types
|
||||||
|
const (
|
||||||
|
SC_MANAGER_CONNECT = 0x0001
|
||||||
|
SC_MANAGER_CREATE_SERVICE = 0x0002
|
||||||
|
SC_MANAGER_ENUMERATE_SERVICE = 0x0004
|
||||||
|
SC_MANAGER_LOCK = 0x0008
|
||||||
|
SC_MANAGER_QUERY_LOCK_STATUS = 0x0010
|
||||||
|
SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020
|
||||||
|
SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS | SC_MANAGER_MODIFY_BOOT_CONFIG
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service Types (Bit Mask)
|
||||||
|
const (
|
||||||
|
SERVICE_KERNEL_DRIVER = 0x00000001
|
||||||
|
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
|
||||||
|
SERVICE_ADAPTER = 0x00000004
|
||||||
|
SERVICE_RECOGNIZER_DRIVER = 0x00000008
|
||||||
|
SERVICE_DRIVER = SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER
|
||||||
|
SERVICE_WIN32_OWN_PROCESS = 0x00000010
|
||||||
|
SERVICE_WIN32_SHARE_PROCESS = 0x00000020
|
||||||
|
SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS
|
||||||
|
SERVICE_INTERACTIVE_PROCESS = 0x00000100
|
||||||
|
SERVICE_TYPE_ALL = SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service State -- for CurrentState
|
||||||
|
const (
|
||||||
|
SERVICE_STOPPED = 0x00000001
|
||||||
|
SERVICE_START_PENDING = 0x00000002
|
||||||
|
SERVICE_STOP_PENDING = 0x00000003
|
||||||
|
SERVICE_RUNNING = 0x00000004
|
||||||
|
SERVICE_CONTINUE_PENDING = 0x00000005
|
||||||
|
SERVICE_PAUSE_PENDING = 0x00000006
|
||||||
|
SERVICE_PAUSED = 0x00000007
|
||||||
|
)
|
||||||
|
|
||||||
|
// Controls Accepted (Bit Mask)
|
||||||
|
const (
|
||||||
|
SERVICE_ACCEPT_STOP = 0x00000001
|
||||||
|
SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
|
||||||
|
SERVICE_ACCEPT_SHUTDOWN = 0x00000004
|
||||||
|
SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
|
||||||
|
SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010
|
||||||
|
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
|
||||||
|
SERVICE_ACCEPT_POWEREVENT = 0x00000040
|
||||||
|
SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
|
||||||
|
SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
|
||||||
|
SERVICE_ACCEPT_TIMECHANGE = 0x00000200
|
||||||
|
SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service object specific access type
|
||||||
|
const (
|
||||||
|
SERVICE_QUERY_CONFIG = 0x0001
|
||||||
|
SERVICE_CHANGE_CONFIG = 0x0002
|
||||||
|
SERVICE_QUERY_STATUS = 0x0004
|
||||||
|
SERVICE_ENUMERATE_DEPENDENTS = 0x0008
|
||||||
|
SERVICE_START = 0x0010
|
||||||
|
SERVICE_STOP = 0x0020
|
||||||
|
SERVICE_PAUSE_CONTINUE = 0x0040
|
||||||
|
SERVICE_INTERROGATE = 0x0080
|
||||||
|
SERVICE_USER_DEFINED_CONTROL = 0x0100
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KERNEL_LOGGER_NAME = "NT Kernel Logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WNODE flags, for ETW (Event Tracing for Windows) / WMI
|
||||||
|
const (
|
||||||
|
WNODE_FLAG_ALL_DATA = 0x00000001
|
||||||
|
WNODE_FLAG_SINGLE_INSTANCE = 0x00000002
|
||||||
|
WNODE_FLAG_SINGLE_ITEM = 0x00000004
|
||||||
|
WNODE_FLAG_EVENT_ITEM = 0x00000008
|
||||||
|
WNODE_FLAG_FIXED_INSTANCE_SIZE = 0x00000010
|
||||||
|
WNODE_FLAG_TOO_SMALL = 0x00000020
|
||||||
|
WNODE_FLAG_INSTANCES_SAME = 0x00000040
|
||||||
|
WNODE_FLAG_STATIC_INSTANCE_NAMES = 0x00000080
|
||||||
|
WNODE_FLAG_INTERNAL = 0x00000100
|
||||||
|
WNODE_FLAG_USE_TIMESTAMP = 0x00000200
|
||||||
|
WNODE_FLAG_PERSIST_EVENT = 0x00000400
|
||||||
|
WNODE_FLAG_EVENT_REFERENCE = 0x00002000
|
||||||
|
WNODE_FLAG_ANSI_INSTANCENAMES = 0x00004000
|
||||||
|
WNODE_FLAG_METHOD_ITEM = 0x00008000
|
||||||
|
WNODE_FLAG_PDO_INSTANCE_NAMES = 0x00010000
|
||||||
|
WNODE_FLAG_TRACED_GUID = 0x00020000
|
||||||
|
WNODE_FLAG_LOG_WNODE = 0x00040000
|
||||||
|
WNODE_FLAG_USE_GUID_PTR = 0x00080000
|
||||||
|
WNODE_FLAG_USE_MOF_PTR = 0x00100000
|
||||||
|
WNODE_FLAG_NO_HEADER = 0x00200000
|
||||||
|
WNODE_FLAG_SEVERITY_MASK = 0xff000000
|
||||||
|
)
|
||||||
|
|
||||||
|
// ETW flags and types etc
|
||||||
|
const (
|
||||||
|
EVENT_TRACE_TYPE_INFO = 0x00
|
||||||
|
EVENT_TRACE_TYPE_START = 0x01
|
||||||
|
EVENT_TRACE_TYPE_END = 0x02
|
||||||
|
EVENT_TRACE_TYPE_STOP = 0x02
|
||||||
|
EVENT_TRACE_TYPE_DC_START = 0x03
|
||||||
|
EVENT_TRACE_TYPE_DC_END = 0x04
|
||||||
|
EVENT_TRACE_TYPE_EXTENSION = 0x05
|
||||||
|
EVENT_TRACE_TYPE_REPLY = 0x06
|
||||||
|
EVENT_TRACE_TYPE_DEQUEUE = 0x07
|
||||||
|
EVENT_TRACE_TYPE_RESUME = 0x07
|
||||||
|
EVENT_TRACE_TYPE_CHECKPOINT = 0x08
|
||||||
|
EVENT_TRACE_TYPE_SUSPEND = 0x08
|
||||||
|
EVENT_TRACE_TYPE_WINEVT_SEND = 0x09
|
||||||
|
EVENT_TRACE_TYPE_WINEVT_RECEIVE = 0XF0
|
||||||
|
TRACE_LEVEL_NONE = 0
|
||||||
|
TRACE_LEVEL_CRITICAL = 1
|
||||||
|
TRACE_LEVEL_FATAL = 1
|
||||||
|
TRACE_LEVEL_ERROR = 2
|
||||||
|
TRACE_LEVEL_WARNING = 3
|
||||||
|
TRACE_LEVEL_INFORMATION = 4
|
||||||
|
TRACE_LEVEL_VERBOSE = 5
|
||||||
|
TRACE_LEVEL_RESERVED6 = 6
|
||||||
|
TRACE_LEVEL_RESERVED7 = 7
|
||||||
|
TRACE_LEVEL_RESERVED8 = 8
|
||||||
|
TRACE_LEVEL_RESERVED9 = 9
|
||||||
|
EVENT_TRACE_TYPE_LOAD = 0x0A
|
||||||
|
EVENT_TRACE_TYPE_IO_READ = 0x0A
|
||||||
|
EVENT_TRACE_TYPE_IO_WRITE = 0x0B
|
||||||
|
EVENT_TRACE_TYPE_IO_READ_INIT = 0x0C
|
||||||
|
EVENT_TRACE_TYPE_IO_WRITE_INIT = 0x0D
|
||||||
|
EVENT_TRACE_TYPE_IO_FLUSH = 0x0E
|
||||||
|
EVENT_TRACE_TYPE_IO_FLUSH_INIT = 0x0F
|
||||||
|
EVENT_TRACE_TYPE_MM_TF = 0x0A
|
||||||
|
EVENT_TRACE_TYPE_MM_DZF = 0x0B
|
||||||
|
EVENT_TRACE_TYPE_MM_COW = 0x0C
|
||||||
|
EVENT_TRACE_TYPE_MM_GPF = 0x0D
|
||||||
|
EVENT_TRACE_TYPE_MM_HPF = 0x0E
|
||||||
|
EVENT_TRACE_TYPE_MM_AV = 0x0F
|
||||||
|
EVENT_TRACE_TYPE_SEND = 0x0A
|
||||||
|
EVENT_TRACE_TYPE_RECEIVE = 0x0B
|
||||||
|
EVENT_TRACE_TYPE_CONNECT = 0x0C
|
||||||
|
EVENT_TRACE_TYPE_DISCONNECT = 0x0D
|
||||||
|
EVENT_TRACE_TYPE_RETRANSMIT = 0x0E
|
||||||
|
EVENT_TRACE_TYPE_ACCEPT = 0x0F
|
||||||
|
EVENT_TRACE_TYPE_RECONNECT = 0x10
|
||||||
|
EVENT_TRACE_TYPE_CONNFAIL = 0x11
|
||||||
|
EVENT_TRACE_TYPE_COPY_TCP = 0x12
|
||||||
|
EVENT_TRACE_TYPE_COPY_ARP = 0x13
|
||||||
|
EVENT_TRACE_TYPE_ACKFULL = 0x14
|
||||||
|
EVENT_TRACE_TYPE_ACKPART = 0x15
|
||||||
|
EVENT_TRACE_TYPE_ACKDUP = 0x16
|
||||||
|
EVENT_TRACE_TYPE_GUIDMAP = 0x0A
|
||||||
|
EVENT_TRACE_TYPE_CONFIG = 0x0B
|
||||||
|
EVENT_TRACE_TYPE_SIDINFO = 0x0C
|
||||||
|
EVENT_TRACE_TYPE_SECURITY = 0x0D
|
||||||
|
EVENT_TRACE_TYPE_REGCREATE = 0x0A
|
||||||
|
EVENT_TRACE_TYPE_REGOPEN = 0x0B
|
||||||
|
EVENT_TRACE_TYPE_REGDELETE = 0x0C
|
||||||
|
EVENT_TRACE_TYPE_REGQUERY = 0x0D
|
||||||
|
EVENT_TRACE_TYPE_REGSETVALUE = 0x0E
|
||||||
|
EVENT_TRACE_TYPE_REGDELETEVALUE = 0x0F
|
||||||
|
EVENT_TRACE_TYPE_REGQUERYVALUE = 0x10
|
||||||
|
EVENT_TRACE_TYPE_REGENUMERATEKEY = 0x11
|
||||||
|
EVENT_TRACE_TYPE_REGENUMERATEVALUEKEY = 0x12
|
||||||
|
EVENT_TRACE_TYPE_REGQUERYMULTIPLEVALUE = 0x13
|
||||||
|
EVENT_TRACE_TYPE_REGSETINFORMATION = 0x14
|
||||||
|
EVENT_TRACE_TYPE_REGFLUSH = 0x15
|
||||||
|
EVENT_TRACE_TYPE_REGKCBCREATE = 0x16
|
||||||
|
EVENT_TRACE_TYPE_REGKCBDELETE = 0x17
|
||||||
|
EVENT_TRACE_TYPE_REGKCBRUNDOWNBEGIN = 0x18
|
||||||
|
EVENT_TRACE_TYPE_REGKCBRUNDOWNEND = 0x19
|
||||||
|
EVENT_TRACE_TYPE_REGVIRTUALIZE = 0x1A
|
||||||
|
EVENT_TRACE_TYPE_REGCLOSE = 0x1B
|
||||||
|
EVENT_TRACE_TYPE_REGSETSECURITY = 0x1C
|
||||||
|
EVENT_TRACE_TYPE_REGQUERYSECURITY = 0x1D
|
||||||
|
EVENT_TRACE_TYPE_REGCOMMIT = 0x1E
|
||||||
|
EVENT_TRACE_TYPE_REGPREPARE = 0x1F
|
||||||
|
EVENT_TRACE_TYPE_REGROLLBACK = 0x20
|
||||||
|
EVENT_TRACE_TYPE_REGMOUNTHIVE = 0x21
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_CPU = 0x0A
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_PHYSICALDISK = 0x0B
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_LOGICALDISK = 0x0C
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_NIC = 0x0D
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_VIDEO = 0x0E
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_SERVICES = 0x0F
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_POWER = 0x10
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_NETINFO = 0x11
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_IRQ = 0x15
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_PNP = 0x16
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_IDECHANNEL = 0x17
|
||||||
|
EVENT_TRACE_TYPE_CONFIG_PLATFORM = 0x19
|
||||||
|
EVENT_TRACE_FLAG_PROCESS = 0x00000001
|
||||||
|
EVENT_TRACE_FLAG_THREAD = 0x00000002
|
||||||
|
EVENT_TRACE_FLAG_IMAGE_LOAD = 0x00000004
|
||||||
|
EVENT_TRACE_FLAG_DISK_IO = 0x00000100
|
||||||
|
EVENT_TRACE_FLAG_DISK_FILE_IO = 0x00000200
|
||||||
|
EVENT_TRACE_FLAG_MEMORY_PAGE_FAULTS = 0x00001000
|
||||||
|
EVENT_TRACE_FLAG_MEMORY_HARD_FAULTS = 0x00002000
|
||||||
|
EVENT_TRACE_FLAG_NETWORK_TCPIP = 0x00010000
|
||||||
|
EVENT_TRACE_FLAG_REGISTRY = 0x00020000
|
||||||
|
EVENT_TRACE_FLAG_DBGPRINT = 0x00040000
|
||||||
|
EVENT_TRACE_FLAG_PROCESS_COUNTERS = 0x00000008
|
||||||
|
EVENT_TRACE_FLAG_CSWITCH = 0x00000010
|
||||||
|
EVENT_TRACE_FLAG_DPC = 0x00000020
|
||||||
|
EVENT_TRACE_FLAG_INTERRUPT = 0x00000040
|
||||||
|
EVENT_TRACE_FLAG_SYSTEMCALL = 0x00000080
|
||||||
|
EVENT_TRACE_FLAG_DISK_IO_INIT = 0x00000400
|
||||||
|
EVENT_TRACE_FLAG_ALPC = 0x00100000
|
||||||
|
EVENT_TRACE_FLAG_SPLIT_IO = 0x00200000
|
||||||
|
EVENT_TRACE_FLAG_DRIVER = 0x00800000
|
||||||
|
EVENT_TRACE_FLAG_PROFILE = 0x01000000
|
||||||
|
EVENT_TRACE_FLAG_FILE_IO = 0x02000000
|
||||||
|
EVENT_TRACE_FLAG_FILE_IO_INIT = 0x04000000
|
||||||
|
EVENT_TRACE_FLAG_DISPATCHER = 0x00000800
|
||||||
|
EVENT_TRACE_FLAG_VIRTUAL_ALLOC = 0x00004000
|
||||||
|
EVENT_TRACE_FLAG_EXTENSION = 0x80000000
|
||||||
|
EVENT_TRACE_FLAG_FORWARD_WMI = 0x40000000
|
||||||
|
EVENT_TRACE_FLAG_ENABLE_RESERVE = 0x20000000
|
||||||
|
EVENT_TRACE_FILE_MODE_NONE = 0x00000000
|
||||||
|
EVENT_TRACE_FILE_MODE_SEQUENTIAL = 0x00000001
|
||||||
|
EVENT_TRACE_FILE_MODE_CIRCULAR = 0x00000002
|
||||||
|
EVENT_TRACE_FILE_MODE_APPEND = 0x00000004
|
||||||
|
EVENT_TRACE_REAL_TIME_MODE = 0x00000100
|
||||||
|
EVENT_TRACE_DELAY_OPEN_FILE_MODE = 0x00000200
|
||||||
|
EVENT_TRACE_BUFFERING_MODE = 0x00000400
|
||||||
|
EVENT_TRACE_PRIVATE_LOGGER_MODE = 0x00000800
|
||||||
|
EVENT_TRACE_ADD_HEADER_MODE = 0x00001000
|
||||||
|
EVENT_TRACE_USE_GLOBAL_SEQUENCE = 0x00004000
|
||||||
|
EVENT_TRACE_USE_LOCAL_SEQUENCE = 0x00008000
|
||||||
|
EVENT_TRACE_RELOG_MODE = 0x00010000
|
||||||
|
EVENT_TRACE_USE_PAGED_MEMORY = 0x01000000
|
||||||
|
EVENT_TRACE_FILE_MODE_NEWFILE = 0x00000008
|
||||||
|
EVENT_TRACE_FILE_MODE_PREALLOCATE = 0x00000020
|
||||||
|
EVENT_TRACE_NONSTOPPABLE_MODE = 0x00000040
|
||||||
|
EVENT_TRACE_SECURE_MODE = 0x00000080
|
||||||
|
EVENT_TRACE_USE_KBYTES_FOR_SIZE = 0x00002000
|
||||||
|
EVENT_TRACE_PRIVATE_IN_PROC = 0x00020000
|
||||||
|
EVENT_TRACE_MODE_RESERVED = 0x00100000
|
||||||
|
EVENT_TRACE_NO_PER_PROCESSOR_BUFFERING = 0x10000000
|
||||||
|
EVENT_TRACE_CONTROL_QUERY = 0
|
||||||
|
EVENT_TRACE_CONTROL_STOP = 1
|
||||||
|
EVENT_TRACE_CONTROL_UPDATE = 2
|
||||||
|
EVENT_TRACE_CONTROL_FLUSH = 3
|
||||||
|
)
|
||||||
122
vendor/github.com/apenwarr/w32/advapi32_typedef.go
generated
vendored
Normal file
122
vendor/github.com/apenwarr/w32/advapi32_typedef.go
generated
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
package w32
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa374931(v=vs.85).aspx
|
||||||
|
type ACL struct {
|
||||||
|
AclRevision byte
|
||||||
|
Sbz1 byte
|
||||||
|
AclSize uint16
|
||||||
|
AceCount uint16
|
||||||
|
Sbz2 uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa379561(v=vs.85).aspx
|
||||||
|
|
||||||
|
type SECURITY_DESCRIPTOR_CONTROL uint16
|
||||||
|
|
||||||
|
type SECURITY_DESCRIPTOR struct {
|
||||||
|
Revision byte
|
||||||
|
Sbz1 byte
|
||||||
|
Control SECURITY_DESCRIPTOR_CONTROL
|
||||||
|
Owner uintptr
|
||||||
|
Group uintptr
|
||||||
|
Sacl *ACL
|
||||||
|
Dacl *ACL
|
||||||
|
}
|
||||||
|
|
||||||
|
type SID_IDENTIFIER_AUTHORITY struct {
|
||||||
|
Value [6]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// typedef struct _SID // 4 elements, 0xC bytes (sizeof)
|
||||||
|
// {
|
||||||
|
// /*0x000*/ UINT8 Revision;
|
||||||
|
// /*0x001*/ UINT8 SubAuthorityCount;
|
||||||
|
// /*0x002*/ struct _SID_IDENTIFIER_AUTHORITY IdentifierAuthority; // 1 elements, 0x6 bytes (sizeof)
|
||||||
|
// /*0x008*/ ULONG32 SubAuthority[1];
|
||||||
|
// }SID, *PSID;
|
||||||
|
type SID struct {
|
||||||
|
Revision byte
|
||||||
|
SubAuthorityCount byte
|
||||||
|
IdentifierAuthority SID_IDENTIFIER_AUTHORITY
|
||||||
|
SubAuthority uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa363646.aspx
|
||||||
|
type EVENTLOGRECORD struct {
|
||||||
|
Length uint32
|
||||||
|
Reserved uint32
|
||||||
|
RecordNumber uint32
|
||||||
|
TimeGenerated uint32
|
||||||
|
TimeWritten uint32
|
||||||
|
EventID uint32
|
||||||
|
EventType uint16
|
||||||
|
NumStrings uint16
|
||||||
|
EventCategory uint16
|
||||||
|
ReservedFlags uint16
|
||||||
|
ClosingRecordNumber uint32
|
||||||
|
StringOffset uint32
|
||||||
|
UserSidLength uint32
|
||||||
|
UserSidOffset uint32
|
||||||
|
DataLength uint32
|
||||||
|
DataOffset uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms685996.aspx
|
||||||
|
type SERVICE_STATUS struct {
|
||||||
|
DwServiceType uint32
|
||||||
|
DwCurrentState uint32
|
||||||
|
DwControlsAccepted uint32
|
||||||
|
DwWin32ExitCode uint32
|
||||||
|
DwServiceSpecificExitCode uint32
|
||||||
|
DwCheckPoint uint32
|
||||||
|
DwWaitHint uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364160(v=vs.85).aspx
|
||||||
|
type WNODE_HEADER struct {
|
||||||
|
BufferSize uint32
|
||||||
|
ProviderId uint32
|
||||||
|
HistoricalContext uint64
|
||||||
|
KernelHandle HANDLE
|
||||||
|
Guid GUID
|
||||||
|
ClientContext uint32
|
||||||
|
Flags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// These partially compensate for the anonymous unions we removed, but there
|
||||||
|
// are no setters.
|
||||||
|
func (w WNODE_HEADER) TimeStamp() uint64 {
|
||||||
|
// TODO: Cast to the stupid LARGE_INTEGER struct which is, itself, nasty
|
||||||
|
// and union-y
|
||||||
|
return uint64(w.KernelHandle)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WNODE_HEADER) Version() uint32 {
|
||||||
|
return uint32(w.HistoricalContext >> 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WNODE_HEADER) Linkage() uint32 {
|
||||||
|
return uint32(w.HistoricalContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa363784(v=vs.85).aspx
|
||||||
|
type EVENT_TRACE_PROPERTIES struct {
|
||||||
|
Wnode WNODE_HEADER
|
||||||
|
BufferSize uint32
|
||||||
|
MinimumBuffers uint32
|
||||||
|
MaximumBuffers uint32
|
||||||
|
MaximumFileSize uint32
|
||||||
|
LogFileMode uint32
|
||||||
|
FlushTimer uint32
|
||||||
|
EnableFlags uint32
|
||||||
|
AgeLimit int32
|
||||||
|
NumberOfBuffers uint32
|
||||||
|
FreeBuffers uint32
|
||||||
|
EventsLost uint32
|
||||||
|
BuffersWritten uint32
|
||||||
|
LogBuffersLost uint32
|
||||||
|
RealTimeBuffersLost uint32
|
||||||
|
LoggerThreadId HANDLE
|
||||||
|
LogFileNameOffset uint32
|
||||||
|
LoggerNameOffset uint32
|
||||||
|
}
|
||||||
304
vendor/github.com/apenwarr/w32/alpc.go
generated
vendored
Normal file
304
vendor/github.com/apenwarr/w32/alpc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,304 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
// "github.com/davecgh/go-spew/spew"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modntdll = syscall.NewLazyDLL("ntdll.dll")
|
||||||
|
|
||||||
|
procAlpcGetMessageAttribute = modntdll.NewProc("AlpcGetMessageAttribute")
|
||||||
|
procNtAlpcAcceptConnectPort = modntdll.NewProc("NtAlpcAcceptConnectPort")
|
||||||
|
procNtAlpcCancelMessage = modntdll.NewProc("NtAlpcCancelMessage")
|
||||||
|
procNtAlpcConnectPort = modntdll.NewProc("NtAlpcConnectPort")
|
||||||
|
procNtAlpcCreatePort = modntdll.NewProc("NtAlpcCreatePort")
|
||||||
|
procNtAlpcDisconnectPort = modntdll.NewProc("NtAlpcDisconnectPort")
|
||||||
|
procNtAlpcSendWaitReceivePort = modntdll.NewProc("NtAlpcSendWaitReceivePort")
|
||||||
|
procRtlCreateUnicodeStringFromAsciiz = modntdll.NewProc("RtlCreateUnicodeStringFromAsciiz")
|
||||||
|
)
|
||||||
|
|
||||||
|
//func RtlCreateUnicodeStringFromAsciiz(s string) (us UNICODE_STRING, e error) {
|
||||||
|
//
|
||||||
|
// cs := C.CString(s)
|
||||||
|
// defer C.free(unsafe.Pointer(cs))
|
||||||
|
//
|
||||||
|
// ret, _, lastErr := procRtlCreateUnicodeStringFromAsciiz.Call(
|
||||||
|
// uintptr(unsafe.Pointer(&us)),
|
||||||
|
// uintptr(unsafe.Pointer(cs)),
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// if ret != 1 { // ret is a BOOL ( I think )
|
||||||
|
// e = lastErr
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
|
||||||
|
//func newUnicodeString(s string) (us UNICODE_STRING, e error) {
|
||||||
|
// // TODO probably not the most efficient way to do this, but I couldn't
|
||||||
|
// // work out how to manually initialize the UNICODE_STRING struct in a way
|
||||||
|
// // that the ALPC subsystem liked.
|
||||||
|
// us, e = RtlCreateUnicodeStringFromAsciiz(s)
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
|
||||||
|
// (this is a macro)
|
||||||
|
// VOID InitializeObjectAttributes(
|
||||||
|
// [out] POBJECT_ATTRIBUTES InitializedAttributes,
|
||||||
|
// [in] PUNICODE_STRING ObjectName,
|
||||||
|
// [in] ULONG Attributes,
|
||||||
|
// [in] HANDLE RootDirectory,
|
||||||
|
// [in, optional] PSECURITY_DESCRIPTOR SecurityDescriptor
|
||||||
|
// )
|
||||||
|
//func InitializeObjectAttributes(
|
||||||
|
// name string,
|
||||||
|
// attributes uint32,
|
||||||
|
// rootDir HANDLE,
|
||||||
|
// pSecurityDescriptor *SECURITY_DESCRIPTOR,
|
||||||
|
//) (oa OBJECT_ATTRIBUTES, e error) {
|
||||||
|
//
|
||||||
|
// oa = OBJECT_ATTRIBUTES{
|
||||||
|
// RootDirectory: rootDir,
|
||||||
|
// Attributes: attributes,
|
||||||
|
// SecurityDescriptor: pSecurityDescriptor,
|
||||||
|
// }
|
||||||
|
// oa.Length = uint32(unsafe.Sizeof(oa))
|
||||||
|
//
|
||||||
|
// if len(name) > 0 {
|
||||||
|
// us, err := newUnicodeString(name)
|
||||||
|
// if err != nil {
|
||||||
|
// e = err
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// oa.ObjectName = &us
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
|
||||||
|
// NTSTATUS
|
||||||
|
// NtAlpcCreatePort(
|
||||||
|
// __out PHANDLE PortHandle,
|
||||||
|
// __in POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
|
// __in_opt PALPC_PORT_ATTRIBUTES PortAttributes
|
||||||
|
// );
|
||||||
|
func NtAlpcCreatePort(pObjectAttributes *OBJECT_ATTRIBUTES, pPortAttributes *ALPC_PORT_ATTRIBUTES) (hPort HANDLE, e error) {
|
||||||
|
|
||||||
|
ret, _, _ := procNtAlpcCreatePort.Call(
|
||||||
|
uintptr(unsafe.Pointer(&hPort)),
|
||||||
|
uintptr(unsafe.Pointer(pObjectAttributes)),
|
||||||
|
uintptr(unsafe.Pointer(pPortAttributes)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
return hPort, fmt.Errorf("0x%x", ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NTSTATUS
|
||||||
|
// NtAlpcConnectPort(
|
||||||
|
// __out PHANDLE PortHandle,
|
||||||
|
// __in PUNICODE_STRING PortName,
|
||||||
|
// __in POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
|
// __in_opt PALPC_PORT_ATTRIBUTES PortAttributes,
|
||||||
|
// __in ULONG Flags,
|
||||||
|
// __in_opt PSID RequiredServerSid,
|
||||||
|
// __inout PPORT_MESSAGE ConnectionMessage,
|
||||||
|
// __inout_opt PULONG BufferLength,
|
||||||
|
// __inout_opt PALPC_MESSAGE_ATTRIBUTES OutMessageAttributes,
|
||||||
|
// __inout_opt PALPC_MESSAGE_ATTRIBUTES InMessageAttributes,
|
||||||
|
// __in_opt PLARGE_INTEGER Timeout
|
||||||
|
// );
|
||||||
|
//func NtAlpcConnectPort(
|
||||||
|
// destPort string,
|
||||||
|
// pClientObjAttrs *OBJECT_ATTRIBUTES,
|
||||||
|
// pClientAlpcPortAttrs *ALPC_PORT_ATTRIBUTES,
|
||||||
|
// flags uint32,
|
||||||
|
// pRequiredServerSid *SID,
|
||||||
|
// pConnMsg *AlpcShortMessage,
|
||||||
|
// pBufLen *uint32,
|
||||||
|
// pOutMsgAttrs *ALPC_MESSAGE_ATTRIBUTES,
|
||||||
|
// pInMsgAttrs *ALPC_MESSAGE_ATTRIBUTES,
|
||||||
|
// timeout *int64,
|
||||||
|
//) (hPort HANDLE, e error) {
|
||||||
|
//
|
||||||
|
// destPortU, e := newUnicodeString(destPort)
|
||||||
|
// if e != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ret, _, _ := procNtAlpcConnectPort.Call(
|
||||||
|
// uintptr(unsafe.Pointer(&hPort)),
|
||||||
|
// uintptr(unsafe.Pointer(&destPortU)),
|
||||||
|
// uintptr(unsafe.Pointer(pClientObjAttrs)),
|
||||||
|
// uintptr(unsafe.Pointer(pClientAlpcPortAttrs)),
|
||||||
|
// uintptr(flags),
|
||||||
|
// uintptr(unsafe.Pointer(pRequiredServerSid)),
|
||||||
|
// uintptr(unsafe.Pointer(pConnMsg)),
|
||||||
|
// uintptr(unsafe.Pointer(pBufLen)),
|
||||||
|
// uintptr(unsafe.Pointer(pOutMsgAttrs)),
|
||||||
|
// uintptr(unsafe.Pointer(pInMsgAttrs)),
|
||||||
|
// uintptr(unsafe.Pointer(timeout)),
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// if ret != ERROR_SUCCESS {
|
||||||
|
// e = fmt.Errorf("0x%x", ret)
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
|
||||||
|
// NTSTATUS
|
||||||
|
// NtAlpcAcceptConnectPort(
|
||||||
|
// __out PHANDLE PortHandle,
|
||||||
|
// __in HANDLE ConnectionPortHandle,
|
||||||
|
// __in ULONG Flags,
|
||||||
|
// __in POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
|
// __in PALPC_PORT_ATTRIBUTES PortAttributes,
|
||||||
|
// __in_opt PVOID PortContext,
|
||||||
|
// __in PPORT_MESSAGE ConnectionRequest,
|
||||||
|
// __inout_opt PALPC_MESSAGE_ATTRIBUTES ConnectionMessageAttributes,
|
||||||
|
// __in BOOLEAN AcceptConnection
|
||||||
|
// );
|
||||||
|
func NtAlpcAcceptConnectPort(
|
||||||
|
hSrvConnPort HANDLE,
|
||||||
|
flags uint32,
|
||||||
|
pObjAttr *OBJECT_ATTRIBUTES,
|
||||||
|
pPortAttr *ALPC_PORT_ATTRIBUTES,
|
||||||
|
pContext *AlpcPortContext,
|
||||||
|
pConnReq *AlpcShortMessage,
|
||||||
|
pConnMsgAttrs *ALPC_MESSAGE_ATTRIBUTES,
|
||||||
|
accept uintptr,
|
||||||
|
) (hPort HANDLE, e error) {
|
||||||
|
|
||||||
|
ret, _, _ := procNtAlpcAcceptConnectPort.Call(
|
||||||
|
uintptr(unsafe.Pointer(&hPort)),
|
||||||
|
uintptr(hSrvConnPort),
|
||||||
|
uintptr(flags),
|
||||||
|
uintptr(unsafe.Pointer(pObjAttr)),
|
||||||
|
uintptr(unsafe.Pointer(pPortAttr)),
|
||||||
|
uintptr(unsafe.Pointer(pContext)),
|
||||||
|
uintptr(unsafe.Pointer(pConnReq)),
|
||||||
|
uintptr(unsafe.Pointer(pConnMsgAttrs)),
|
||||||
|
accept,
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
e = fmt.Errorf("0x%x", ret)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NTSTATUS
|
||||||
|
// NtAlpcSendWaitReceivePort(
|
||||||
|
// __in HANDLE PortHandle,
|
||||||
|
// __in ULONG Flags,
|
||||||
|
// __in_opt PPORT_MESSAGE SendMessage,
|
||||||
|
// __in_opt PALPC_MESSAGE_ATTRIBUTES SendMessageAttributes,
|
||||||
|
// __inout_opt PPORT_MESSAGE ReceiveMessage,
|
||||||
|
// __inout_opt PULONG BufferLength,
|
||||||
|
// __inout_opt PALPC_MESSAGE_ATTRIBUTES ReceiveMessageAttributes,
|
||||||
|
// __in_opt PLARGE_INTEGER Timeout
|
||||||
|
// );
|
||||||
|
func NtAlpcSendWaitReceivePort(
|
||||||
|
hPort HANDLE,
|
||||||
|
flags uint32,
|
||||||
|
sendMsg *AlpcShortMessage, // Should actually point to PORT_MESSAGE + payload
|
||||||
|
sendMsgAttrs *ALPC_MESSAGE_ATTRIBUTES,
|
||||||
|
recvMsg *AlpcShortMessage,
|
||||||
|
recvBufLen *uint32,
|
||||||
|
recvMsgAttrs *ALPC_MESSAGE_ATTRIBUTES,
|
||||||
|
timeout *int64, // use native int64
|
||||||
|
) (e error) {
|
||||||
|
|
||||||
|
ret, _, _ := procNtAlpcSendWaitReceivePort.Call(
|
||||||
|
uintptr(hPort),
|
||||||
|
uintptr(flags),
|
||||||
|
uintptr(unsafe.Pointer(sendMsg)),
|
||||||
|
uintptr(unsafe.Pointer(sendMsgAttrs)),
|
||||||
|
uintptr(unsafe.Pointer(recvMsg)),
|
||||||
|
uintptr(unsafe.Pointer(recvBufLen)),
|
||||||
|
uintptr(unsafe.Pointer(recvMsgAttrs)),
|
||||||
|
uintptr(unsafe.Pointer(timeout)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
e = fmt.Errorf("0x%x", ret)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NTSYSAPI
|
||||||
|
// PVOID
|
||||||
|
// NTAPI
|
||||||
|
// AlpcGetMessageAttribute(
|
||||||
|
// __in PALPC_MESSAGE_ATTRIBUTES Buffer,
|
||||||
|
// __in ULONG AttributeFlag
|
||||||
|
// );
|
||||||
|
|
||||||
|
// This basically returns a pointer to the correct struct for whichever
|
||||||
|
// message attribute you asked for. In Go terms, it returns unsafe.Pointer
|
||||||
|
// which you should then cast. Example:
|
||||||
|
|
||||||
|
// ptr := AlpcGetMessageAttribute(&recvMsgAttrs, ALPC_MESSAGE_CONTEXT_ATTRIBUTE)
|
||||||
|
// if ptr != nil {
|
||||||
|
// context := (*ALPC_CONTEXT_ATTR)(ptr)
|
||||||
|
// }
|
||||||
|
func AlpcGetMessageAttribute(buf *ALPC_MESSAGE_ATTRIBUTES, attr uint32) unsafe.Pointer {
|
||||||
|
|
||||||
|
ret, _, _ := procAlpcGetMessageAttribute.Call(
|
||||||
|
uintptr(unsafe.Pointer(buf)),
|
||||||
|
uintptr(attr),
|
||||||
|
)
|
||||||
|
return unsafe.Pointer(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NTSYSCALLAPI
|
||||||
|
// NTSTATUS
|
||||||
|
// NTAPI
|
||||||
|
// NtAlpcCancelMessage(
|
||||||
|
// __in HANDLE PortHandle,
|
||||||
|
// __in ULONG Flags,
|
||||||
|
// __in PALPC_CONTEXT_ATTR MessageContext
|
||||||
|
// );
|
||||||
|
func NtAlpcCancelMessage(hPort HANDLE, flags uint32, pMsgContext *ALPC_CONTEXT_ATTR) (e error) {
|
||||||
|
|
||||||
|
ret, _, _ := procNtAlpcCancelMessage.Call(
|
||||||
|
uintptr(hPort),
|
||||||
|
uintptr(flags),
|
||||||
|
uintptr(unsafe.Pointer(pMsgContext)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
e = fmt.Errorf("0x%x", ret)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NTSYSCALLAPI
|
||||||
|
// NTSTATUS
|
||||||
|
// NTAPI
|
||||||
|
// NtAlpcDisconnectPort(
|
||||||
|
// __in HANDLE PortHandle,
|
||||||
|
// __in ULONG Flags
|
||||||
|
// );
|
||||||
|
func NtAlpcDisconnectPort(hPort HANDLE, flags uint32) (e error) {
|
||||||
|
|
||||||
|
ret, _, _ := procNtAlpcDisconnectPort.Call(
|
||||||
|
uintptr(hPort),
|
||||||
|
uintptr(flags),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
e = fmt.Errorf("0x%x", ret)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
64
vendor/github.com/apenwarr/w32/alpc_constants.go
generated
vendored
Normal file
64
vendor/github.com/apenwarr/w32/alpc_constants.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
package w32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ALPC_PORFLG_ALLOW_LPC_REQUESTS = 0x20000
|
||||||
|
ALPC_PORFLG_SYSTEM_PROCESS = 0x100000
|
||||||
|
ALPC_PORFLG_WAITABLE_PORT = 0x40000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ALPC_MSGFLG_REPLY_MESSAGE = 0x1
|
||||||
|
ALPC_MSGFLG_LPC_MODE = 0x2 // ?
|
||||||
|
ALPC_MSGFLG_RELEASE_MESSAGE = 0x10000 // dbg
|
||||||
|
ALPC_MSGFLG_SYNC_REQUEST = 0x20000 // dbg
|
||||||
|
ALPC_MSGFLG_WAIT_USER_MODE = 0x100000
|
||||||
|
ALPC_MSGFLG_WAIT_ALERTABLE = 0x200000
|
||||||
|
ALPC_MSGFLG_WOW64_CALL = 0x80000000 // dbg
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
ALPC_MESSAGE_SECURITY_ATTRIBUTE = 0x80000000
|
||||||
|
ALPC_MESSAGE_VIEW_ATTRIBUTE = 0x40000000
|
||||||
|
ALPC_MESSAGE_CONTEXT_ATTRIBUTE = 0x20000000
|
||||||
|
ALPC_MESSAGE_HANDLE_ATTRIBUTE = 0x10000000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
OBJ_INHERIT = 0x00000002
|
||||||
|
OBJ_PERMANENT = 0x00000010
|
||||||
|
OBJ_EXCLUSIVE = 0x00000020
|
||||||
|
OBJ_CASE_INSENSITIVE = 0x00000040
|
||||||
|
OBJ_OPENIF = 0x00000080
|
||||||
|
OBJ_OPENLINK = 0x00000100
|
||||||
|
OBJ_KERNEL_HANDLE = 0x00000200
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LPC_REQUEST = 1
|
||||||
|
LPC_REPLY = 2
|
||||||
|
LPC_DATAGRAM = 3
|
||||||
|
LPC_LOST_REPLY = 4
|
||||||
|
LPC_PORT_CLOSED = 5
|
||||||
|
LPC_CLIENT_DIED = 6
|
||||||
|
LPC_EXCEPTION = 7
|
||||||
|
LPC_DEBUG_EVENT = 8
|
||||||
|
LPC_ERROR_EVENT = 9
|
||||||
|
LPC_CONNECTION_REQUEST = 10
|
||||||
|
LPC_CONTINUATION_REQUIRED = 0x2000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SecurityAnonymous uint32 = 1
|
||||||
|
SecurityIdentification uint32 = 2
|
||||||
|
SecurityImpersonation uint32 = 3
|
||||||
|
SecurityDelegation uint32 = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SECURITY_DYNAMIC_TRACKING byte = 1
|
||||||
|
SECURITY_STATIC_TRACKING byte = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ALPC_SYNC_OBJECT_TYPE uint32 = 2
|
||||||
|
ALPC_THREAD_OBJECT_TYPE uint32 = 4
|
||||||
|
)
|
||||||
181
vendor/github.com/apenwarr/w32/alpc_typedef.go
generated
vendored
Normal file
181
vendor/github.com/apenwarr/w32/alpc_typedef.go
generated
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
package w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// nt!_ALPC_MESSAGE_ATTRIBUTES
|
||||||
|
// +0x000 AllocatedAttributes : Uint4B
|
||||||
|
// +0x004 ValidAttributes : Uint4B
|
||||||
|
type ALPC_MESSAGE_ATTRIBUTES struct {
|
||||||
|
AllocatedAttributes uint32
|
||||||
|
ValidAttributes uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ALPC_CONTEXT_ATTR struct {
|
||||||
|
PortContext *AlpcPortContext
|
||||||
|
MessageContext uintptr
|
||||||
|
Sequence uint32
|
||||||
|
MessageId uint32
|
||||||
|
CallbackId uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ALPC_HANDLE_ATTR struct {
|
||||||
|
Flags uint32
|
||||||
|
Handle HANDLE
|
||||||
|
ObjectType uint32
|
||||||
|
DesiredAccess uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// nt!_CLIENT_ID
|
||||||
|
// +0x000 UniqueProcess : Ptr64 Void
|
||||||
|
// +0x008 UniqueThread : Ptr64 Void
|
||||||
|
type CLIENT_ID struct {
|
||||||
|
UniqueProcess uintptr
|
||||||
|
UniqueThread uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// nt!_UNICODE_STRING
|
||||||
|
// +0x000 Length : Uint2B
|
||||||
|
// +0x002 MaximumLength : Uint2B
|
||||||
|
// +0x008 Buffer : Ptr64 Uint2B
|
||||||
|
type UNICODE_STRING struct {
|
||||||
|
Length uint16
|
||||||
|
MaximumLength uint16
|
||||||
|
_ [4]byte // align to 0x08
|
||||||
|
Buffer *uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// nt!_OBJECT_ATTRIBUTES
|
||||||
|
// +0x000 Length : Uint4B
|
||||||
|
// +0x008 RootDirectory : Ptr64 Void
|
||||||
|
// +0x010 ObjectName : Ptr64 _UNICODE_STRING
|
||||||
|
// +0x018 Attributes : Uint4B
|
||||||
|
// +0x020 SecurityDescriptor : Ptr64 Void
|
||||||
|
// +0x028 SecurityQualityOfService : Ptr64 Void
|
||||||
|
type OBJECT_ATTRIBUTES struct {
|
||||||
|
Length uint32
|
||||||
|
_ [4]byte // align to 0x08
|
||||||
|
RootDirectory HANDLE
|
||||||
|
ObjectName *UNICODE_STRING
|
||||||
|
Attributes uint32
|
||||||
|
_ [4]byte // align to 0x20
|
||||||
|
SecurityDescriptor *SECURITY_DESCRIPTOR
|
||||||
|
SecurityQualityOfService *SECURITY_QUALITY_OF_SERVICE
|
||||||
|
}
|
||||||
|
|
||||||
|
// cf: http://j00ru.vexillium.org/?p=502 for legacy RPC
|
||||||
|
// nt!_PORT_MESSAGE
|
||||||
|
// +0x000 u1 : <unnamed-tag>
|
||||||
|
// +0x004 u2 : <unnamed-tag>
|
||||||
|
// +0x008 ClientId : _CLIENT_ID
|
||||||
|
// +0x008 DoNotUseThisField : Float
|
||||||
|
// +0x018 MessageId : Uint4B
|
||||||
|
// +0x020 ClientViewSize : Uint8B
|
||||||
|
// +0x020 CallbackId : Uint4B
|
||||||
|
type PORT_MESSAGE struct {
|
||||||
|
DataLength uint16 // These are the two unnamed unions
|
||||||
|
TotalLength uint16 // without Length and ZeroInit
|
||||||
|
Type uint16
|
||||||
|
DataInfoOffset uint16
|
||||||
|
ClientId CLIENT_ID
|
||||||
|
MessageId uint32
|
||||||
|
_ [4]byte // align up to 0x20
|
||||||
|
ClientViewSize uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm PORT_MESSAGE) CallbackId() uint32 {
|
||||||
|
return uint32(pm.ClientViewSize >> 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm PORT_MESSAGE) DoNotUseThisField() float64 {
|
||||||
|
panic("WE TOLD YOU NOT TO USE THIS FIELD")
|
||||||
|
}
|
||||||
|
|
||||||
|
const PORT_MESSAGE_SIZE = 0x28
|
||||||
|
|
||||||
|
// http://www.nirsoft.net/kernel_struct/vista/SECURITY_QUALITY_OF_SERVICE.html
|
||||||
|
type SECURITY_QUALITY_OF_SERVICE struct {
|
||||||
|
Length uint32
|
||||||
|
ImpersonationLevel uint32
|
||||||
|
ContextTrackingMode byte
|
||||||
|
EffectiveOnly byte
|
||||||
|
_ [2]byte // align to 12 bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
const SECURITY_QOS_SIZE = 12
|
||||||
|
|
||||||
|
// nt!_ALPC_PORT_ATTRIBUTES
|
||||||
|
// +0x000 Flags : Uint4B
|
||||||
|
// +0x004 SecurityQos : _SECURITY_QUALITY_OF_SERVICE
|
||||||
|
// +0x010 MaxMessageLength : Uint8B
|
||||||
|
// +0x018 MemoryBandwidth : Uint8B
|
||||||
|
// +0x020 MaxPoolUsage : Uint8B
|
||||||
|
// +0x028 MaxSectionSize : Uint8B
|
||||||
|
// +0x030 MaxViewSize : Uint8B
|
||||||
|
// +0x038 MaxTotalSectionSize : Uint8B
|
||||||
|
// +0x040 DupObjectTypes : Uint4B
|
||||||
|
// +0x044 Reserved : Uint4B
|
||||||
|
type ALPC_PORT_ATTRIBUTES struct {
|
||||||
|
Flags uint32
|
||||||
|
SecurityQos SECURITY_QUALITY_OF_SERVICE
|
||||||
|
MaxMessageLength uint64 // must be filled out
|
||||||
|
MemoryBandwidth uint64
|
||||||
|
MaxPoolUsage uint64
|
||||||
|
MaxSectionSize uint64
|
||||||
|
MaxViewSize uint64
|
||||||
|
MaxTotalSectionSize uint64
|
||||||
|
DupObjectTypes uint32
|
||||||
|
Reserved uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHORT_MESSAGE_MAX_SIZE uint16 = 65535 // MAX_USHORT
|
||||||
|
const SHORT_MESSAGE_MAX_PAYLOAD uint16 = SHORT_MESSAGE_MAX_SIZE - PORT_MESSAGE_SIZE
|
||||||
|
|
||||||
|
// LPC uses the first 4 bytes of the payload as an LPC Command, but this is
|
||||||
|
// NOT represented here, to allow the use of raw ALPC. For legacy LPC, callers
|
||||||
|
// must include the command as part of their payload.
|
||||||
|
type AlpcShortMessage struct {
|
||||||
|
PORT_MESSAGE
|
||||||
|
Data [SHORT_MESSAGE_MAX_PAYLOAD]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAlpcShortMessage() AlpcShortMessage {
|
||||||
|
sm := AlpcShortMessage{}
|
||||||
|
sm.TotalLength = SHORT_MESSAGE_MAX_SIZE
|
||||||
|
return sm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *AlpcShortMessage) SetData(d []byte) (e error) {
|
||||||
|
|
||||||
|
copy(sm.Data[:], d)
|
||||||
|
if len(d) > int(SHORT_MESSAGE_MAX_PAYLOAD) {
|
||||||
|
e = errors.New("data too big - truncated")
|
||||||
|
sm.DataLength = SHORT_MESSAGE_MAX_PAYLOAD
|
||||||
|
sm.TotalLength = SHORT_MESSAGE_MAX_SIZE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sm.TotalLength = uint16(PORT_MESSAGE_SIZE + len(d))
|
||||||
|
sm.DataLength = uint16(len(d))
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO - is this still useful?
|
||||||
|
func (sm *AlpcShortMessage) GetData() []byte {
|
||||||
|
if int(sm.DataLength) > int(SHORT_MESSAGE_MAX_PAYLOAD) {
|
||||||
|
return sm.Data[:] // truncate
|
||||||
|
}
|
||||||
|
return sm.Data[:sm.DataLength]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *AlpcShortMessage) Reset() {
|
||||||
|
// zero the PORT_MESSAGE header
|
||||||
|
sm.PORT_MESSAGE = PORT_MESSAGE{}
|
||||||
|
sm.TotalLength = SHORT_MESSAGE_MAX_SIZE
|
||||||
|
sm.DataLength = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type AlpcPortContext struct {
|
||||||
|
Handle HANDLE
|
||||||
|
}
|
||||||
109
vendor/github.com/apenwarr/w32/comctl32.go
generated
vendored
Normal file
109
vendor/github.com/apenwarr/w32/comctl32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modcomctl32 = syscall.NewLazyDLL("comctl32.dll")
|
||||||
|
|
||||||
|
procInitCommonControlsEx = modcomctl32.NewProc("InitCommonControlsEx")
|
||||||
|
procImageList_Create = modcomctl32.NewProc("ImageList_Create")
|
||||||
|
procImageList_Destroy = modcomctl32.NewProc("ImageList_Destroy")
|
||||||
|
procImageList_GetImageCount = modcomctl32.NewProc("ImageList_GetImageCount")
|
||||||
|
procImageList_SetImageCount = modcomctl32.NewProc("ImageList_SetImageCount")
|
||||||
|
procImageList_Add = modcomctl32.NewProc("ImageList_Add")
|
||||||
|
procImageList_ReplaceIcon = modcomctl32.NewProc("ImageList_ReplaceIcon")
|
||||||
|
procImageList_Remove = modcomctl32.NewProc("ImageList_Remove")
|
||||||
|
procTrackMouseEvent = modcomctl32.NewProc("_TrackMouseEvent")
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitCommonControlsEx(lpInitCtrls *INITCOMMONCONTROLSEX) bool {
|
||||||
|
ret, _, _ := procInitCommonControlsEx.Call(
|
||||||
|
uintptr(unsafe.Pointer(lpInitCtrls)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageList_Create(cx, cy int, flags uint, cInitial, cGrow int) HIMAGELIST {
|
||||||
|
ret, _, _ := procImageList_Create.Call(
|
||||||
|
uintptr(cx),
|
||||||
|
uintptr(cy),
|
||||||
|
uintptr(flags),
|
||||||
|
uintptr(cInitial),
|
||||||
|
uintptr(cGrow))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("Create image list failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return HIMAGELIST(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageList_Destroy(himl HIMAGELIST) bool {
|
||||||
|
ret, _, _ := procImageList_Destroy.Call(
|
||||||
|
uintptr(himl))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageList_GetImageCount(himl HIMAGELIST) int {
|
||||||
|
ret, _, _ := procImageList_GetImageCount.Call(
|
||||||
|
uintptr(himl))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageList_SetImageCount(himl HIMAGELIST, uNewCount uint) bool {
|
||||||
|
ret, _, _ := procImageList_SetImageCount.Call(
|
||||||
|
uintptr(himl),
|
||||||
|
uintptr(uNewCount))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageList_Add(himl HIMAGELIST, hbmImage, hbmMask HBITMAP) int {
|
||||||
|
ret, _, _ := procImageList_Add.Call(
|
||||||
|
uintptr(himl),
|
||||||
|
uintptr(hbmImage),
|
||||||
|
uintptr(hbmMask))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageList_ReplaceIcon(himl HIMAGELIST, i int, hicon HICON) int {
|
||||||
|
ret, _, _ := procImageList_ReplaceIcon.Call(
|
||||||
|
uintptr(himl),
|
||||||
|
uintptr(i),
|
||||||
|
uintptr(hicon))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageList_AddIcon(himl HIMAGELIST, hicon HICON) int {
|
||||||
|
return ImageList_ReplaceIcon(himl, -1, hicon)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageList_Remove(himl HIMAGELIST, i int) bool {
|
||||||
|
ret, _, _ := procImageList_Remove.Call(
|
||||||
|
uintptr(himl),
|
||||||
|
uintptr(i))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageList_RemoveAll(himl HIMAGELIST) bool {
|
||||||
|
return ImageList_Remove(himl, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TrackMouseEvent(tme *TRACKMOUSEEVENT) bool {
|
||||||
|
ret, _, _ := procTrackMouseEvent.Call(
|
||||||
|
uintptr(unsafe.Pointer(tme)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
38
vendor/github.com/apenwarr/w32/comdlg32.go
generated
vendored
Normal file
38
vendor/github.com/apenwarr/w32/comdlg32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modcomdlg32 = syscall.NewLazyDLL("comdlg32.dll")
|
||||||
|
|
||||||
|
procGetSaveFileName = modcomdlg32.NewProc("GetSaveFileNameW")
|
||||||
|
procGetOpenFileName = modcomdlg32.NewProc("GetOpenFileNameW")
|
||||||
|
procCommDlgExtendedError = modcomdlg32.NewProc("CommDlgExtendedError")
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetOpenFileName(ofn *OPENFILENAME) bool {
|
||||||
|
ret, _, _ := procGetOpenFileName.Call(
|
||||||
|
uintptr(unsafe.Pointer(ofn)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSaveFileName(ofn *OPENFILENAME) bool {
|
||||||
|
ret, _, _ := procGetSaveFileName.Call(
|
||||||
|
uintptr(unsafe.Pointer(ofn)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func CommDlgExtendedError() uint {
|
||||||
|
ret, _, _ := procCommDlgExtendedError.Call()
|
||||||
|
|
||||||
|
return uint(ret)
|
||||||
|
}
|
||||||
2628
vendor/github.com/apenwarr/w32/constants.go
generated
vendored
Normal file
2628
vendor/github.com/apenwarr/w32/constants.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
152
vendor/github.com/apenwarr/w32/create_process.go
generated
vendored
Normal file
152
vendor/github.com/apenwarr/w32/create_process.go
generated
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||||
|
|
||||||
|
procCreateProcessW = kernel32.NewProc("CreateProcessW")
|
||||||
|
procTerminateProcess = kernel32.NewProc("TerminateProcess")
|
||||||
|
procGetExitCodeProcess = kernel32.NewProc("GetExitCodeProcess")
|
||||||
|
procWaitForSingleObject = kernel32.NewProc("WaitForSingleObject")
|
||||||
|
)
|
||||||
|
|
||||||
|
// WINBASEAPI WINBOOL WINAPI
|
||||||
|
// CreateProcessW (
|
||||||
|
// LPCWSTR lpApplicationName,
|
||||||
|
// LPWSTR lpCommandLine,
|
||||||
|
// LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
|
// LPSECURITY_ATTRIBUTES lpThreadAttributes
|
||||||
|
// WINBOOL bInheritHandles
|
||||||
|
// DWORD dwCreationFlags
|
||||||
|
// LPVOID lpEnvironment
|
||||||
|
// LPCWSTR lpCurrentDirectory
|
||||||
|
// LPSTARTUPINFOW lpStartupInfo
|
||||||
|
// LPPROCESS_INFORMATION lpProcessInformation
|
||||||
|
//);
|
||||||
|
func CreateProcessW(
|
||||||
|
lpApplicationName, lpCommandLine string,
|
||||||
|
lpProcessAttributes, lpThreadAttributes *SECURITY_ATTRIBUTES,
|
||||||
|
bInheritHandles BOOL,
|
||||||
|
dwCreationFlags uint32,
|
||||||
|
lpEnvironment unsafe.Pointer,
|
||||||
|
lpCurrentDirectory string,
|
||||||
|
lpStartupInfo *STARTUPINFOW,
|
||||||
|
lpProcessInformation *PROCESS_INFORMATION,
|
||||||
|
) (e error) {
|
||||||
|
|
||||||
|
var lpAN, lpCL, lpCD *uint16
|
||||||
|
if len(lpApplicationName) > 0 {
|
||||||
|
lpAN, e = syscall.UTF16PtrFromString(lpApplicationName)
|
||||||
|
if e != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(lpCommandLine) > 0 {
|
||||||
|
lpCL, e = syscall.UTF16PtrFromString(lpCommandLine)
|
||||||
|
if e != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(lpCurrentDirectory) > 0 {
|
||||||
|
lpCD, e = syscall.UTF16PtrFromString(lpCurrentDirectory)
|
||||||
|
if e != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, lastErr := procCreateProcessW.Call(
|
||||||
|
uintptr(unsafe.Pointer(lpAN)),
|
||||||
|
uintptr(unsafe.Pointer(lpCL)),
|
||||||
|
uintptr(unsafe.Pointer(lpProcessAttributes)),
|
||||||
|
uintptr(unsafe.Pointer(lpProcessInformation)),
|
||||||
|
uintptr(bInheritHandles),
|
||||||
|
uintptr(dwCreationFlags),
|
||||||
|
uintptr(lpEnvironment),
|
||||||
|
uintptr(unsafe.Pointer(lpCD)),
|
||||||
|
uintptr(unsafe.Pointer(lpStartupInfo)),
|
||||||
|
uintptr(unsafe.Pointer(lpProcessInformation)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
e = lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateProcessQuick(cmd string) (pi PROCESS_INFORMATION, e error) {
|
||||||
|
si := &STARTUPINFOW{}
|
||||||
|
e = CreateProcessW(
|
||||||
|
"",
|
||||||
|
cmd,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
unsafe.Pointer(nil),
|
||||||
|
"",
|
||||||
|
si,
|
||||||
|
&pi,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TerminateProcess(hProcess HANDLE, exitCode uint32) (e error) {
|
||||||
|
ret, _, lastErr := procTerminateProcess.Call(
|
||||||
|
uintptr(hProcess),
|
||||||
|
uintptr(exitCode),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
e = lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetExitCodeProcess(hProcess HANDLE) (code uintptr, e error) {
|
||||||
|
ret, _, lastErr := procGetExitCodeProcess.Call(
|
||||||
|
uintptr(hProcess),
|
||||||
|
uintptr(unsafe.Pointer(&code)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
e = lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DWORD WINAPI WaitForSingleObject(
|
||||||
|
// _In_ HANDLE hHandle,
|
||||||
|
// _In_ DWORD dwMilliseconds
|
||||||
|
// );
|
||||||
|
|
||||||
|
func WaitForSingleObject(hHandle HANDLE, msecs uint32) (ok bool, e error) {
|
||||||
|
|
||||||
|
ret, _, lastErr := procWaitForSingleObject.Call(
|
||||||
|
uintptr(hHandle),
|
||||||
|
uintptr(msecs),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret == WAIT_OBJECT_0 {
|
||||||
|
ok = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't set e for timeouts, or it will be ERROR_SUCCESS which is
|
||||||
|
// confusing
|
||||||
|
if ret != WAIT_TIMEOUT {
|
||||||
|
e = lastErr
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
9
vendor/github.com/apenwarr/w32/create_process_constants.go
generated
vendored
Normal file
9
vendor/github.com/apenwarr/w32/create_process_constants.go
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
package w32
|
||||||
|
|
||||||
|
const (
|
||||||
|
WAIT_ABANDONED = 0x00000080
|
||||||
|
WAIT_OBJECT_0 = 0x00000000
|
||||||
|
WAIT_TIMEOUT = 0x00000102
|
||||||
|
WAIT_FAILED = 0xFFFFFFFF
|
||||||
|
INFINITE = 0xFFFFFFFF
|
||||||
|
)
|
||||||
68
vendor/github.com/apenwarr/w32/create_process_typedef.go
generated
vendored
Normal file
68
vendor/github.com/apenwarr/w32/create_process_typedef.go
generated
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
package w32
|
||||||
|
|
||||||
|
// typedef struct _PROCESS_INFORMATION {
|
||||||
|
// HANDLE hProcess;
|
||||||
|
// HANDLE hThread;
|
||||||
|
// DWORD dwProcessId;
|
||||||
|
// DWORD dwThreadId;
|
||||||
|
// } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
|
||||||
|
|
||||||
|
type PROCESS_INFORMATION struct {
|
||||||
|
Process HANDLE
|
||||||
|
Thread HANDLE
|
||||||
|
ProcessId uint32
|
||||||
|
ThreadId uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// typedef struct _STARTUPINFOW {
|
||||||
|
// DWORD cb;
|
||||||
|
// LPWSTR lpReserved;
|
||||||
|
// LPWSTR lpDesktop;
|
||||||
|
// LPWSTR lpTitle;
|
||||||
|
// DWORD dwX;
|
||||||
|
// DWORD dwY;
|
||||||
|
// DWORD dwXSize;
|
||||||
|
// DWORD dwYSize;
|
||||||
|
// DWORD dwXCountChars;
|
||||||
|
// DWORD dwYCountChars;
|
||||||
|
// DWORD dwFillAttribute;
|
||||||
|
// DWORD dwFlags;
|
||||||
|
// WORD wShowWindow;
|
||||||
|
// WORD cbReserved2;
|
||||||
|
// LPBYTE lpReserved2;
|
||||||
|
// HANDLE hStdInput;
|
||||||
|
// HANDLE hStdOutput;
|
||||||
|
// HANDLE hStdError;
|
||||||
|
// } STARTUPINFOW, *LPSTARTUPINFOW;
|
||||||
|
|
||||||
|
type STARTUPINFOW struct {
|
||||||
|
cb uint32
|
||||||
|
_ *uint16
|
||||||
|
Desktop *uint16
|
||||||
|
Title *uint16
|
||||||
|
X uint32
|
||||||
|
Y uint32
|
||||||
|
XSize uint32
|
||||||
|
YSize uint32
|
||||||
|
XCountChars uint32
|
||||||
|
YCountChars uint32
|
||||||
|
FillAttribute uint32
|
||||||
|
Flags uint32
|
||||||
|
ShowWindow uint16
|
||||||
|
_ uint16
|
||||||
|
_ *uint8
|
||||||
|
StdInput HANDLE
|
||||||
|
StdOutput HANDLE
|
||||||
|
StdError HANDLE
|
||||||
|
}
|
||||||
|
|
||||||
|
// combase!_SECURITY_ATTRIBUTES
|
||||||
|
// +0x000 nLength : Uint4B
|
||||||
|
// +0x008 lpSecurityDescriptor : Ptr64 Void
|
||||||
|
// +0x010 bInheritHandle : Int4B
|
||||||
|
|
||||||
|
type SECURITY_ATTRIBUTES struct {
|
||||||
|
Length uint32
|
||||||
|
SecurityDescriptor uintptr
|
||||||
|
InheritHandle BOOL
|
||||||
|
}
|
||||||
254
vendor/github.com/apenwarr/w32/dwmapi.go
generated
vendored
Normal file
254
vendor/github.com/apenwarr/w32/dwmapi.go
generated
vendored
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DEFINED IN THE DWM API BUT NOT IMPLEMENTED BY MS:
|
||||||
|
// DwmAttachMilContent
|
||||||
|
// DwmDetachMilContent
|
||||||
|
// DwmEnableComposition
|
||||||
|
// DwmGetGraphicsStreamClient
|
||||||
|
// DwmGetGraphicsStreamTransformHint
|
||||||
|
|
||||||
|
var (
|
||||||
|
moddwmapi = syscall.NewLazyDLL("dwmapi.dll")
|
||||||
|
|
||||||
|
procDwmDefWindowProc = moddwmapi.NewProc("DwmDefWindowProc")
|
||||||
|
procDwmEnableBlurBehindWindow = moddwmapi.NewProc("DwmEnableBlurBehindWindow")
|
||||||
|
procDwmEnableMMCSS = moddwmapi.NewProc("DwmEnableMMCSS")
|
||||||
|
procDwmExtendFrameIntoClientArea = moddwmapi.NewProc("DwmExtendFrameIntoClientArea")
|
||||||
|
procDwmFlush = moddwmapi.NewProc("DwmFlush")
|
||||||
|
procDwmGetColorizationColor = moddwmapi.NewProc("DwmGetColorizationColor")
|
||||||
|
procDwmGetCompositionTimingInfo = moddwmapi.NewProc("DwmGetCompositionTimingInfo")
|
||||||
|
procDwmGetTransportAttributes = moddwmapi.NewProc("DwmGetTransportAttributes")
|
||||||
|
procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute")
|
||||||
|
procDwmInvalidateIconicBitmaps = moddwmapi.NewProc("DwmInvalidateIconicBitmaps")
|
||||||
|
procDwmIsCompositionEnabled = moddwmapi.NewProc("DwmIsCompositionEnabled")
|
||||||
|
procDwmModifyPreviousDxFrameDuration = moddwmapi.NewProc("DwmModifyPreviousDxFrameDuration")
|
||||||
|
procDwmQueryThumbnailSourceSize = moddwmapi.NewProc("DwmQueryThumbnailSourceSize")
|
||||||
|
procDwmRegisterThumbnail = moddwmapi.NewProc("DwmRegisterThumbnail")
|
||||||
|
procDwmRenderGesture = moddwmapi.NewProc("DwmRenderGesture")
|
||||||
|
procDwmSetDxFrameDuration = moddwmapi.NewProc("DwmSetDxFrameDuration")
|
||||||
|
procDwmSetIconicLivePreviewBitmap = moddwmapi.NewProc("DwmSetIconicLivePreviewBitmap")
|
||||||
|
procDwmSetIconicThumbnail = moddwmapi.NewProc("DwmSetIconicThumbnail")
|
||||||
|
procDwmSetPresentParameters = moddwmapi.NewProc("DwmSetPresentParameters")
|
||||||
|
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
|
||||||
|
procDwmShowContact = moddwmapi.NewProc("DwmShowContact")
|
||||||
|
procDwmTetherContact = moddwmapi.NewProc("DwmTetherContact")
|
||||||
|
procDwmTransitionOwnedWindow = moddwmapi.NewProc("DwmTransitionOwnedWindow")
|
||||||
|
procDwmUnregisterThumbnail = moddwmapi.NewProc("DwmUnregisterThumbnail")
|
||||||
|
procDwmUpdateThumbnailProperties = moddwmapi.NewProc("DwmUpdateThumbnailProperties")
|
||||||
|
)
|
||||||
|
|
||||||
|
func DwmDefWindowProc(hWnd HWND, msg uint, wParam, lParam uintptr) (bool, uint) {
|
||||||
|
var result uint
|
||||||
|
ret, _, _ := procDwmDefWindowProc.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(msg),
|
||||||
|
wParam,
|
||||||
|
lParam,
|
||||||
|
uintptr(unsafe.Pointer(&result)))
|
||||||
|
return ret != 0, result
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmEnableBlurBehindWindow(hWnd HWND, pBlurBehind *DWM_BLURBEHIND) HRESULT {
|
||||||
|
ret, _, _ := procDwmEnableBlurBehindWindow.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(unsafe.Pointer(pBlurBehind)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmEnableMMCSS(fEnableMMCSS bool) HRESULT {
|
||||||
|
ret, _, _ := procDwmEnableMMCSS.Call(
|
||||||
|
uintptr(BoolToBOOL(fEnableMMCSS)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmExtendFrameIntoClientArea(hWnd HWND, pMarInset *MARGINS) HRESULT {
|
||||||
|
ret, _, _ := procDwmExtendFrameIntoClientArea.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(unsafe.Pointer(pMarInset)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmFlush() HRESULT {
|
||||||
|
ret, _, _ := procDwmFlush.Call()
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmGetColorizationColor(pcrColorization *uint32, pfOpaqueBlend *BOOL) HRESULT {
|
||||||
|
ret, _, _ := procDwmGetColorizationColor.Call(
|
||||||
|
uintptr(unsafe.Pointer(pcrColorization)),
|
||||||
|
uintptr(unsafe.Pointer(pfOpaqueBlend)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmGetCompositionTimingInfo(hWnd HWND, pTimingInfo *DWM_TIMING_INFO) HRESULT {
|
||||||
|
ret, _, _ := procDwmGetCompositionTimingInfo.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(unsafe.Pointer(pTimingInfo)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmGetTransportAttributes(pfIsRemoting *BOOL, pfIsConnected *BOOL, pDwGeneration *uint32) HRESULT {
|
||||||
|
ret, _, _ := procDwmGetTransportAttributes.Call(
|
||||||
|
uintptr(unsafe.Pointer(pfIsRemoting)),
|
||||||
|
uintptr(unsafe.Pointer(pfIsConnected)),
|
||||||
|
uintptr(unsafe.Pointer(pDwGeneration)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: verify handling of variable arguments
|
||||||
|
func DwmGetWindowAttribute(hWnd HWND, dwAttribute uint32) (pAttribute interface{}, result HRESULT) {
|
||||||
|
var pvAttribute, pvAttrSize uintptr
|
||||||
|
switch dwAttribute {
|
||||||
|
case DWMWA_NCRENDERING_ENABLED:
|
||||||
|
v := new(BOOL)
|
||||||
|
pAttribute = v
|
||||||
|
pvAttribute = uintptr(unsafe.Pointer(v))
|
||||||
|
pvAttrSize = unsafe.Sizeof(*v)
|
||||||
|
case DWMWA_CAPTION_BUTTON_BOUNDS, DWMWA_EXTENDED_FRAME_BOUNDS:
|
||||||
|
v := new(RECT)
|
||||||
|
pAttribute = v
|
||||||
|
pvAttribute = uintptr(unsafe.Pointer(v))
|
||||||
|
pvAttrSize = unsafe.Sizeof(*v)
|
||||||
|
case DWMWA_CLOAKED:
|
||||||
|
panic(fmt.Sprintf("DwmGetWindowAttribute(%d) is not currently supported.", dwAttribute))
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("DwmGetWindowAttribute(%d) is not valid.", dwAttribute))
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, _ := procDwmGetWindowAttribute.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(dwAttribute),
|
||||||
|
pvAttribute,
|
||||||
|
pvAttrSize)
|
||||||
|
result = HRESULT(ret)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmInvalidateIconicBitmaps(hWnd HWND) HRESULT {
|
||||||
|
ret, _, _ := procDwmInvalidateIconicBitmaps.Call(
|
||||||
|
uintptr(hWnd))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmIsCompositionEnabled(pfEnabled *BOOL) HRESULT {
|
||||||
|
ret, _, _ := procDwmIsCompositionEnabled.Call(
|
||||||
|
uintptr(unsafe.Pointer(pfEnabled)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmModifyPreviousDxFrameDuration(hWnd HWND, cRefreshes int, fRelative bool) HRESULT {
|
||||||
|
ret, _, _ := procDwmModifyPreviousDxFrameDuration.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(cRefreshes),
|
||||||
|
uintptr(BoolToBOOL(fRelative)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmQueryThumbnailSourceSize(hThumbnail HTHUMBNAIL, pSize *SIZE) HRESULT {
|
||||||
|
ret, _, _ := procDwmQueryThumbnailSourceSize.Call(
|
||||||
|
uintptr(hThumbnail),
|
||||||
|
uintptr(unsafe.Pointer(pSize)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmRegisterThumbnail(hWndDestination HWND, hWndSource HWND, phThumbnailId *HTHUMBNAIL) HRESULT {
|
||||||
|
ret, _, _ := procDwmRegisterThumbnail.Call(
|
||||||
|
uintptr(hWndDestination),
|
||||||
|
uintptr(hWndSource),
|
||||||
|
uintptr(unsafe.Pointer(phThumbnailId)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmRenderGesture(gt GESTURE_TYPE, cContacts uint, pdwPointerID *uint32, pPoints *POINT) {
|
||||||
|
procDwmRenderGesture.Call(
|
||||||
|
uintptr(gt),
|
||||||
|
uintptr(cContacts),
|
||||||
|
uintptr(unsafe.Pointer(pdwPointerID)),
|
||||||
|
uintptr(unsafe.Pointer(pPoints)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmSetDxFrameDuration(hWnd HWND, cRefreshes int) HRESULT {
|
||||||
|
ret, _, _ := procDwmSetDxFrameDuration.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(cRefreshes))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmSetIconicLivePreviewBitmap(hWnd HWND, hbmp HBITMAP, pptClient *POINT, dwSITFlags uint32) HRESULT {
|
||||||
|
ret, _, _ := procDwmSetIconicLivePreviewBitmap.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(hbmp),
|
||||||
|
uintptr(unsafe.Pointer(pptClient)),
|
||||||
|
uintptr(dwSITFlags))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmSetIconicThumbnail(hWnd HWND, hbmp HBITMAP, dwSITFlags uint32) HRESULT {
|
||||||
|
ret, _, _ := procDwmSetIconicThumbnail.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(hbmp),
|
||||||
|
uintptr(dwSITFlags))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmSetPresentParameters(hWnd HWND, pPresentParams *DWM_PRESENT_PARAMETERS) HRESULT {
|
||||||
|
ret, _, _ := procDwmSetPresentParameters.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(unsafe.Pointer(pPresentParams)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmSetWindowAttribute(hWnd HWND, dwAttribute uint32, pvAttribute LPCVOID, cbAttribute uint32) HRESULT {
|
||||||
|
ret, _, _ := procDwmSetWindowAttribute.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(dwAttribute),
|
||||||
|
uintptr(pvAttribute),
|
||||||
|
uintptr(cbAttribute))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmShowContact(dwPointerID uint32, eShowContact DWM_SHOWCONTACT) {
|
||||||
|
procDwmShowContact.Call(
|
||||||
|
uintptr(dwPointerID),
|
||||||
|
uintptr(eShowContact))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmTetherContact(dwPointerID uint32, fEnable bool, ptTether POINT) {
|
||||||
|
procDwmTetherContact.Call(
|
||||||
|
uintptr(dwPointerID),
|
||||||
|
uintptr(BoolToBOOL(fEnable)),
|
||||||
|
uintptr(unsafe.Pointer(&ptTether)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmTransitionOwnedWindow(hWnd HWND, target DWMTRANSITION_OWNEDWINDOW_TARGET) {
|
||||||
|
procDwmTransitionOwnedWindow.Call(
|
||||||
|
uintptr(hWnd),
|
||||||
|
uintptr(target))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmUnregisterThumbnail(hThumbnailId HTHUMBNAIL) HRESULT {
|
||||||
|
ret, _, _ := procDwmUnregisterThumbnail.Call(
|
||||||
|
uintptr(hThumbnailId))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DwmUpdateThumbnailProperties(hThumbnailId HTHUMBNAIL, ptnProperties *DWM_THUMBNAIL_PROPERTIES) HRESULT {
|
||||||
|
ret, _, _ := procDwmUpdateThumbnailProperties.Call(
|
||||||
|
uintptr(hThumbnailId),
|
||||||
|
uintptr(unsafe.Pointer(ptnProperties)))
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
174
vendor/github.com/apenwarr/w32/fork.go
generated
vendored
Normal file
174
vendor/github.com/apenwarr/w32/fork.go
generated
vendored
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
// #include <stdlib.h>
|
||||||
|
//import (
|
||||||
|
// "C"
|
||||||
|
//)
|
||||||
|
|
||||||
|
// Based on C code found here https://gist.github.com/juntalis/4366916
|
||||||
|
// Original code license:
|
||||||
|
/*
|
||||||
|
* fork.c
|
||||||
|
* Experimental fork() on Windows. Requires NT 6 subsystem or
|
||||||
|
* newer.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* This software is provided 'as is' and without any warranty, express or
|
||||||
|
* implied. In no event shall the authors be liable for any damages arising
|
||||||
|
* from the use of this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ntdll = syscall.NewLazyDLL("ntdll.dll")
|
||||||
|
|
||||||
|
procRtlCloneUserProcess = ntdll.NewProc("RtlCloneUserProcess")
|
||||||
|
procAllocConsole = modkernel32.NewProc("AllocConsole")
|
||||||
|
procOpenProcess = modkernel32.NewProc("OpenProcess")
|
||||||
|
procOpenThread = modkernel32.NewProc("OpenThread")
|
||||||
|
procResumeThread = modkernel32.NewProc("ResumeThread")
|
||||||
|
)
|
||||||
|
|
||||||
|
func OpenProcess(desiredAccess int, inheritHandle bool, processId uintptr) (h HANDLE, e error) {
|
||||||
|
inherit := uintptr(0)
|
||||||
|
if inheritHandle {
|
||||||
|
inherit = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, lastErr := procOpenProcess.Call(
|
||||||
|
uintptr(desiredAccess),
|
||||||
|
inherit,
|
||||||
|
uintptr(processId),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
e = lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
h = HANDLE(ret)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func OpenThread(desiredAccess int, inheritHandle bool, threadId uintptr) (h HANDLE, e error) {
|
||||||
|
inherit := uintptr(0)
|
||||||
|
if inheritHandle {
|
||||||
|
inherit = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, lastErr := procOpenThread.Call(
|
||||||
|
uintptr(desiredAccess),
|
||||||
|
inherit,
|
||||||
|
uintptr(threadId),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
e = lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
h = HANDLE(ret)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DWORD WINAPI ResumeThread(
|
||||||
|
// _In_ HANDLE hThread
|
||||||
|
// );
|
||||||
|
func ResumeThread(ht HANDLE) (e error) {
|
||||||
|
|
||||||
|
ret, _, lastErr := procResumeThread.Call(
|
||||||
|
uintptr(ht),
|
||||||
|
)
|
||||||
|
if ret == ^uintptr(0) { // -1
|
||||||
|
e = lastErr
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOOL WINAPI AllocConsole(void);
|
||||||
|
func AllocConsole() (e error) {
|
||||||
|
ret, _, lastErr := procAllocConsole.Call()
|
||||||
|
if ret != ERROR_SUCCESS {
|
||||||
|
e = lastErr
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NTSYSAPI
|
||||||
|
// NTSTATUS
|
||||||
|
// NTAPI RtlCloneUserProcess (
|
||||||
|
// _In_ ULONG ProcessFlags,
|
||||||
|
// _In_opt_ PSECURITY_DESCRIPTOR ProcessSecurityDescriptor,
|
||||||
|
// _In_opt_ PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,
|
||||||
|
// _In_opt_ HANDLE DebugPort,
|
||||||
|
// _Out_ PRTL_USER_PROCESS_INFORMATION ProcessInformation
|
||||||
|
// )
|
||||||
|
|
||||||
|
func RtlCloneUserProcess(
|
||||||
|
ProcessFlags uint32,
|
||||||
|
ProcessSecurityDescriptor, ThreadSecurityDescriptor *SECURITY_DESCRIPTOR, // in advapi32_typedef.go
|
||||||
|
DebugPort HANDLE,
|
||||||
|
ProcessInformation *RTL_USER_PROCESS_INFORMATION,
|
||||||
|
) (status uintptr) {
|
||||||
|
|
||||||
|
status, _, _ = procRtlCloneUserProcess.Call(
|
||||||
|
uintptr(ProcessFlags),
|
||||||
|
uintptr(unsafe.Pointer(ProcessSecurityDescriptor)),
|
||||||
|
uintptr(unsafe.Pointer(ThreadSecurityDescriptor)),
|
||||||
|
uintptr(DebugPort),
|
||||||
|
uintptr(unsafe.Pointer(ProcessInformation)),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fork creates a clone of the current process using the undocumented
|
||||||
|
// RtlCloneUserProcess call in ntdll, similar to unix fork(). The
|
||||||
|
// return value in the parent is the child PID. In the child it is 0.
|
||||||
|
func Fork() (pid uintptr, e error) {
|
||||||
|
|
||||||
|
pi := &RTL_USER_PROCESS_INFORMATION{}
|
||||||
|
|
||||||
|
ret := RtlCloneUserProcess(
|
||||||
|
RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED|RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
HANDLE(0),
|
||||||
|
pi,
|
||||||
|
)
|
||||||
|
|
||||||
|
switch ret {
|
||||||
|
case RTL_CLONE_PARENT:
|
||||||
|
pid = pi.ClientId.UniqueProcess
|
||||||
|
ht, err := OpenThread(THREAD_ALL_ACCESS, false, pi.ClientId.UniqueThread)
|
||||||
|
if err != nil {
|
||||||
|
e = fmt.Errorf("OpenThread: %s", err)
|
||||||
|
}
|
||||||
|
err = ResumeThread(ht)
|
||||||
|
if err != nil {
|
||||||
|
e = fmt.Errorf("ResumeThread: %s", err)
|
||||||
|
}
|
||||||
|
CloseHandle(ht)
|
||||||
|
case RTL_CLONE_CHILD:
|
||||||
|
pid = 0
|
||||||
|
err := AllocConsole()
|
||||||
|
if err != nil {
|
||||||
|
e = fmt.Errorf("AllocConsole: %s", err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
e = fmt.Errorf("0x%x", ret)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
26
vendor/github.com/apenwarr/w32/fork_constants.go
generated
vendored
Normal file
26
vendor/github.com/apenwarr/w32/fork_constants.go
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package w32
|
||||||
|
|
||||||
|
const (
|
||||||
|
RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED = 0x00000001
|
||||||
|
RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES = 0x00000002
|
||||||
|
RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE = 0x00000004
|
||||||
|
|
||||||
|
RTL_CLONE_PARENT = 0
|
||||||
|
RTL_CLONE_CHILD = 297
|
||||||
|
|
||||||
|
THREAD_TERMINATE = 0x0001
|
||||||
|
THREAD_SUSPEND_RESUME = 0x0002
|
||||||
|
THREAD_GET_CONTEXT = 0x0008
|
||||||
|
THREAD_SET_CONTEXT = 0x0010
|
||||||
|
THREAD_SET_INFORMATION = 0x0020
|
||||||
|
THREAD_QUERY_INFORMATION = 0x0040
|
||||||
|
THREAD_SET_THREAD_TOKEN = 0x0080
|
||||||
|
THREAD_IMPERSONATE = 0x0100
|
||||||
|
THREAD_DIRECT_IMPERSONATION = 0x0200
|
||||||
|
THREAD_SET_LIMITED_INFORMATION = 0x0400
|
||||||
|
THREAD_QUERY_LIMITED_INFORMATION = 0x0800
|
||||||
|
THREAD_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff
|
||||||
|
|
||||||
|
PROCESS_SET_SESSIONID = 0x0004
|
||||||
|
PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff
|
||||||
|
)
|
||||||
89
vendor/github.com/apenwarr/w32/fork_typedef.go
generated
vendored
Normal file
89
vendor/github.com/apenwarr/w32/fork_typedef.go
generated
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
package w32
|
||||||
|
|
||||||
|
// combase!_SECTION_IMAGE_INFORMATION
|
||||||
|
// +0x000 TransferAddress : Ptr64 Void
|
||||||
|
// +0x008 ZeroBits : Uint4B
|
||||||
|
// +0x010 MaximumStackSize : Uint8B
|
||||||
|
// +0x018 CommittedStackSize : Uint8B
|
||||||
|
// +0x020 SubSystemType : Uint4B
|
||||||
|
// +0x024 SubSystemMinorVersion : Uint2B
|
||||||
|
// +0x026 SubSystemMajorVersion : Uint2B
|
||||||
|
// +0x024 SubSystemVersion : Uint4B
|
||||||
|
// +0x028 MajorOperatingSystemVersion : Uint2B
|
||||||
|
// +0x02a MinorOperatingSystemVersion : Uint2B
|
||||||
|
// +0x028 OperatingSystemVersion : Uint4B
|
||||||
|
// +0x02c ImageCharacteristics : Uint2B
|
||||||
|
// +0x02e DllCharacteristics : Uint2B
|
||||||
|
// +0x030 Machine : Uint2B
|
||||||
|
// +0x032 ImageContainsCode : UChar
|
||||||
|
// +0x033 ImageFlags : UChar
|
||||||
|
// +0x033 ComPlusNativeReady : Pos 0, 1 Bit
|
||||||
|
// +0x033 ComPlusILOnly : Pos 1, 1 Bit
|
||||||
|
// +0x033 ImageDynamicallyRelocated : Pos 2, 1 Bit
|
||||||
|
// +0x033 ImageMappedFlat : Pos 3, 1 Bit
|
||||||
|
// +0x033 BaseBelow4gb : Pos 4, 1 Bit
|
||||||
|
// +0x033 ComPlusPrefer32bit : Pos 5, 1 Bit
|
||||||
|
// +0x033 Reserved : Pos 6, 2 Bits
|
||||||
|
// +0x034 LoaderFlags : Uint4B
|
||||||
|
// +0x038 ImageFileSize : Uint4B
|
||||||
|
// +0x03c CheckSum : Uint4B
|
||||||
|
type SECTION_IMAGE_INFORMATION struct {
|
||||||
|
TransferAddress uintptr
|
||||||
|
ZeroBits uint32
|
||||||
|
MaximumStackSize uint64
|
||||||
|
CommittedStackSize uint64
|
||||||
|
SubSystemType uint32
|
||||||
|
SubSystemMinorVersion uint16
|
||||||
|
SubSystemMajorVersion uint16
|
||||||
|
SubSystemVersion uint32
|
||||||
|
MajorOperatingSystemVersion uint16
|
||||||
|
MinorOperatingSystemVersion uint16
|
||||||
|
OperatingSystemVersion uint32
|
||||||
|
ImageCharacteristics uint16
|
||||||
|
DllCharacteristics uint16
|
||||||
|
Machine uint16
|
||||||
|
ImageContainsCode uint8
|
||||||
|
ImageFlags uint8
|
||||||
|
ComPlusFlags uint8
|
||||||
|
LoaderFlags uint32
|
||||||
|
ImageFileSize uint32
|
||||||
|
CheckSum uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (si *SECTION_IMAGE_INFORMATION) ComPlusNativeReady() bool {
|
||||||
|
return (si.ComPlusFlags & (1 << 0)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (si *SECTION_IMAGE_INFORMATION) ComPlusILOnly() bool {
|
||||||
|
return (si.ComPlusFlags & (1 << 1)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (si *SECTION_IMAGE_INFORMATION) ImageDynamicallyRelocated() bool {
|
||||||
|
return (si.ComPlusFlags & (1 << 2)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (si *SECTION_IMAGE_INFORMATION) ImageMappedFlat() bool {
|
||||||
|
return (si.ComPlusFlags & (1 << 3)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (si *SECTION_IMAGE_INFORMATION) BaseBelow4gb() bool {
|
||||||
|
return (si.ComPlusFlags & (1 << 4)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (si *SECTION_IMAGE_INFORMATION) ComPlusPrefer32bit() bool {
|
||||||
|
return (si.ComPlusFlags & (1 << 5)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// combase!_RTL_USER_PROCESS_INFORMATION
|
||||||
|
// +0x000 Length : Uint4B
|
||||||
|
// +0x008 Process : Ptr64 Void
|
||||||
|
// +0x010 Thread : Ptr64 Void
|
||||||
|
// +0x018 ClientId : _CLIENT_ID
|
||||||
|
// +0x028 ImageInformation : _SECTION_IMAGE_INFORMATION
|
||||||
|
type RTL_USER_PROCESS_INFORMATION struct {
|
||||||
|
Length uint32
|
||||||
|
Process HANDLE
|
||||||
|
Thread HANDLE
|
||||||
|
ClientId CLIENT_ID
|
||||||
|
ImageInformation SECTION_IMAGE_INFORMATION
|
||||||
|
}
|
||||||
543
vendor/github.com/apenwarr/w32/gdi32.go
generated
vendored
Normal file
543
vendor/github.com/apenwarr/w32/gdi32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,543 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modgdi32 = syscall.NewLazyDLL("gdi32.dll")
|
||||||
|
|
||||||
|
procGetDeviceCaps = modgdi32.NewProc("GetDeviceCaps")
|
||||||
|
procGetCurrentObject = modgdi32.NewProc("GetCurrentObject")
|
||||||
|
procDeleteObject = modgdi32.NewProc("DeleteObject")
|
||||||
|
procCreateFontIndirect = modgdi32.NewProc("CreateFontIndirectW")
|
||||||
|
procAbortDoc = modgdi32.NewProc("AbortDoc")
|
||||||
|
procBitBlt = modgdi32.NewProc("BitBlt")
|
||||||
|
procPatBlt = modgdi32.NewProc("PatBlt")
|
||||||
|
procCloseEnhMetaFile = modgdi32.NewProc("CloseEnhMetaFile")
|
||||||
|
procCopyEnhMetaFile = modgdi32.NewProc("CopyEnhMetaFileW")
|
||||||
|
procCreateBrushIndirect = modgdi32.NewProc("CreateBrushIndirect")
|
||||||
|
procCreateCompatibleDC = modgdi32.NewProc("CreateCompatibleDC")
|
||||||
|
procCreateDC = modgdi32.NewProc("CreateDCW")
|
||||||
|
procCreateCompatibleBitmap = modgdi32.NewProc("CreateCompatibleBitmap")
|
||||||
|
procCreateDIBSection = modgdi32.NewProc("CreateDIBSection")
|
||||||
|
procCreateEnhMetaFile = modgdi32.NewProc("CreateEnhMetaFileW")
|
||||||
|
procCreateIC = modgdi32.NewProc("CreateICW")
|
||||||
|
procDeleteDC = modgdi32.NewProc("DeleteDC")
|
||||||
|
procDeleteEnhMetaFile = modgdi32.NewProc("DeleteEnhMetaFile")
|
||||||
|
procEllipse = modgdi32.NewProc("Ellipse")
|
||||||
|
procEndDoc = modgdi32.NewProc("EndDoc")
|
||||||
|
procEndPage = modgdi32.NewProc("EndPage")
|
||||||
|
procExtCreatePen = modgdi32.NewProc("ExtCreatePen")
|
||||||
|
procGetEnhMetaFile = modgdi32.NewProc("GetEnhMetaFileW")
|
||||||
|
procGetEnhMetaFileHeader = modgdi32.NewProc("GetEnhMetaFileHeader")
|
||||||
|
procGetObject = modgdi32.NewProc("GetObjectW")
|
||||||
|
procGetStockObject = modgdi32.NewProc("GetStockObject")
|
||||||
|
procGetTextExtentExPoint = modgdi32.NewProc("GetTextExtentExPointW")
|
||||||
|
procGetTextExtentPoint32 = modgdi32.NewProc("GetTextExtentPoint32W")
|
||||||
|
procGetTextMetrics = modgdi32.NewProc("GetTextMetricsW")
|
||||||
|
procLineTo = modgdi32.NewProc("LineTo")
|
||||||
|
procMoveToEx = modgdi32.NewProc("MoveToEx")
|
||||||
|
procPlayEnhMetaFile = modgdi32.NewProc("PlayEnhMetaFile")
|
||||||
|
procRectangle = modgdi32.NewProc("Rectangle")
|
||||||
|
procResetDC = modgdi32.NewProc("ResetDCW")
|
||||||
|
procSelectObject = modgdi32.NewProc("SelectObject")
|
||||||
|
procSetBkMode = modgdi32.NewProc("SetBkMode")
|
||||||
|
procSetBrushOrgEx = modgdi32.NewProc("SetBrushOrgEx")
|
||||||
|
procSetStretchBltMode = modgdi32.NewProc("SetStretchBltMode")
|
||||||
|
procSetTextColor = modgdi32.NewProc("SetTextColor")
|
||||||
|
procSetBkColor = modgdi32.NewProc("SetBkColor")
|
||||||
|
procStartDoc = modgdi32.NewProc("StartDocW")
|
||||||
|
procStartPage = modgdi32.NewProc("StartPage")
|
||||||
|
procStretchBlt = modgdi32.NewProc("StretchBlt")
|
||||||
|
procSetDIBitsToDevice = modgdi32.NewProc("SetDIBitsToDevice")
|
||||||
|
procChoosePixelFormat = modgdi32.NewProc("ChoosePixelFormat")
|
||||||
|
procDescribePixelFormat = modgdi32.NewProc("DescribePixelFormat")
|
||||||
|
procGetEnhMetaFilePixelFormat = modgdi32.NewProc("GetEnhMetaFilePixelFormat")
|
||||||
|
procGetPixelFormat = modgdi32.NewProc("GetPixelFormat")
|
||||||
|
procSetPixelFormat = modgdi32.NewProc("SetPixelFormat")
|
||||||
|
procSwapBuffers = modgdi32.NewProc("SwapBuffers")
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetDeviceCaps(hdc HDC, index int) int {
|
||||||
|
ret, _, _ := procGetDeviceCaps.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(index))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCurrentObject(hdc HDC, uObjectType uint32) HGDIOBJ {
|
||||||
|
ret, _, _ := procGetCurrentObject.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(uObjectType))
|
||||||
|
|
||||||
|
return HGDIOBJ(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteObject(hObject HGDIOBJ) bool {
|
||||||
|
ret, _, _ := procDeleteObject.Call(
|
||||||
|
uintptr(hObject))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateFontIndirect(logFont *LOGFONT) HFONT {
|
||||||
|
ret, _, _ := procCreateFontIndirect.Call(
|
||||||
|
uintptr(unsafe.Pointer(logFont)))
|
||||||
|
|
||||||
|
return HFONT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func AbortDoc(hdc HDC) int {
|
||||||
|
ret, _, _ := procAbortDoc.Call(
|
||||||
|
uintptr(hdc))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BitBlt(hdcDest HDC, nXDest, nYDest, nWidth, nHeight int, hdcSrc HDC, nXSrc, nYSrc int, dwRop uint) {
|
||||||
|
ret, _, _ := procBitBlt.Call(
|
||||||
|
uintptr(hdcDest),
|
||||||
|
uintptr(nXDest),
|
||||||
|
uintptr(nYDest),
|
||||||
|
uintptr(nWidth),
|
||||||
|
uintptr(nHeight),
|
||||||
|
uintptr(hdcSrc),
|
||||||
|
uintptr(nXSrc),
|
||||||
|
uintptr(nYSrc),
|
||||||
|
uintptr(dwRop))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("BitBlt failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func PatBlt(hdc HDC, nXLeft, nYLeft, nWidth, nHeight int, dwRop uint) {
|
||||||
|
ret, _, _ := procPatBlt.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(nXLeft),
|
||||||
|
uintptr(nYLeft),
|
||||||
|
uintptr(nWidth),
|
||||||
|
uintptr(nHeight),
|
||||||
|
uintptr(dwRop))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("PatBlt failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CloseEnhMetaFile(hdc HDC) HENHMETAFILE {
|
||||||
|
ret, _, _ := procCloseEnhMetaFile.Call(
|
||||||
|
uintptr(hdc))
|
||||||
|
|
||||||
|
return HENHMETAFILE(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CopyEnhMetaFile(hemfSrc HENHMETAFILE, lpszFile *uint16) HENHMETAFILE {
|
||||||
|
ret, _, _ := procCopyEnhMetaFile.Call(
|
||||||
|
uintptr(hemfSrc),
|
||||||
|
uintptr(unsafe.Pointer(lpszFile)))
|
||||||
|
|
||||||
|
return HENHMETAFILE(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateBrushIndirect(lplb *LOGBRUSH) HBRUSH {
|
||||||
|
ret, _, _ := procCreateBrushIndirect.Call(
|
||||||
|
uintptr(unsafe.Pointer(lplb)))
|
||||||
|
|
||||||
|
return HBRUSH(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateCompatibleDC(hdc HDC) HDC {
|
||||||
|
ret, _, _ := procCreateCompatibleDC.Call(
|
||||||
|
uintptr(hdc))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("Create compatible DC failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return HDC(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateDC(lpszDriver, lpszDevice, lpszOutput *uint16, lpInitData *DEVMODE) HDC {
|
||||||
|
ret, _, _ := procCreateDC.Call(
|
||||||
|
uintptr(unsafe.Pointer(lpszDriver)),
|
||||||
|
uintptr(unsafe.Pointer(lpszDevice)),
|
||||||
|
uintptr(unsafe.Pointer(lpszOutput)),
|
||||||
|
uintptr(unsafe.Pointer(lpInitData)))
|
||||||
|
|
||||||
|
return HDC(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateCompatibleBitmap(hdc HDC, width, height uint) HBITMAP {
|
||||||
|
ret, _, _ := procCreateCompatibleBitmap.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(width),
|
||||||
|
uintptr(height))
|
||||||
|
|
||||||
|
return HBITMAP(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateDIBSection(hdc HDC, pbmi *BITMAPINFO, iUsage uint, ppvBits *unsafe.Pointer, hSection HANDLE, dwOffset uint) HBITMAP {
|
||||||
|
ret, _, _ := procCreateDIBSection.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(unsafe.Pointer(pbmi)),
|
||||||
|
uintptr(iUsage),
|
||||||
|
uintptr(unsafe.Pointer(ppvBits)),
|
||||||
|
uintptr(hSection),
|
||||||
|
uintptr(dwOffset))
|
||||||
|
|
||||||
|
return HBITMAP(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateEnhMetaFile(hdcRef HDC, lpFilename *uint16, lpRect *RECT, lpDescription *uint16) HDC {
|
||||||
|
ret, _, _ := procCreateEnhMetaFile.Call(
|
||||||
|
uintptr(hdcRef),
|
||||||
|
uintptr(unsafe.Pointer(lpFilename)),
|
||||||
|
uintptr(unsafe.Pointer(lpRect)),
|
||||||
|
uintptr(unsafe.Pointer(lpDescription)))
|
||||||
|
|
||||||
|
return HDC(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateIC(lpszDriver, lpszDevice, lpszOutput *uint16, lpdvmInit *DEVMODE) HDC {
|
||||||
|
ret, _, _ := procCreateIC.Call(
|
||||||
|
uintptr(unsafe.Pointer(lpszDriver)),
|
||||||
|
uintptr(unsafe.Pointer(lpszDevice)),
|
||||||
|
uintptr(unsafe.Pointer(lpszOutput)),
|
||||||
|
uintptr(unsafe.Pointer(lpdvmInit)))
|
||||||
|
|
||||||
|
return HDC(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteDC(hdc HDC) bool {
|
||||||
|
ret, _, _ := procDeleteDC.Call(
|
||||||
|
uintptr(hdc))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteEnhMetaFile(hemf HENHMETAFILE) bool {
|
||||||
|
ret, _, _ := procDeleteEnhMetaFile.Call(
|
||||||
|
uintptr(hemf))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ellipse(hdc HDC, nLeftRect, nTopRect, nRightRect, nBottomRect int) bool {
|
||||||
|
ret, _, _ := procEllipse.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(nLeftRect),
|
||||||
|
uintptr(nTopRect),
|
||||||
|
uintptr(nRightRect),
|
||||||
|
uintptr(nBottomRect))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func EndDoc(hdc HDC) int {
|
||||||
|
ret, _, _ := procEndDoc.Call(
|
||||||
|
uintptr(hdc))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EndPage(hdc HDC) int {
|
||||||
|
ret, _, _ := procEndPage.Call(
|
||||||
|
uintptr(hdc))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtCreatePen(dwPenStyle, dwWidth uint, lplb *LOGBRUSH, dwStyleCount uint, lpStyle *uint) HPEN {
|
||||||
|
ret, _, _ := procExtCreatePen.Call(
|
||||||
|
uintptr(dwPenStyle),
|
||||||
|
uintptr(dwWidth),
|
||||||
|
uintptr(unsafe.Pointer(lplb)),
|
||||||
|
uintptr(dwStyleCount),
|
||||||
|
uintptr(unsafe.Pointer(lpStyle)))
|
||||||
|
|
||||||
|
return HPEN(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetEnhMetaFile(lpszMetaFile *uint16) HENHMETAFILE {
|
||||||
|
ret, _, _ := procGetEnhMetaFile.Call(
|
||||||
|
uintptr(unsafe.Pointer(lpszMetaFile)))
|
||||||
|
|
||||||
|
return HENHMETAFILE(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetEnhMetaFileHeader(hemf HENHMETAFILE, cbBuffer uint, lpemh *ENHMETAHEADER) uint {
|
||||||
|
ret, _, _ := procGetEnhMetaFileHeader.Call(
|
||||||
|
uintptr(hemf),
|
||||||
|
uintptr(cbBuffer),
|
||||||
|
uintptr(unsafe.Pointer(lpemh)))
|
||||||
|
|
||||||
|
return uint(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetObject(hgdiobj HGDIOBJ, cbBuffer uintptr, lpvObject unsafe.Pointer) int {
|
||||||
|
ret, _, _ := procGetObject.Call(
|
||||||
|
uintptr(hgdiobj),
|
||||||
|
uintptr(cbBuffer),
|
||||||
|
uintptr(lpvObject))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStockObject(fnObject int) HGDIOBJ {
|
||||||
|
ret, _, _ := procGetStockObject.Call(
|
||||||
|
uintptr(fnObject))
|
||||||
|
|
||||||
|
return HGDIOBJ(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTextExtentExPoint(hdc HDC, lpszStr *uint16, cchString, nMaxExtent int, lpnFit, alpDx *int, lpSize *SIZE) bool {
|
||||||
|
ret, _, _ := procGetTextExtentExPoint.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(unsafe.Pointer(lpszStr)),
|
||||||
|
uintptr(cchString),
|
||||||
|
uintptr(nMaxExtent),
|
||||||
|
uintptr(unsafe.Pointer(lpnFit)),
|
||||||
|
uintptr(unsafe.Pointer(alpDx)),
|
||||||
|
uintptr(unsafe.Pointer(lpSize)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTextExtentPoint32(hdc HDC, lpString *uint16, c int, lpSize *SIZE) bool {
|
||||||
|
ret, _, _ := procGetTextExtentPoint32.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(unsafe.Pointer(lpString)),
|
||||||
|
uintptr(c),
|
||||||
|
uintptr(unsafe.Pointer(lpSize)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTextMetrics(hdc HDC, lptm *TEXTMETRIC) bool {
|
||||||
|
ret, _, _ := procGetTextMetrics.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(unsafe.Pointer(lptm)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func LineTo(hdc HDC, nXEnd, nYEnd int) bool {
|
||||||
|
ret, _, _ := procLineTo.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(nXEnd),
|
||||||
|
uintptr(nYEnd))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func MoveToEx(hdc HDC, x, y int, lpPoint *POINT) bool {
|
||||||
|
ret, _, _ := procMoveToEx.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(x),
|
||||||
|
uintptr(y),
|
||||||
|
uintptr(unsafe.Pointer(lpPoint)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func PlayEnhMetaFile(hdc HDC, hemf HENHMETAFILE, lpRect *RECT) bool {
|
||||||
|
ret, _, _ := procPlayEnhMetaFile.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(hemf),
|
||||||
|
uintptr(unsafe.Pointer(lpRect)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Rectangle(hdc HDC, nLeftRect, nTopRect, nRightRect, nBottomRect int) bool {
|
||||||
|
ret, _, _ := procRectangle.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(nLeftRect),
|
||||||
|
uintptr(nTopRect),
|
||||||
|
uintptr(nRightRect),
|
||||||
|
uintptr(nBottomRect))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResetDC(hdc HDC, lpInitData *DEVMODE) HDC {
|
||||||
|
ret, _, _ := procResetDC.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(unsafe.Pointer(lpInitData)))
|
||||||
|
|
||||||
|
return HDC(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SelectObject(hdc HDC, hgdiobj HGDIOBJ) HGDIOBJ {
|
||||||
|
ret, _, _ := procSelectObject.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(hgdiobj))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("SelectObject failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return HGDIOBJ(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetBkMode(hdc HDC, iBkMode int) int {
|
||||||
|
ret, _, _ := procSetBkMode.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(iBkMode))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("SetBkMode failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetBrushOrgEx(hdc HDC, nXOrg, nYOrg int, lppt *POINT) bool {
|
||||||
|
ret, _, _ := procSetBrushOrgEx.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(nXOrg),
|
||||||
|
uintptr(nYOrg),
|
||||||
|
uintptr(unsafe.Pointer(lppt)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetStretchBltMode(hdc HDC, iStretchMode int) int {
|
||||||
|
ret, _, _ := procSetStretchBltMode.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(iStretchMode))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetTextColor(hdc HDC, crColor COLORREF) COLORREF {
|
||||||
|
ret, _, _ := procSetTextColor.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(crColor))
|
||||||
|
|
||||||
|
if ret == CLR_INVALID {
|
||||||
|
panic("SetTextColor failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return COLORREF(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetBkColor(hdc HDC, crColor COLORREF) COLORREF {
|
||||||
|
ret, _, _ := procSetBkColor.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(crColor))
|
||||||
|
|
||||||
|
if ret == CLR_INVALID {
|
||||||
|
panic("SetBkColor failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return COLORREF(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartDoc(hdc HDC, lpdi *DOCINFO) int {
|
||||||
|
ret, _, _ := procStartDoc.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(unsafe.Pointer(lpdi)))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartPage(hdc HDC) int {
|
||||||
|
ret, _, _ := procStartPage.Call(
|
||||||
|
uintptr(hdc))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StretchBlt(hdcDest HDC, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest int, hdcSrc HDC, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc int, dwRop uint) {
|
||||||
|
ret, _, _ := procStretchBlt.Call(
|
||||||
|
uintptr(hdcDest),
|
||||||
|
uintptr(nXOriginDest),
|
||||||
|
uintptr(nYOriginDest),
|
||||||
|
uintptr(nWidthDest),
|
||||||
|
uintptr(nHeightDest),
|
||||||
|
uintptr(hdcSrc),
|
||||||
|
uintptr(nXOriginSrc),
|
||||||
|
uintptr(nYOriginSrc),
|
||||||
|
uintptr(nWidthSrc),
|
||||||
|
uintptr(nHeightSrc),
|
||||||
|
uintptr(dwRop))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("StretchBlt failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetDIBitsToDevice(hdc HDC, xDest, yDest, dwWidth, dwHeight, xSrc, ySrc int, uStartScan, cScanLines uint, lpvBits []byte, lpbmi *BITMAPINFO, fuColorUse uint) int {
|
||||||
|
ret, _, _ := procSetDIBitsToDevice.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(xDest),
|
||||||
|
uintptr(yDest),
|
||||||
|
uintptr(dwWidth),
|
||||||
|
uintptr(dwHeight),
|
||||||
|
uintptr(xSrc),
|
||||||
|
uintptr(ySrc),
|
||||||
|
uintptr(uStartScan),
|
||||||
|
uintptr(cScanLines),
|
||||||
|
uintptr(unsafe.Pointer(&lpvBits[0])),
|
||||||
|
uintptr(unsafe.Pointer(lpbmi)),
|
||||||
|
uintptr(fuColorUse))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChoosePixelFormat(hdc HDC, pfd *PIXELFORMATDESCRIPTOR) int {
|
||||||
|
ret, _, _ := procChoosePixelFormat.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(unsafe.Pointer(pfd)),
|
||||||
|
)
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DescribePixelFormat(hdc HDC, iPixelFormat int, nBytes uint, pfd *PIXELFORMATDESCRIPTOR) int {
|
||||||
|
ret, _, _ := procDescribePixelFormat.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(iPixelFormat),
|
||||||
|
uintptr(nBytes),
|
||||||
|
uintptr(unsafe.Pointer(pfd)),
|
||||||
|
)
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetEnhMetaFilePixelFormat(hemf HENHMETAFILE, cbBuffer uint32, pfd *PIXELFORMATDESCRIPTOR) uint {
|
||||||
|
ret, _, _ := procGetEnhMetaFilePixelFormat.Call(
|
||||||
|
uintptr(hemf),
|
||||||
|
uintptr(cbBuffer),
|
||||||
|
uintptr(unsafe.Pointer(pfd)),
|
||||||
|
)
|
||||||
|
return uint(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPixelFormat(hdc HDC) int {
|
||||||
|
ret, _, _ := procGetPixelFormat.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
)
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetPixelFormat(hdc HDC, iPixelFormat int, pfd *PIXELFORMATDESCRIPTOR) bool {
|
||||||
|
ret, _, _ := procSetPixelFormat.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(iPixelFormat),
|
||||||
|
uintptr(unsafe.Pointer(pfd)),
|
||||||
|
)
|
||||||
|
return ret == TRUE
|
||||||
|
}
|
||||||
|
|
||||||
|
func SwapBuffers(hdc HDC) bool {
|
||||||
|
ret, _, _ := procSwapBuffers.Call(uintptr(hdc))
|
||||||
|
return ret == TRUE
|
||||||
|
}
|
||||||
175
vendor/github.com/apenwarr/w32/gdiplus.go
generated
vendored
Normal file
175
vendor/github.com/apenwarr/w32/gdiplus.go
generated
vendored
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Ok = 0
|
||||||
|
GenericError = 1
|
||||||
|
InvalidParameter = 2
|
||||||
|
OutOfMemory = 3
|
||||||
|
ObjectBusy = 4
|
||||||
|
InsufficientBuffer = 5
|
||||||
|
NotImplemented = 6
|
||||||
|
Win32Error = 7
|
||||||
|
WrongState = 8
|
||||||
|
Aborted = 9
|
||||||
|
FileNotFound = 10
|
||||||
|
ValueOverflow = 11
|
||||||
|
AccessDenied = 12
|
||||||
|
UnknownImageFormat = 13
|
||||||
|
FontFamilyNotFound = 14
|
||||||
|
FontStyleNotFound = 15
|
||||||
|
NotTrueTypeFont = 16
|
||||||
|
UnsupportedGdiplusVersion = 17
|
||||||
|
GdiplusNotInitialized = 18
|
||||||
|
PropertyNotFound = 19
|
||||||
|
PropertyNotSupported = 20
|
||||||
|
ProfileNotFound = 21
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetGpStatus(s int32) string {
|
||||||
|
switch s {
|
||||||
|
case Ok:
|
||||||
|
return "Ok"
|
||||||
|
case GenericError:
|
||||||
|
return "GenericError"
|
||||||
|
case InvalidParameter:
|
||||||
|
return "InvalidParameter"
|
||||||
|
case OutOfMemory:
|
||||||
|
return "OutOfMemory"
|
||||||
|
case ObjectBusy:
|
||||||
|
return "ObjectBusy"
|
||||||
|
case InsufficientBuffer:
|
||||||
|
return "InsufficientBuffer"
|
||||||
|
case NotImplemented:
|
||||||
|
return "NotImplemented"
|
||||||
|
case Win32Error:
|
||||||
|
return "Win32Error"
|
||||||
|
case WrongState:
|
||||||
|
return "WrongState"
|
||||||
|
case Aborted:
|
||||||
|
return "Aborted"
|
||||||
|
case FileNotFound:
|
||||||
|
return "FileNotFound"
|
||||||
|
case ValueOverflow:
|
||||||
|
return "ValueOverflow"
|
||||||
|
case AccessDenied:
|
||||||
|
return "AccessDenied"
|
||||||
|
case UnknownImageFormat:
|
||||||
|
return "UnknownImageFormat"
|
||||||
|
case FontFamilyNotFound:
|
||||||
|
return "FontFamilyNotFound"
|
||||||
|
case FontStyleNotFound:
|
||||||
|
return "FontStyleNotFound"
|
||||||
|
case NotTrueTypeFont:
|
||||||
|
return "NotTrueTypeFont"
|
||||||
|
case UnsupportedGdiplusVersion:
|
||||||
|
return "UnsupportedGdiplusVersion"
|
||||||
|
case GdiplusNotInitialized:
|
||||||
|
return "GdiplusNotInitialized"
|
||||||
|
case PropertyNotFound:
|
||||||
|
return "PropertyNotFound"
|
||||||
|
case PropertyNotSupported:
|
||||||
|
return "PropertyNotSupported"
|
||||||
|
case ProfileNotFound:
|
||||||
|
return "ProfileNotFound"
|
||||||
|
}
|
||||||
|
return "Unknown Status Value"
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
token uintptr
|
||||||
|
|
||||||
|
modgdiplus = syscall.NewLazyDLL("gdiplus.dll")
|
||||||
|
|
||||||
|
procGdipCreateBitmapFromFile = modgdiplus.NewProc("GdipCreateBitmapFromFile")
|
||||||
|
procGdipCreateBitmapFromHBITMAP = modgdiplus.NewProc("GdipCreateBitmapFromHBITMAP")
|
||||||
|
procGdipCreateHBITMAPFromBitmap = modgdiplus.NewProc("GdipCreateHBITMAPFromBitmap")
|
||||||
|
procGdipCreateBitmapFromResource = modgdiplus.NewProc("GdipCreateBitmapFromResource")
|
||||||
|
procGdipCreateBitmapFromStream = modgdiplus.NewProc("GdipCreateBitmapFromStream")
|
||||||
|
procGdipDisposeImage = modgdiplus.NewProc("GdipDisposeImage")
|
||||||
|
procGdiplusShutdown = modgdiplus.NewProc("GdiplusShutdown")
|
||||||
|
procGdiplusStartup = modgdiplus.NewProc("GdiplusStartup")
|
||||||
|
)
|
||||||
|
|
||||||
|
func GdipCreateBitmapFromFile(filename string) (*uintptr, error) {
|
||||||
|
var bitmap *uintptr
|
||||||
|
ret, _, _ := procGdipCreateBitmapFromFile.Call(
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(filename))),
|
||||||
|
uintptr(unsafe.Pointer(&bitmap)))
|
||||||
|
|
||||||
|
if ret != Ok {
|
||||||
|
return nil, errors.New(fmt.Sprintf("GdipCreateBitmapFromFile failed with status '%s' for file '%s'", GetGpStatus(int32(ret)), filename))
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GdipCreateBitmapFromResource(instance HINSTANCE, resId *uint16) (*uintptr, error) {
|
||||||
|
var bitmap *uintptr
|
||||||
|
ret, _, _ := procGdipCreateBitmapFromResource.Call(
|
||||||
|
uintptr(instance),
|
||||||
|
uintptr(unsafe.Pointer(resId)),
|
||||||
|
uintptr(unsafe.Pointer(&bitmap)))
|
||||||
|
|
||||||
|
if ret != Ok {
|
||||||
|
return nil, errors.New(fmt.Sprintf("GdiCreateBitmapFromResource failed with status '%s'", GetGpStatus(int32(ret))))
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GdipCreateBitmapFromStream(stream *IStream) (*uintptr, error) {
|
||||||
|
var bitmap *uintptr
|
||||||
|
ret, _, _ := procGdipCreateBitmapFromStream.Call(
|
||||||
|
uintptr(unsafe.Pointer(stream)),
|
||||||
|
uintptr(unsafe.Pointer(&bitmap)))
|
||||||
|
|
||||||
|
if ret != Ok {
|
||||||
|
return nil, errors.New(fmt.Sprintf("GdipCreateBitmapFromStream failed with status '%s'", GetGpStatus(int32(ret))))
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GdipCreateHBITMAPFromBitmap(bitmap *uintptr, background uint32) (HBITMAP, error) {
|
||||||
|
var hbitmap HBITMAP
|
||||||
|
ret, _, _ := procGdipCreateHBITMAPFromBitmap.Call(
|
||||||
|
uintptr(unsafe.Pointer(bitmap)),
|
||||||
|
uintptr(unsafe.Pointer(&hbitmap)),
|
||||||
|
uintptr(background))
|
||||||
|
|
||||||
|
if ret != Ok {
|
||||||
|
return 0, errors.New(fmt.Sprintf("GdipCreateHBITMAPFromBitmap failed with status '%s'", GetGpStatus(int32(ret))))
|
||||||
|
}
|
||||||
|
|
||||||
|
return hbitmap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GdipDisposeImage(image *uintptr) {
|
||||||
|
procGdipDisposeImage.Call(uintptr(unsafe.Pointer(image)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GdiplusShutdown() {
|
||||||
|
procGdiplusShutdown.Call(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GdiplusStartup(input *GdiplusStartupInput, output *GdiplusStartupOutput) {
|
||||||
|
ret, _, _ := procGdiplusStartup.Call(
|
||||||
|
uintptr(unsafe.Pointer(&token)),
|
||||||
|
uintptr(unsafe.Pointer(input)),
|
||||||
|
uintptr(unsafe.Pointer(output)))
|
||||||
|
|
||||||
|
if ret != Ok {
|
||||||
|
panic("GdiplusStartup failed with status " + GetGpStatus(int32(ret)))
|
||||||
|
}
|
||||||
|
}
|
||||||
43
vendor/github.com/apenwarr/w32/idispatch.go
generated
vendored
Normal file
43
vendor/github.com/apenwarr/w32/idispatch.go
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type pIDispatchVtbl struct {
|
||||||
|
pQueryInterface uintptr
|
||||||
|
pAddRef uintptr
|
||||||
|
pRelease uintptr
|
||||||
|
pGetTypeInfoCount uintptr
|
||||||
|
pGetTypeInfo uintptr
|
||||||
|
pGetIDsOfNames uintptr
|
||||||
|
pInvoke uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type IDispatch struct {
|
||||||
|
lpVtbl *pIDispatchVtbl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IDispatch) QueryInterface(id *GUID) *IDispatch {
|
||||||
|
return ComQueryInterface((*IUnknown)(unsafe.Pointer(this)), id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IDispatch) AddRef() int32 {
|
||||||
|
return ComAddRef((*IUnknown)(unsafe.Pointer(this)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IDispatch) Release() int32 {
|
||||||
|
return ComRelease((*IUnknown)(unsafe.Pointer(this)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IDispatch) GetIDsOfName(names []string) []int32 {
|
||||||
|
return ComGetIDsOfName(this, names)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) *VARIANT {
|
||||||
|
return ComInvoke(this, dispid, dispatch, params...)
|
||||||
|
}
|
||||||
31
vendor/github.com/apenwarr/w32/istream.go
generated
vendored
Normal file
31
vendor/github.com/apenwarr/w32/istream.go
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type pIStreamVtbl struct {
|
||||||
|
pQueryInterface uintptr
|
||||||
|
pAddRef uintptr
|
||||||
|
pRelease uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type IStream struct {
|
||||||
|
lpVtbl *pIStreamVtbl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IStream) QueryInterface(id *GUID) *IDispatch {
|
||||||
|
return ComQueryInterface((*IUnknown)(unsafe.Pointer(this)), id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IStream) AddRef() int32 {
|
||||||
|
return ComAddRef((*IUnknown)(unsafe.Pointer(this)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IStream) Release() int32 {
|
||||||
|
return ComRelease((*IUnknown)(unsafe.Pointer(this)))
|
||||||
|
}
|
||||||
27
vendor/github.com/apenwarr/w32/iunknown.go
generated
vendored
Normal file
27
vendor/github.com/apenwarr/w32/iunknown.go
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
type pIUnknownVtbl struct {
|
||||||
|
pQueryInterface uintptr
|
||||||
|
pAddRef uintptr
|
||||||
|
pRelease uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type IUnknown struct {
|
||||||
|
lpVtbl *pIUnknownVtbl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IUnknown) QueryInterface(id *GUID) *IDispatch {
|
||||||
|
return ComQueryInterface(this, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IUnknown) AddRef() int32 {
|
||||||
|
return ComAddRef(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IUnknown) Release() int32 {
|
||||||
|
return ComRelease(this)
|
||||||
|
}
|
||||||
388
vendor/github.com/apenwarr/w32/kernel32.go
generated
vendored
Normal file
388
vendor/github.com/apenwarr/w32/kernel32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,388 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||||
|
|
||||||
|
procGetModuleHandle = modkernel32.NewProc("GetModuleHandleW")
|
||||||
|
procMulDiv = modkernel32.NewProc("MulDiv")
|
||||||
|
procGetConsoleWindow = modkernel32.NewProc("GetConsoleWindow")
|
||||||
|
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
|
||||||
|
procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives")
|
||||||
|
procGetUserDefaultLCID = modkernel32.NewProc("GetUserDefaultLCID")
|
||||||
|
procLstrlen = modkernel32.NewProc("lstrlenW")
|
||||||
|
procLstrcpy = modkernel32.NewProc("lstrcpyW")
|
||||||
|
procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
|
||||||
|
procGlobalFree = modkernel32.NewProc("GlobalFree")
|
||||||
|
procGlobalLock = modkernel32.NewProc("GlobalLock")
|
||||||
|
procGlobalUnlock = modkernel32.NewProc("GlobalUnlock")
|
||||||
|
procMoveMemory = modkernel32.NewProc("RtlMoveMemory")
|
||||||
|
procFindResource = modkernel32.NewProc("FindResourceW")
|
||||||
|
procSizeofResource = modkernel32.NewProc("SizeofResource")
|
||||||
|
procLockResource = modkernel32.NewProc("LockResource")
|
||||||
|
procLoadResource = modkernel32.NewProc("LoadResource")
|
||||||
|
procGetLastError = modkernel32.NewProc("GetLastError")
|
||||||
|
// procOpenProcess = modkernel32.NewProc("OpenProcess")
|
||||||
|
// procTerminateProcess = modkernel32.NewProc("TerminateProcess")
|
||||||
|
procCloseHandle = modkernel32.NewProc("CloseHandle")
|
||||||
|
procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot")
|
||||||
|
procModule32First = modkernel32.NewProc("Module32FirstW")
|
||||||
|
procModule32Next = modkernel32.NewProc("Module32NextW")
|
||||||
|
procGetSystemTimes = modkernel32.NewProc("GetSystemTimes")
|
||||||
|
procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo")
|
||||||
|
procSetConsoleTextAttribute = modkernel32.NewProc("SetConsoleTextAttribute")
|
||||||
|
procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW")
|
||||||
|
procGetProcessTimes = modkernel32.NewProc("GetProcessTimes")
|
||||||
|
procSetSystemTime = modkernel32.NewProc("SetSystemTime")
|
||||||
|
procGetSystemTime = modkernel32.NewProc("GetSystemTime")
|
||||||
|
procVirtualAllocEx = modkernel32.NewProc("VirtualAllocEx")
|
||||||
|
procVirtualFreeEx = modkernel32.NewProc("VirtualFreeEx")
|
||||||
|
procWriteProcessMemory = modkernel32.NewProc("WriteProcessMemory")
|
||||||
|
procReadProcessMemory = modkernel32.NewProc("ReadProcessMemory")
|
||||||
|
procQueryPerformanceCounter = modkernel32.NewProc("QueryPerformanceCounter")
|
||||||
|
procQueryPerformanceFrequency = modkernel32.NewProc("QueryPerformanceFrequency")
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetModuleHandle(modulename string) HINSTANCE {
|
||||||
|
var mn uintptr
|
||||||
|
if modulename == "" {
|
||||||
|
mn = 0
|
||||||
|
} else {
|
||||||
|
mn = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(modulename)))
|
||||||
|
}
|
||||||
|
ret, _, _ := procGetModuleHandle.Call(mn)
|
||||||
|
return HINSTANCE(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MulDiv(number, numerator, denominator int) int {
|
||||||
|
ret, _, _ := procMulDiv.Call(
|
||||||
|
uintptr(number),
|
||||||
|
uintptr(numerator),
|
||||||
|
uintptr(denominator))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConsoleWindow() HWND {
|
||||||
|
ret, _, _ := procGetConsoleWindow.Call()
|
||||||
|
|
||||||
|
return HWND(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCurrentThread() HANDLE {
|
||||||
|
ret, _, _ := procGetCurrentThread.Call()
|
||||||
|
|
||||||
|
return HANDLE(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLogicalDrives() uint32 {
|
||||||
|
ret, _, _ := procGetLogicalDrives.Call()
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUserDefaultLCID() uint32 {
|
||||||
|
ret, _, _ := procGetUserDefaultLCID.Call()
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Lstrlen(lpString *uint16) int {
|
||||||
|
ret, _, _ := procLstrlen.Call(uintptr(unsafe.Pointer(lpString)))
|
||||||
|
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Lstrcpy(buf []uint16, lpString *uint16) {
|
||||||
|
procLstrcpy.Call(
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
|
uintptr(unsafe.Pointer(lpString)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GlobalAlloc(uFlags uint, dwBytes uint32) HGLOBAL {
|
||||||
|
ret, _, _ := procGlobalAlloc.Call(
|
||||||
|
uintptr(uFlags),
|
||||||
|
uintptr(dwBytes))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("GlobalAlloc failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return HGLOBAL(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GlobalFree(hMem HGLOBAL) {
|
||||||
|
ret, _, _ := procGlobalFree.Call(uintptr(hMem))
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
panic("GlobalFree failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GlobalLock(hMem HGLOBAL) unsafe.Pointer {
|
||||||
|
ret, _, _ := procGlobalLock.Call(uintptr(hMem))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("GlobalLock failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return unsafe.Pointer(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GlobalUnlock(hMem HGLOBAL) bool {
|
||||||
|
ret, _, _ := procGlobalUnlock.Call(uintptr(hMem))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func MoveMemory(destination, source unsafe.Pointer, length uint32) {
|
||||||
|
procMoveMemory.Call(
|
||||||
|
uintptr(unsafe.Pointer(destination)),
|
||||||
|
uintptr(source),
|
||||||
|
uintptr(length))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindResource(hModule HMODULE, lpName, lpType *uint16) (HRSRC, error) {
|
||||||
|
ret, _, _ := procFindResource.Call(
|
||||||
|
uintptr(hModule),
|
||||||
|
uintptr(unsafe.Pointer(lpName)),
|
||||||
|
uintptr(unsafe.Pointer(lpType)))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
return 0, syscall.GetLastError()
|
||||||
|
}
|
||||||
|
|
||||||
|
return HRSRC(ret), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SizeofResource(hModule HMODULE, hResInfo HRSRC) uint32 {
|
||||||
|
ret, _, _ := procSizeofResource.Call(
|
||||||
|
uintptr(hModule),
|
||||||
|
uintptr(hResInfo))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("SizeofResource failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LockResource(hResData HGLOBAL) unsafe.Pointer {
|
||||||
|
ret, _, _ := procLockResource.Call(uintptr(hResData))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("LockResource failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return unsafe.Pointer(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadResource(hModule HMODULE, hResInfo HRSRC) HGLOBAL {
|
||||||
|
ret, _, _ := procLoadResource.Call(
|
||||||
|
uintptr(hModule),
|
||||||
|
uintptr(hResInfo))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("LoadResource failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return HGLOBAL(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLastError() uint32 {
|
||||||
|
ret, _, _ := procGetLastError.Call()
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) HANDLE {
|
||||||
|
// inherit := 0
|
||||||
|
// if inheritHandle {
|
||||||
|
// inherit = 1
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ret, _, _ := procOpenProcess.Call(
|
||||||
|
// uintptr(desiredAccess),
|
||||||
|
// uintptr(inherit),
|
||||||
|
// uintptr(processId))
|
||||||
|
// return HANDLE(ret)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func TerminateProcess(hProcess HANDLE, uExitCode uint) bool {
|
||||||
|
// ret, _, _ := procTerminateProcess.Call(
|
||||||
|
// uintptr(hProcess),
|
||||||
|
// uintptr(uExitCode))
|
||||||
|
// return ret != 0
|
||||||
|
// }
|
||||||
|
|
||||||
|
func CloseHandle(object HANDLE) bool {
|
||||||
|
ret, _, _ := procCloseHandle.Call(
|
||||||
|
uintptr(object))
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateToolhelp32Snapshot(flags, processId uint32) HANDLE {
|
||||||
|
ret, _, _ := procCreateToolhelp32Snapshot.Call(
|
||||||
|
uintptr(flags),
|
||||||
|
uintptr(processId))
|
||||||
|
|
||||||
|
if ret <= 0 {
|
||||||
|
return HANDLE(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return HANDLE(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Module32First(snapshot HANDLE, me *MODULEENTRY32) bool {
|
||||||
|
ret, _, _ := procModule32First.Call(
|
||||||
|
uintptr(snapshot),
|
||||||
|
uintptr(unsafe.Pointer(me)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Module32Next(snapshot HANDLE, me *MODULEENTRY32) bool {
|
||||||
|
ret, _, _ := procModule32Next.Call(
|
||||||
|
uintptr(snapshot),
|
||||||
|
uintptr(unsafe.Pointer(me)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSystemTimes(lpIdleTime, lpKernelTime, lpUserTime *FILETIME) bool {
|
||||||
|
ret, _, _ := procGetSystemTimes.Call(
|
||||||
|
uintptr(unsafe.Pointer(lpIdleTime)),
|
||||||
|
uintptr(unsafe.Pointer(lpKernelTime)),
|
||||||
|
uintptr(unsafe.Pointer(lpUserTime)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProcessTimes(hProcess HANDLE, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime *FILETIME) bool {
|
||||||
|
ret, _, _ := procGetProcessTimes.Call(
|
||||||
|
uintptr(hProcess),
|
||||||
|
uintptr(unsafe.Pointer(lpCreationTime)),
|
||||||
|
uintptr(unsafe.Pointer(lpExitTime)),
|
||||||
|
uintptr(unsafe.Pointer(lpKernelTime)),
|
||||||
|
uintptr(unsafe.Pointer(lpUserTime)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConsoleScreenBufferInfo(hConsoleOutput HANDLE) *CONSOLE_SCREEN_BUFFER_INFO {
|
||||||
|
var csbi CONSOLE_SCREEN_BUFFER_INFO
|
||||||
|
ret, _, _ := procGetConsoleScreenBufferInfo.Call(
|
||||||
|
uintptr(hConsoleOutput),
|
||||||
|
uintptr(unsafe.Pointer(&csbi)))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &csbi
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetConsoleTextAttribute(hConsoleOutput HANDLE, wAttributes uint16) bool {
|
||||||
|
ret, _, _ := procSetConsoleTextAttribute.Call(
|
||||||
|
uintptr(hConsoleOutput),
|
||||||
|
uintptr(wAttributes))
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDiskFreeSpaceEx(dirName string) (r bool,
|
||||||
|
freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes uint64) {
|
||||||
|
ret, _, _ := procGetDiskFreeSpaceEx.Call(
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(dirName))),
|
||||||
|
uintptr(unsafe.Pointer(&freeBytesAvailable)),
|
||||||
|
uintptr(unsafe.Pointer(&totalNumberOfBytes)),
|
||||||
|
uintptr(unsafe.Pointer(&totalNumberOfFreeBytes)))
|
||||||
|
return ret != 0,
|
||||||
|
freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSystemTime() *SYSTEMTIME {
|
||||||
|
var time SYSTEMTIME
|
||||||
|
procGetSystemTime.Call(
|
||||||
|
uintptr(unsafe.Pointer(&time)))
|
||||||
|
return &time
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetSystemTime(time *SYSTEMTIME) bool {
|
||||||
|
ret, _, _ := procSetSystemTime.Call(
|
||||||
|
uintptr(unsafe.Pointer(time)))
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func VirtualAllocEx(hProcess HANDLE, lpAddress, dwSize uintptr, flAllocationType, flProtect uint32) uintptr {
|
||||||
|
ret, _, _ := procVirtualAllocEx.Call(
|
||||||
|
uintptr(hProcess),
|
||||||
|
lpAddress,
|
||||||
|
dwSize,
|
||||||
|
uintptr(flAllocationType),
|
||||||
|
uintptr(flProtect),
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func VirtualFreeEx(hProcess HANDLE, lpAddress, dwSize uintptr, dwFreeType uint32) bool {
|
||||||
|
ret, _, _ := procVirtualFreeEx.Call(
|
||||||
|
uintptr(hProcess),
|
||||||
|
lpAddress,
|
||||||
|
dwSize,
|
||||||
|
uintptr(dwFreeType),
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteProcessMemory(hProcess HANDLE, lpBaseAddress, lpBuffer, nSize uintptr) (int, bool) {
|
||||||
|
var nBytesWritten int
|
||||||
|
ret, _, _ := procWriteProcessMemory.Call(
|
||||||
|
uintptr(hProcess),
|
||||||
|
lpBaseAddress,
|
||||||
|
lpBuffer,
|
||||||
|
nSize,
|
||||||
|
uintptr(unsafe.Pointer(&nBytesWritten)),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nBytesWritten, ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadProcessMemory(hProcess HANDLE, lpBaseAddress, nSize uintptr) (lpBuffer []uint16, lpNumberOfBytesRead int, ok bool) {
|
||||||
|
|
||||||
|
var nBytesRead int
|
||||||
|
buf := make([]uint16, nSize)
|
||||||
|
ret, _, _ := procReadProcessMemory.Call(
|
||||||
|
uintptr(hProcess),
|
||||||
|
lpBaseAddress,
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
|
nSize,
|
||||||
|
uintptr(unsafe.Pointer(&nBytesRead)),
|
||||||
|
)
|
||||||
|
|
||||||
|
return buf, nBytesRead, ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func QueryPerformanceCounter() uint64 {
|
||||||
|
result := uint64(0)
|
||||||
|
procQueryPerformanceCounter.Call(
|
||||||
|
uintptr(unsafe.Pointer(&result)),
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func QueryPerformanceFrequency() uint64 {
|
||||||
|
result := uint64(0)
|
||||||
|
procQueryPerformanceFrequency.Call(
|
||||||
|
uintptr(unsafe.Pointer(&result)),
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
63
vendor/github.com/apenwarr/w32/ole32.go
generated
vendored
Normal file
63
vendor/github.com/apenwarr/w32/ole32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modole32 = syscall.NewLazyDLL("ole32.dll")
|
||||||
|
|
||||||
|
procCoInitializeEx = modole32.NewProc("CoInitializeEx")
|
||||||
|
procCoInitialize = modole32.NewProc("CoInitialize")
|
||||||
|
procCoUninitialize = modole32.NewProc("CoUninitialize")
|
||||||
|
procCreateStreamOnHGlobal = modole32.NewProc("CreateStreamOnHGlobal")
|
||||||
|
)
|
||||||
|
|
||||||
|
func CoInitializeEx(coInit uintptr) HRESULT {
|
||||||
|
ret, _, _ := procCoInitializeEx.Call(
|
||||||
|
0,
|
||||||
|
coInit)
|
||||||
|
|
||||||
|
switch uint32(ret) {
|
||||||
|
case E_INVALIDARG:
|
||||||
|
panic("CoInitializeEx failed with E_INVALIDARG")
|
||||||
|
case E_OUTOFMEMORY:
|
||||||
|
panic("CoInitializeEx failed with E_OUTOFMEMORY")
|
||||||
|
case E_UNEXPECTED:
|
||||||
|
panic("CoInitializeEx failed with E_UNEXPECTED")
|
||||||
|
}
|
||||||
|
|
||||||
|
return HRESULT(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CoInitialize() {
|
||||||
|
procCoInitialize.Call(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CoUninitialize() {
|
||||||
|
procCoUninitialize.Call()
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateStreamOnHGlobal(hGlobal HGLOBAL, fDeleteOnRelease bool) *IStream {
|
||||||
|
stream := new(IStream)
|
||||||
|
ret, _, _ := procCreateStreamOnHGlobal.Call(
|
||||||
|
uintptr(hGlobal),
|
||||||
|
uintptr(BoolToBOOL(fDeleteOnRelease)),
|
||||||
|
uintptr(unsafe.Pointer(&stream)))
|
||||||
|
|
||||||
|
switch uint32(ret) {
|
||||||
|
case E_INVALIDARG:
|
||||||
|
panic("CreateStreamOnHGlobal failed with E_INVALIDARG")
|
||||||
|
case E_OUTOFMEMORY:
|
||||||
|
panic("CreateStreamOnHGlobal failed with E_OUTOFMEMORY")
|
||||||
|
case E_UNEXPECTED:
|
||||||
|
panic("CreateStreamOnHGlobal failed with E_UNEXPECTED")
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream
|
||||||
|
}
|
||||||
48
vendor/github.com/apenwarr/w32/oleaut32.go
generated
vendored
Normal file
48
vendor/github.com/apenwarr/w32/oleaut32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modoleaut32 = syscall.NewLazyDLL("oleaut32")
|
||||||
|
|
||||||
|
procVariantInit = modoleaut32.NewProc("VariantInit")
|
||||||
|
procSysAllocString = modoleaut32.NewProc("SysAllocString")
|
||||||
|
procSysFreeString = modoleaut32.NewProc("SysFreeString")
|
||||||
|
procSysStringLen = modoleaut32.NewProc("SysStringLen")
|
||||||
|
procCreateDispTypeInfo = modoleaut32.NewProc("CreateDispTypeInfo")
|
||||||
|
procCreateStdDispatch = modoleaut32.NewProc("CreateStdDispatch")
|
||||||
|
)
|
||||||
|
|
||||||
|
func VariantInit(v *VARIANT) {
|
||||||
|
hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v)))
|
||||||
|
if hr != 0 {
|
||||||
|
panic("Invoke VariantInit error.")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SysAllocString(v string) (ss *int16) {
|
||||||
|
pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v))))
|
||||||
|
ss = (*int16)(unsafe.Pointer(pss))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SysFreeString(v *int16) {
|
||||||
|
hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v)))
|
||||||
|
if hr != 0 {
|
||||||
|
panic("Invoke SysFreeString error.")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SysStringLen(v *int16) uint {
|
||||||
|
l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v)))
|
||||||
|
return uint(l)
|
||||||
|
}
|
||||||
72
vendor/github.com/apenwarr/w32/opengl32.go
generated
vendored
Normal file
72
vendor/github.com/apenwarr/w32/opengl32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modopengl32 = syscall.NewLazyDLL("opengl32.dll")
|
||||||
|
|
||||||
|
procwglCreateContext = modopengl32.NewProc("wglCreateContext")
|
||||||
|
procwglCreateLayerContext = modopengl32.NewProc("wglCreateLayerContext")
|
||||||
|
procwglDeleteContext = modopengl32.NewProc("wglDeleteContext")
|
||||||
|
procwglGetProcAddress = modopengl32.NewProc("wglGetProcAddress")
|
||||||
|
procwglMakeCurrent = modopengl32.NewProc("wglMakeCurrent")
|
||||||
|
procwglShareLists = modopengl32.NewProc("wglShareLists")
|
||||||
|
)
|
||||||
|
|
||||||
|
func WglCreateContext(hdc HDC) HGLRC {
|
||||||
|
ret, _, _ := procwglCreateContext.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
)
|
||||||
|
|
||||||
|
return HGLRC(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WglCreateLayerContext(hdc HDC, iLayerPlane int) HGLRC {
|
||||||
|
ret, _, _ := procwglCreateLayerContext.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(iLayerPlane),
|
||||||
|
)
|
||||||
|
|
||||||
|
return HGLRC(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WglDeleteContext(hglrc HGLRC) bool {
|
||||||
|
ret, _, _ := procwglDeleteContext.Call(
|
||||||
|
uintptr(hglrc),
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret == TRUE
|
||||||
|
}
|
||||||
|
|
||||||
|
func WglGetProcAddress(szProc string) uintptr {
|
||||||
|
ret, _, _ := procwglGetProcAddress.Call(
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringBytePtr(szProc))),
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func WglMakeCurrent(hdc HDC, hglrc HGLRC) bool {
|
||||||
|
ret, _, _ := procwglMakeCurrent.Call(
|
||||||
|
uintptr(hdc),
|
||||||
|
uintptr(hglrc),
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret == TRUE
|
||||||
|
}
|
||||||
|
|
||||||
|
func WglShareLists(hglrc1, hglrc2 HGLRC) bool {
|
||||||
|
ret, _, _ := procwglShareLists.Call(
|
||||||
|
uintptr(hglrc1),
|
||||||
|
uintptr(hglrc2),
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret == TRUE
|
||||||
|
}
|
||||||
25
vendor/github.com/apenwarr/w32/psapi.go
generated
vendored
Normal file
25
vendor/github.com/apenwarr/w32/psapi.go
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modpsapi = syscall.NewLazyDLL("psapi.dll")
|
||||||
|
|
||||||
|
procEnumProcesses = modpsapi.NewProc("EnumProcesses")
|
||||||
|
)
|
||||||
|
|
||||||
|
func EnumProcesses(processIds []uint32, cb uint32, bytesReturned *uint32) bool {
|
||||||
|
ret, _, _ := procEnumProcesses.Call(
|
||||||
|
uintptr(unsafe.Pointer(&processIds[0])),
|
||||||
|
uintptr(cb),
|
||||||
|
uintptr(unsafe.Pointer(bytesReturned)))
|
||||||
|
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
153
vendor/github.com/apenwarr/w32/shell32.go
generated
vendored
Normal file
153
vendor/github.com/apenwarr/w32/shell32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modshell32 = syscall.NewLazyDLL("shell32.dll")
|
||||||
|
|
||||||
|
procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolderW")
|
||||||
|
procSHGetPathFromIDList = modshell32.NewProc("SHGetPathFromIDListW")
|
||||||
|
procDragAcceptFiles = modshell32.NewProc("DragAcceptFiles")
|
||||||
|
procDragQueryFile = modshell32.NewProc("DragQueryFileW")
|
||||||
|
procDragQueryPoint = modshell32.NewProc("DragQueryPoint")
|
||||||
|
procDragFinish = modshell32.NewProc("DragFinish")
|
||||||
|
procShellExecute = modshell32.NewProc("ShellExecuteW")
|
||||||
|
procExtractIcon = modshell32.NewProc("ExtractIconW")
|
||||||
|
)
|
||||||
|
|
||||||
|
func SHBrowseForFolder(bi *BROWSEINFO) uintptr {
|
||||||
|
ret, _, _ := procSHBrowseForFolder.Call(uintptr(unsafe.Pointer(bi)))
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func SHGetPathFromIDList(idl uintptr) string {
|
||||||
|
buf := make([]uint16, 1024)
|
||||||
|
procSHGetPathFromIDList.Call(
|
||||||
|
idl,
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])))
|
||||||
|
|
||||||
|
return syscall.UTF16ToString(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DragAcceptFiles(hwnd HWND, accept bool) {
|
||||||
|
procDragAcceptFiles.Call(
|
||||||
|
uintptr(hwnd),
|
||||||
|
uintptr(BoolToBOOL(accept)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func DragQueryFile(hDrop HDROP, iFile uint) (fileName string, fileCount uint) {
|
||||||
|
ret, _, _ := procDragQueryFile.Call(
|
||||||
|
uintptr(hDrop),
|
||||||
|
uintptr(iFile),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
|
||||||
|
fileCount = uint(ret)
|
||||||
|
|
||||||
|
if iFile != 0xFFFFFFFF {
|
||||||
|
buf := make([]uint16, fileCount+1)
|
||||||
|
|
||||||
|
ret, _, _ := procDragQueryFile.Call(
|
||||||
|
uintptr(hDrop),
|
||||||
|
uintptr(iFile),
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
|
uintptr(fileCount+1))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
panic("Invoke DragQueryFile error.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName = syscall.UTF16ToString(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func DragQueryPoint(hDrop HDROP) (x, y int, isClientArea bool) {
|
||||||
|
var pt POINT
|
||||||
|
ret, _, _ := procDragQueryPoint.Call(
|
||||||
|
uintptr(hDrop),
|
||||||
|
uintptr(unsafe.Pointer(&pt)))
|
||||||
|
|
||||||
|
return int(pt.X), int(pt.Y), (ret == 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DragFinish(hDrop HDROP) {
|
||||||
|
procDragFinish.Call(uintptr(hDrop))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ShellExecute(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
|
||||||
|
var op, param, directory uintptr
|
||||||
|
if len(lpOperation) != 0 {
|
||||||
|
op = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
|
||||||
|
}
|
||||||
|
if len(lpParameters) != 0 {
|
||||||
|
param = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
|
||||||
|
}
|
||||||
|
if len(lpDirectory) != 0 {
|
||||||
|
directory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, _ := procShellExecute.Call(
|
||||||
|
uintptr(hwnd),
|
||||||
|
op,
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
|
||||||
|
param,
|
||||||
|
directory,
|
||||||
|
uintptr(nShowCmd))
|
||||||
|
|
||||||
|
errorMsg := ""
|
||||||
|
if ret != 0 && ret <= 32 {
|
||||||
|
switch int(ret) {
|
||||||
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
errorMsg = "The specified file was not found."
|
||||||
|
case ERROR_PATH_NOT_FOUND:
|
||||||
|
errorMsg = "The specified path was not found."
|
||||||
|
case ERROR_BAD_FORMAT:
|
||||||
|
errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)."
|
||||||
|
case SE_ERR_ACCESSDENIED:
|
||||||
|
errorMsg = "The operating system denied access to the specified file."
|
||||||
|
case SE_ERR_ASSOCINCOMPLETE:
|
||||||
|
errorMsg = "The file name association is incomplete or invalid."
|
||||||
|
case SE_ERR_DDEBUSY:
|
||||||
|
errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed."
|
||||||
|
case SE_ERR_DDEFAIL:
|
||||||
|
errorMsg = "The DDE transaction failed."
|
||||||
|
case SE_ERR_DDETIMEOUT:
|
||||||
|
errorMsg = "The DDE transaction could not be completed because the request timed out."
|
||||||
|
case SE_ERR_DLLNOTFOUND:
|
||||||
|
errorMsg = "The specified DLL was not found."
|
||||||
|
case SE_ERR_NOASSOC:
|
||||||
|
errorMsg = "There is no application associated with the given file name extension. This error will also be returned if you attempt to print a file that is not printable."
|
||||||
|
case SE_ERR_OOM:
|
||||||
|
errorMsg = "There was not enough memory to complete the operation."
|
||||||
|
case SE_ERR_SHARE:
|
||||||
|
errorMsg = "A sharing violation occurred."
|
||||||
|
default:
|
||||||
|
errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", ret)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New(errorMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtractIcon(lpszExeFileName string, nIconIndex int) HICON {
|
||||||
|
ret, _, _ := procExtractIcon.Call(
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpszExeFileName))),
|
||||||
|
uintptr(nIconIndex))
|
||||||
|
|
||||||
|
return HICON(ret)
|
||||||
|
}
|
||||||
891
vendor/github.com/apenwarr/w32/typedef.go
generated
vendored
Normal file
891
vendor/github.com/apenwarr/w32/typedef.go
generated
vendored
Normal file
|
|
@ -0,0 +1,891 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// From MSDN: Windows Data Types
|
||||||
|
// http://msdn.microsoft.com/en-us/library/s3f49ktz.aspx
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751.aspx
|
||||||
|
// ATOM WORD
|
||||||
|
// BOOL int32
|
||||||
|
// BOOLEAN byte
|
||||||
|
// BYTE byte
|
||||||
|
// CCHAR int8
|
||||||
|
// CHAR int8
|
||||||
|
// COLORREF DWORD
|
||||||
|
// DWORD uint32
|
||||||
|
// DWORDLONG ULONGLONG
|
||||||
|
// DWORD_PTR ULONG_PTR
|
||||||
|
// DWORD32 uint32
|
||||||
|
// DWORD64 uint64
|
||||||
|
// FLOAT float32
|
||||||
|
// HACCEL HANDLE
|
||||||
|
// HALF_PTR struct{} // ???
|
||||||
|
// HANDLE PVOID
|
||||||
|
// HBITMAP HANDLE
|
||||||
|
// HBRUSH HANDLE
|
||||||
|
// HCOLORSPACE HANDLE
|
||||||
|
// HCONV HANDLE
|
||||||
|
// HCONVLIST HANDLE
|
||||||
|
// HCURSOR HANDLE
|
||||||
|
// HDC HANDLE
|
||||||
|
// HDDEDATA HANDLE
|
||||||
|
// HDESK HANDLE
|
||||||
|
// HDROP HANDLE
|
||||||
|
// HDWP HANDLE
|
||||||
|
// HENHMETAFILE HANDLE
|
||||||
|
// HFILE HANDLE
|
||||||
|
// HFONT HANDLE
|
||||||
|
// HGDIOBJ HANDLE
|
||||||
|
// HGLOBAL HANDLE
|
||||||
|
// HHOOK HANDLE
|
||||||
|
// HICON HANDLE
|
||||||
|
// HINSTANCE HANDLE
|
||||||
|
// HKEY HANDLE
|
||||||
|
// HKL HANDLE
|
||||||
|
// HLOCAL HANDLE
|
||||||
|
// HMENU HANDLE
|
||||||
|
// HMETAFILE HANDLE
|
||||||
|
// HMODULE HANDLE
|
||||||
|
// HPALETTE HANDLE
|
||||||
|
// HPEN HANDLE
|
||||||
|
// HRESULT int32
|
||||||
|
// HRGN HANDLE
|
||||||
|
// HSZ HANDLE
|
||||||
|
// HWINSTA HANDLE
|
||||||
|
// HWND HANDLE
|
||||||
|
// INT int32
|
||||||
|
// INT_PTR uintptr
|
||||||
|
// INT8 int8
|
||||||
|
// INT16 int16
|
||||||
|
// INT32 int32
|
||||||
|
// INT64 int64
|
||||||
|
// LANGID WORD
|
||||||
|
// LCID DWORD
|
||||||
|
// LCTYPE DWORD
|
||||||
|
// LGRPID DWORD
|
||||||
|
// LONG int32
|
||||||
|
// LONGLONG int64
|
||||||
|
// LONG_PTR uintptr
|
||||||
|
// LONG32 int32
|
||||||
|
// LONG64 int64
|
||||||
|
// LPARAM LONG_PTR
|
||||||
|
// LPBOOL *BOOL
|
||||||
|
// LPBYTE *BYTE
|
||||||
|
// LPCOLORREF *COLORREF
|
||||||
|
// LPCSTR *int8
|
||||||
|
// LPCTSTR LPCWSTR
|
||||||
|
// LPCVOID unsafe.Pointer
|
||||||
|
// LPCWSTR *WCHAR
|
||||||
|
// LPDWORD *DWORD
|
||||||
|
// LPHANDLE *HANDLE
|
||||||
|
// LPINT *INT
|
||||||
|
// LPLONG *LONG
|
||||||
|
// LPSTR *CHAR
|
||||||
|
// LPTSTR LPWSTR
|
||||||
|
// LPVOID unsafe.Pointer
|
||||||
|
// LPWORD *WORD
|
||||||
|
// LPWSTR *WCHAR
|
||||||
|
// LRESULT LONG_PTR
|
||||||
|
// PBOOL *BOOL
|
||||||
|
// PBOOLEAN *BOOLEAN
|
||||||
|
// PBYTE *BYTE
|
||||||
|
// PCHAR *CHAR
|
||||||
|
// PCSTR *CHAR
|
||||||
|
// PCTSTR PCWSTR
|
||||||
|
// PCWSTR *WCHAR
|
||||||
|
// PDWORD *DWORD
|
||||||
|
// PDWORDLONG *DWORDLONG
|
||||||
|
// PDWORD_PTR *DWORD_PTR
|
||||||
|
// PDWORD32 *DWORD32
|
||||||
|
// PDWORD64 *DWORD64
|
||||||
|
// PFLOAT *FLOAT
|
||||||
|
// PHALF_PTR *HALF_PTR
|
||||||
|
// PHANDLE *HANDLE
|
||||||
|
// PHKEY *HKEY
|
||||||
|
// PINT_PTR *INT_PTR
|
||||||
|
// PINT8 *INT8
|
||||||
|
// PINT16 *INT16
|
||||||
|
// PINT32 *INT32
|
||||||
|
// PINT64 *INT64
|
||||||
|
// PLCID *LCID
|
||||||
|
// PLONG *LONG
|
||||||
|
// PLONGLONG *LONGLONG
|
||||||
|
// PLONG_PTR *LONG_PTR
|
||||||
|
// PLONG32 *LONG32
|
||||||
|
// PLONG64 *LONG64
|
||||||
|
// POINTER_32 struct{} // ???
|
||||||
|
// POINTER_64 struct{} // ???
|
||||||
|
// POINTER_SIGNED uintptr
|
||||||
|
// POINTER_UNSIGNED uintptr
|
||||||
|
// PSHORT *SHORT
|
||||||
|
// PSIZE_T *SIZE_T
|
||||||
|
// PSSIZE_T *SSIZE_T
|
||||||
|
// PSTR *CHAR
|
||||||
|
// PTBYTE *TBYTE
|
||||||
|
// PTCHAR *TCHAR
|
||||||
|
// PTSTR PWSTR
|
||||||
|
// PUCHAR *UCHAR
|
||||||
|
// PUHALF_PTR *UHALF_PTR
|
||||||
|
// PUINT *UINT
|
||||||
|
// PUINT_PTR *UINT_PTR
|
||||||
|
// PUINT8 *UINT8
|
||||||
|
// PUINT16 *UINT16
|
||||||
|
// PUINT32 *UINT32
|
||||||
|
// PUINT64 *UINT64
|
||||||
|
// PULONG *ULONG
|
||||||
|
// PULONGLONG *ULONGLONG
|
||||||
|
// PULONG_PTR *ULONG_PTR
|
||||||
|
// PULONG32 *ULONG32
|
||||||
|
// PULONG64 *ULONG64
|
||||||
|
// PUSHORT *USHORT
|
||||||
|
// PVOID unsafe.Pointer
|
||||||
|
// PWCHAR *WCHAR
|
||||||
|
// PWORD *WORD
|
||||||
|
// PWSTR *WCHAR
|
||||||
|
// QWORD uint64
|
||||||
|
// SC_HANDLE HANDLE
|
||||||
|
// SC_LOCK LPVOID
|
||||||
|
// SERVICE_STATUS_HANDLE HANDLE
|
||||||
|
// SHORT int16
|
||||||
|
// SIZE_T ULONG_PTR
|
||||||
|
// SSIZE_T LONG_PTR
|
||||||
|
// TBYTE WCHAR
|
||||||
|
// TCHAR WCHAR
|
||||||
|
// UCHAR uint8
|
||||||
|
// UHALF_PTR struct{} // ???
|
||||||
|
// UINT uint32
|
||||||
|
// UINT_PTR uintptr
|
||||||
|
// UINT8 uint8
|
||||||
|
// UINT16 uint16
|
||||||
|
// UINT32 uint32
|
||||||
|
// UINT64 uint64
|
||||||
|
// ULONG uint32
|
||||||
|
// ULONGLONG uint64
|
||||||
|
// ULONG_PTR uintptr
|
||||||
|
// ULONG32 uint32
|
||||||
|
// ULONG64 uint64
|
||||||
|
// USHORT uint16
|
||||||
|
// USN LONGLONG
|
||||||
|
// WCHAR uint16
|
||||||
|
// WORD uint16
|
||||||
|
// WPARAM UINT_PTR
|
||||||
|
type (
|
||||||
|
ATOM uint16
|
||||||
|
BOOL int32
|
||||||
|
COLORREF uint32
|
||||||
|
DWM_FRAME_COUNT uint64
|
||||||
|
DWORD uint32
|
||||||
|
HACCEL HANDLE
|
||||||
|
HANDLE uintptr
|
||||||
|
HBITMAP HANDLE
|
||||||
|
HBRUSH HANDLE
|
||||||
|
HCURSOR HANDLE
|
||||||
|
HDC HANDLE
|
||||||
|
HDROP HANDLE
|
||||||
|
HDWP HANDLE
|
||||||
|
HENHMETAFILE HANDLE
|
||||||
|
HFONT HANDLE
|
||||||
|
HGDIOBJ HANDLE
|
||||||
|
HGLOBAL HANDLE
|
||||||
|
HGLRC HANDLE
|
||||||
|
HHOOK HANDLE
|
||||||
|
HICON HANDLE
|
||||||
|
HIMAGELIST HANDLE
|
||||||
|
HINSTANCE HANDLE
|
||||||
|
HKEY HANDLE
|
||||||
|
HKL HANDLE
|
||||||
|
HMENU HANDLE
|
||||||
|
HMODULE HANDLE
|
||||||
|
HMONITOR HANDLE
|
||||||
|
HPEN HANDLE
|
||||||
|
HRESULT int32
|
||||||
|
HRGN HANDLE
|
||||||
|
HRSRC HANDLE
|
||||||
|
HTHUMBNAIL HANDLE
|
||||||
|
HWND HANDLE
|
||||||
|
LPARAM uintptr
|
||||||
|
LPCVOID unsafe.Pointer
|
||||||
|
LRESULT uintptr
|
||||||
|
PVOID unsafe.Pointer
|
||||||
|
QPC_TIME uint64
|
||||||
|
ULONG_PTR uintptr
|
||||||
|
WPARAM uintptr
|
||||||
|
TRACEHANDLE uintptr
|
||||||
|
)
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162805.aspx
|
||||||
|
type POINT struct {
|
||||||
|
X, Y int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897.aspx
|
||||||
|
type RECT struct {
|
||||||
|
Left, Top, Right, Bottom int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms633577.aspx
|
||||||
|
type WNDCLASSEX struct {
|
||||||
|
Size uint32
|
||||||
|
Style uint32
|
||||||
|
WndProc uintptr
|
||||||
|
ClsExtra int32
|
||||||
|
WndExtra int32
|
||||||
|
Instance HINSTANCE
|
||||||
|
Icon HICON
|
||||||
|
Cursor HCURSOR
|
||||||
|
Background HBRUSH
|
||||||
|
MenuName *uint16
|
||||||
|
ClassName *uint16
|
||||||
|
IconSm HICON
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644958.aspx
|
||||||
|
type MSG struct {
|
||||||
|
Hwnd HWND
|
||||||
|
Message uint32
|
||||||
|
WParam uintptr
|
||||||
|
LParam uintptr
|
||||||
|
Time uint32
|
||||||
|
Pt POINT
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145037.aspx
|
||||||
|
type LOGFONT struct {
|
||||||
|
Height int32
|
||||||
|
Width int32
|
||||||
|
Escapement int32
|
||||||
|
Orientation int32
|
||||||
|
Weight int32
|
||||||
|
Italic byte
|
||||||
|
Underline byte
|
||||||
|
StrikeOut byte
|
||||||
|
CharSet byte
|
||||||
|
OutPrecision byte
|
||||||
|
ClipPrecision byte
|
||||||
|
Quality byte
|
||||||
|
PitchAndFamily byte
|
||||||
|
FaceName [LF_FACESIZE]uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839.aspx
|
||||||
|
type OPENFILENAME struct {
|
||||||
|
StructSize uint32
|
||||||
|
Owner HWND
|
||||||
|
Instance HINSTANCE
|
||||||
|
Filter *uint16
|
||||||
|
CustomFilter *uint16
|
||||||
|
MaxCustomFilter uint32
|
||||||
|
FilterIndex uint32
|
||||||
|
File *uint16
|
||||||
|
MaxFile uint32
|
||||||
|
FileTitle *uint16
|
||||||
|
MaxFileTitle uint32
|
||||||
|
InitialDir *uint16
|
||||||
|
Title *uint16
|
||||||
|
Flags uint32
|
||||||
|
FileOffset uint16
|
||||||
|
FileExtension uint16
|
||||||
|
DefExt *uint16
|
||||||
|
CustData uintptr
|
||||||
|
FnHook uintptr
|
||||||
|
TemplateName *uint16
|
||||||
|
PvReserved unsafe.Pointer
|
||||||
|
DwReserved uint32
|
||||||
|
FlagsEx uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773205.aspx
|
||||||
|
type BROWSEINFO struct {
|
||||||
|
Owner HWND
|
||||||
|
Root *uint16
|
||||||
|
DisplayName *uint16
|
||||||
|
Title *uint16
|
||||||
|
Flags uint32
|
||||||
|
CallbackFunc uintptr
|
||||||
|
LParam uintptr
|
||||||
|
Image int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373931.aspx
|
||||||
|
type GUID struct {
|
||||||
|
Data1 uint32
|
||||||
|
Data2 uint16
|
||||||
|
Data3 uint16
|
||||||
|
Data4 [8]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221627.aspx
|
||||||
|
type VARIANT struct {
|
||||||
|
VT uint16 // 2
|
||||||
|
WReserved1 uint16 // 4
|
||||||
|
WReserved2 uint16 // 6
|
||||||
|
WReserved3 uint16 // 8
|
||||||
|
Val int64 // 16
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221416.aspx
|
||||||
|
type DISPPARAMS struct {
|
||||||
|
Rgvarg uintptr
|
||||||
|
RgdispidNamedArgs uintptr
|
||||||
|
CArgs uint32
|
||||||
|
CNamedArgs uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221133.aspx
|
||||||
|
type EXCEPINFO struct {
|
||||||
|
WCode uint16
|
||||||
|
WReserved uint16
|
||||||
|
BstrSource *uint16
|
||||||
|
BstrDescription *uint16
|
||||||
|
BstrHelpFile *uint16
|
||||||
|
DwHelpContext uint32
|
||||||
|
PvReserved uintptr
|
||||||
|
PfnDeferredFillIn uintptr
|
||||||
|
Scode int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145035.aspx
|
||||||
|
type LOGBRUSH struct {
|
||||||
|
LbStyle uint32
|
||||||
|
LbColor COLORREF
|
||||||
|
LbHatch uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565.aspx
|
||||||
|
type DEVMODE struct {
|
||||||
|
DmDeviceName [CCHDEVICENAME]uint16
|
||||||
|
DmSpecVersion uint16
|
||||||
|
DmDriverVersion uint16
|
||||||
|
DmSize uint16
|
||||||
|
DmDriverExtra uint16
|
||||||
|
DmFields uint32
|
||||||
|
DmOrientation int16
|
||||||
|
DmPaperSize int16
|
||||||
|
DmPaperLength int16
|
||||||
|
DmPaperWidth int16
|
||||||
|
DmScale int16
|
||||||
|
DmCopies int16
|
||||||
|
DmDefaultSource int16
|
||||||
|
DmPrintQuality int16
|
||||||
|
DmColor int16
|
||||||
|
DmDuplex int16
|
||||||
|
DmYResolution int16
|
||||||
|
DmTTOption int16
|
||||||
|
DmCollate int16
|
||||||
|
DmFormName [CCHFORMNAME]uint16
|
||||||
|
DmLogPixels uint16
|
||||||
|
DmBitsPerPel uint32
|
||||||
|
DmPelsWidth uint32
|
||||||
|
DmPelsHeight uint32
|
||||||
|
DmDisplayFlags uint32
|
||||||
|
DmDisplayFrequency uint32
|
||||||
|
DmICMMethod uint32
|
||||||
|
DmICMIntent uint32
|
||||||
|
DmMediaType uint32
|
||||||
|
DmDitherType uint32
|
||||||
|
DmReserved1 uint32
|
||||||
|
DmReserved2 uint32
|
||||||
|
DmPanningWidth uint32
|
||||||
|
DmPanningHeight uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376.aspx
|
||||||
|
type BITMAPINFOHEADER struct {
|
||||||
|
BiSize uint32
|
||||||
|
BiWidth int32
|
||||||
|
BiHeight int32
|
||||||
|
BiPlanes uint16
|
||||||
|
BiBitCount uint16
|
||||||
|
BiCompression uint32
|
||||||
|
BiSizeImage uint32
|
||||||
|
BiXPelsPerMeter int32
|
||||||
|
BiYPelsPerMeter int32
|
||||||
|
BiClrUsed uint32
|
||||||
|
BiClrImportant uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162938.aspx
|
||||||
|
type RGBQUAD struct {
|
||||||
|
RgbBlue byte
|
||||||
|
RgbGreen byte
|
||||||
|
RgbRed byte
|
||||||
|
RgbReserved byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183375.aspx
|
||||||
|
type BITMAPINFO struct {
|
||||||
|
BmiHeader BITMAPINFOHEADER
|
||||||
|
BmiColors *RGBQUAD
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183371.aspx
|
||||||
|
type BITMAP struct {
|
||||||
|
BmType int32
|
||||||
|
BmWidth int32
|
||||||
|
BmHeight int32
|
||||||
|
BmWidthBytes int32
|
||||||
|
BmPlanes uint16
|
||||||
|
BmBitsPixel uint16
|
||||||
|
BmBits unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183567.aspx
|
||||||
|
type DIBSECTION struct {
|
||||||
|
DsBm BITMAP
|
||||||
|
DsBmih BITMAPINFOHEADER
|
||||||
|
DsBitfields [3]uint32
|
||||||
|
DshSection HANDLE
|
||||||
|
DsOffset uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162607.aspx
|
||||||
|
type ENHMETAHEADER struct {
|
||||||
|
IType uint32
|
||||||
|
NSize uint32
|
||||||
|
RclBounds RECT
|
||||||
|
RclFrame RECT
|
||||||
|
DSignature uint32
|
||||||
|
NVersion uint32
|
||||||
|
NBytes uint32
|
||||||
|
NRecords uint32
|
||||||
|
NHandles uint16
|
||||||
|
SReserved uint16
|
||||||
|
NDescription uint32
|
||||||
|
OffDescription uint32
|
||||||
|
NPalEntries uint32
|
||||||
|
SzlDevice SIZE
|
||||||
|
SzlMillimeters SIZE
|
||||||
|
CbPixelFormat uint32
|
||||||
|
OffPixelFormat uint32
|
||||||
|
BOpenGL uint32
|
||||||
|
SzlMicrometers SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145106.aspx
|
||||||
|
type SIZE struct {
|
||||||
|
CX, CY int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145132.aspx
|
||||||
|
type TEXTMETRIC struct {
|
||||||
|
TmHeight int32
|
||||||
|
TmAscent int32
|
||||||
|
TmDescent int32
|
||||||
|
TmInternalLeading int32
|
||||||
|
TmExternalLeading int32
|
||||||
|
TmAveCharWidth int32
|
||||||
|
TmMaxCharWidth int32
|
||||||
|
TmWeight int32
|
||||||
|
TmOverhang int32
|
||||||
|
TmDigitizedAspectX int32
|
||||||
|
TmDigitizedAspectY int32
|
||||||
|
TmFirstChar uint16
|
||||||
|
TmLastChar uint16
|
||||||
|
TmDefaultChar uint16
|
||||||
|
TmBreakChar uint16
|
||||||
|
TmItalic byte
|
||||||
|
TmUnderlined byte
|
||||||
|
TmStruckOut byte
|
||||||
|
TmPitchAndFamily byte
|
||||||
|
TmCharSet byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183574.aspx
|
||||||
|
type DOCINFO struct {
|
||||||
|
CbSize int32
|
||||||
|
LpszDocName *uint16
|
||||||
|
LpszOutput *uint16
|
||||||
|
LpszDatatype *uint16
|
||||||
|
FwType uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb775514.aspx
|
||||||
|
type NMHDR struct {
|
||||||
|
HwndFrom HWND
|
||||||
|
IdFrom uintptr
|
||||||
|
Code uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774743.aspx
|
||||||
|
type LVCOLUMN struct {
|
||||||
|
Mask uint32
|
||||||
|
Fmt int32
|
||||||
|
Cx int32
|
||||||
|
PszText *uint16
|
||||||
|
CchTextMax int32
|
||||||
|
ISubItem int32
|
||||||
|
IImage int32
|
||||||
|
IOrder int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774760.aspx
|
||||||
|
type LVITEM struct {
|
||||||
|
Mask uint32
|
||||||
|
IItem int32
|
||||||
|
ISubItem int32
|
||||||
|
State uint32
|
||||||
|
StateMask uint32
|
||||||
|
PszText *uint16
|
||||||
|
CchTextMax int32
|
||||||
|
IImage int32
|
||||||
|
LParam uintptr
|
||||||
|
IIndent int32
|
||||||
|
IGroupId int32
|
||||||
|
CColumns uint32
|
||||||
|
PuColumns uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774754.aspx
|
||||||
|
type LVHITTESTINFO struct {
|
||||||
|
Pt POINT
|
||||||
|
Flags uint32
|
||||||
|
IItem int32
|
||||||
|
ISubItem int32
|
||||||
|
IGroup int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774771.aspx
|
||||||
|
type NMITEMACTIVATE struct {
|
||||||
|
Hdr NMHDR
|
||||||
|
IItem int32
|
||||||
|
ISubItem int32
|
||||||
|
UNewState uint32
|
||||||
|
UOldState uint32
|
||||||
|
UChanged uint32
|
||||||
|
PtAction POINT
|
||||||
|
LParam uintptr
|
||||||
|
UKeyFlags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774773.aspx
|
||||||
|
type NMLISTVIEW struct {
|
||||||
|
Hdr NMHDR
|
||||||
|
IItem int32
|
||||||
|
ISubItem int32
|
||||||
|
UNewState uint32
|
||||||
|
UOldState uint32
|
||||||
|
UChanged uint32
|
||||||
|
PtAction POINT
|
||||||
|
LParam uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774780.aspx
|
||||||
|
type NMLVDISPINFO struct {
|
||||||
|
Hdr NMHDR
|
||||||
|
Item LVITEM
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb775507.aspx
|
||||||
|
type INITCOMMONCONTROLSEX struct {
|
||||||
|
DwSize uint32
|
||||||
|
DwICC uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb760256.aspx
|
||||||
|
type TOOLINFO struct {
|
||||||
|
CbSize uint32
|
||||||
|
UFlags uint32
|
||||||
|
Hwnd HWND
|
||||||
|
UId uintptr
|
||||||
|
Rect RECT
|
||||||
|
Hinst HINSTANCE
|
||||||
|
LpszText *uint16
|
||||||
|
LParam uintptr
|
||||||
|
LpReserved unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms645604.aspx
|
||||||
|
type TRACKMOUSEEVENT struct {
|
||||||
|
CbSize uint32
|
||||||
|
DwFlags uint32
|
||||||
|
HwndTrack HWND
|
||||||
|
DwHoverTime uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms534067.aspx
|
||||||
|
type GdiplusStartupInput struct {
|
||||||
|
GdiplusVersion uint32
|
||||||
|
DebugEventCallback uintptr
|
||||||
|
SuppressBackgroundThread BOOL
|
||||||
|
SuppressExternalCodecs BOOL
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms534068.aspx
|
||||||
|
type GdiplusStartupOutput struct {
|
||||||
|
NotificationHook uintptr
|
||||||
|
NotificationUnhook uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162768.aspx
|
||||||
|
type PAINTSTRUCT struct {
|
||||||
|
Hdc HDC
|
||||||
|
FErase BOOL
|
||||||
|
RcPaint RECT
|
||||||
|
FRestore BOOL
|
||||||
|
FIncUpdate BOOL
|
||||||
|
RgbReserved [32]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684225.aspx
|
||||||
|
type MODULEENTRY32 struct {
|
||||||
|
Size uint32
|
||||||
|
ModuleID uint32
|
||||||
|
ProcessID uint32
|
||||||
|
GlblcntUsage uint32
|
||||||
|
ProccntUsage uint32
|
||||||
|
ModBaseAddr *uint8
|
||||||
|
ModBaseSize uint32
|
||||||
|
HModule HMODULE
|
||||||
|
SzModule [MAX_MODULE_NAME32 + 1]uint16
|
||||||
|
SzExePath [MAX_PATH]uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
|
||||||
|
type FILETIME struct {
|
||||||
|
DwLowDateTime uint32
|
||||||
|
DwHighDateTime uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119.aspx
|
||||||
|
type COORD struct {
|
||||||
|
X, Y int16
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms686311.aspx
|
||||||
|
type SMALL_RECT struct {
|
||||||
|
Left, Top, Right, Bottom int16
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093.aspx
|
||||||
|
type CONSOLE_SCREEN_BUFFER_INFO struct {
|
||||||
|
DwSize COORD
|
||||||
|
DwCursorPosition COORD
|
||||||
|
WAttributes uint16
|
||||||
|
SrWindow SMALL_RECT
|
||||||
|
DwMaximumWindowSize COORD
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773244.aspx
|
||||||
|
type MARGINS struct {
|
||||||
|
CxLeftWidth, CxRightWidth, CyTopHeight, CyBottomHeight int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969500.aspx
|
||||||
|
type DWM_BLURBEHIND struct {
|
||||||
|
DwFlags uint32
|
||||||
|
fEnable BOOL
|
||||||
|
hRgnBlur HRGN
|
||||||
|
fTransitionOnMaximized BOOL
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969501.aspx
|
||||||
|
type DWM_PRESENT_PARAMETERS struct {
|
||||||
|
cbSize uint32
|
||||||
|
fQueue BOOL
|
||||||
|
cRefreshStart DWM_FRAME_COUNT
|
||||||
|
cBuffer uint32
|
||||||
|
fUseSourceRate BOOL
|
||||||
|
rateSource UNSIGNED_RATIO
|
||||||
|
cRefreshesPerFrame uint32
|
||||||
|
eSampling DWM_SOURCE_FRAME_SAMPLING
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969502.aspx
|
||||||
|
type DWM_THUMBNAIL_PROPERTIES struct {
|
||||||
|
dwFlags uint32
|
||||||
|
rcDestination RECT
|
||||||
|
rcSource RECT
|
||||||
|
opacity byte
|
||||||
|
fVisible BOOL
|
||||||
|
fSourceClientAreaOnly BOOL
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969503.aspx
|
||||||
|
type DWM_TIMING_INFO struct {
|
||||||
|
cbSize uint32
|
||||||
|
rateRefresh UNSIGNED_RATIO
|
||||||
|
qpcRefreshPeriod QPC_TIME
|
||||||
|
rateCompose UNSIGNED_RATIO
|
||||||
|
qpcVBlank QPC_TIME
|
||||||
|
cRefresh DWM_FRAME_COUNT
|
||||||
|
cDXRefresh uint32
|
||||||
|
qpcCompose QPC_TIME
|
||||||
|
cFrame DWM_FRAME_COUNT
|
||||||
|
cDXPresent uint32
|
||||||
|
cRefreshFrame DWM_FRAME_COUNT
|
||||||
|
cFrameSubmitted DWM_FRAME_COUNT
|
||||||
|
cDXPresentSubmitted uint32
|
||||||
|
cFrameConfirmed DWM_FRAME_COUNT
|
||||||
|
cDXPresentConfirmed uint32
|
||||||
|
cRefreshConfirmed DWM_FRAME_COUNT
|
||||||
|
cDXRefreshConfirmed uint32
|
||||||
|
cFramesLate DWM_FRAME_COUNT
|
||||||
|
cFramesOutstanding uint32
|
||||||
|
cFrameDisplayed DWM_FRAME_COUNT
|
||||||
|
qpcFrameDisplayed QPC_TIME
|
||||||
|
cRefreshFrameDisplayed DWM_FRAME_COUNT
|
||||||
|
cFrameComplete DWM_FRAME_COUNT
|
||||||
|
qpcFrameComplete QPC_TIME
|
||||||
|
cFramePending DWM_FRAME_COUNT
|
||||||
|
qpcFramePending QPC_TIME
|
||||||
|
cFramesDisplayed DWM_FRAME_COUNT
|
||||||
|
cFramesComplete DWM_FRAME_COUNT
|
||||||
|
cFramesPending DWM_FRAME_COUNT
|
||||||
|
cFramesAvailable DWM_FRAME_COUNT
|
||||||
|
cFramesDropped DWM_FRAME_COUNT
|
||||||
|
cFramesMissed DWM_FRAME_COUNT
|
||||||
|
cRefreshNextDisplayed DWM_FRAME_COUNT
|
||||||
|
cRefreshNextPresented DWM_FRAME_COUNT
|
||||||
|
cRefreshesDisplayed DWM_FRAME_COUNT
|
||||||
|
cRefreshesPresented DWM_FRAME_COUNT
|
||||||
|
cRefreshStarted DWM_FRAME_COUNT
|
||||||
|
cPixelsReceived uint64
|
||||||
|
cPixelsDrawn uint64
|
||||||
|
cBuffersEmpty DWM_FRAME_COUNT
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd389402.aspx
|
||||||
|
type MilMatrix3x2D struct {
|
||||||
|
S_11, S_12, S_21, S_22 float64
|
||||||
|
DX, DY float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa969505.aspx
|
||||||
|
type UNSIGNED_RATIO struct {
|
||||||
|
uiNumerator uint32
|
||||||
|
uiDenominator uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms632603.aspx
|
||||||
|
type CREATESTRUCT struct {
|
||||||
|
CreateParams uintptr
|
||||||
|
Instance HINSTANCE
|
||||||
|
Menu HMENU
|
||||||
|
Parent HWND
|
||||||
|
Cy, Cx int32
|
||||||
|
Y, X int32
|
||||||
|
Style int32
|
||||||
|
Name *uint16
|
||||||
|
Class *uint16
|
||||||
|
dwExStyle uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145065.aspx
|
||||||
|
type MONITORINFO struct {
|
||||||
|
CbSize uint32
|
||||||
|
RcMonitor RECT
|
||||||
|
RcWork RECT
|
||||||
|
DwFlags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145066.aspx
|
||||||
|
type MONITORINFOEX struct {
|
||||||
|
MONITORINFO
|
||||||
|
SzDevice [CCHDEVICENAME]uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd368826.aspx
|
||||||
|
type PIXELFORMATDESCRIPTOR struct {
|
||||||
|
Size uint16
|
||||||
|
Version uint16
|
||||||
|
DwFlags uint32
|
||||||
|
IPixelType byte
|
||||||
|
ColorBits byte
|
||||||
|
RedBits, RedShift byte
|
||||||
|
GreenBits, GreenShift byte
|
||||||
|
BlueBits, BlueShift byte
|
||||||
|
AlphaBits, AlphaShift byte
|
||||||
|
AccumBits byte
|
||||||
|
AccumRedBits byte
|
||||||
|
AccumGreenBits byte
|
||||||
|
AccumBlueBits byte
|
||||||
|
AccumAlphaBits byte
|
||||||
|
DepthBits, StencilBits byte
|
||||||
|
AuxBuffers byte
|
||||||
|
ILayerType byte
|
||||||
|
Reserved byte
|
||||||
|
DwLayerMask uint32
|
||||||
|
DwVisibleMask uint32
|
||||||
|
DwDamageMask uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270(v=vs.85).aspx
|
||||||
|
type INPUT struct {
|
||||||
|
Type uint32
|
||||||
|
Mi MOUSEINPUT
|
||||||
|
Ki KEYBDINPUT
|
||||||
|
Hi HARDWAREINPUT
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646273(v=vs.85).aspx
|
||||||
|
type MOUSEINPUT struct {
|
||||||
|
Dx int32
|
||||||
|
Dy int32
|
||||||
|
MouseData uint32
|
||||||
|
DwFlags uint32
|
||||||
|
Time uint32
|
||||||
|
DwExtraInfo uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646271(v=vs.85).aspx
|
||||||
|
type KEYBDINPUT struct {
|
||||||
|
WVk uint16
|
||||||
|
WScan uint16
|
||||||
|
DwFlags uint32
|
||||||
|
Time uint32
|
||||||
|
DwExtraInfo uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646269(v=vs.85).aspx
|
||||||
|
type HARDWAREINPUT struct {
|
||||||
|
UMsg uint32
|
||||||
|
WParamL uint16
|
||||||
|
WParamH uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type KbdInput struct {
|
||||||
|
typ uint32
|
||||||
|
ki KEYBDINPUT
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseInput struct {
|
||||||
|
typ uint32
|
||||||
|
mi MOUSEINPUT
|
||||||
|
}
|
||||||
|
|
||||||
|
type HardwareInput struct {
|
||||||
|
typ uint32
|
||||||
|
hi HARDWAREINPUT
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx
|
||||||
|
type SYSTEMTIME struct {
|
||||||
|
Year uint16
|
||||||
|
Month uint16
|
||||||
|
DayOfWeek uint16
|
||||||
|
Day uint16
|
||||||
|
Hour uint16
|
||||||
|
Minute uint16
|
||||||
|
Second uint16
|
||||||
|
Milliseconds uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644967(v=vs.85).aspx
|
||||||
|
type KBDLLHOOKSTRUCT struct {
|
||||||
|
VkCode DWORD
|
||||||
|
ScanCode DWORD
|
||||||
|
Flags DWORD
|
||||||
|
Time DWORD
|
||||||
|
DwExtraInfo ULONG_PTR
|
||||||
|
}
|
||||||
|
|
||||||
|
type HOOKPROC func(int, WPARAM, LPARAM) LRESULT
|
||||||
|
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms633498(v=vs.85).aspx
|
||||||
|
type WNDENUMPROC func(HWND, LPARAM) LRESULT
|
||||||
1046
vendor/github.com/apenwarr/w32/user32.go
generated
vendored
Normal file
1046
vendor/github.com/apenwarr/w32/user32.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
201
vendor/github.com/apenwarr/w32/utils.go
generated
vendored
Normal file
201
vendor/github.com/apenwarr/w32/utils.go
generated
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unicode/utf16"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MakeIntResource(id uint16) *uint16 {
|
||||||
|
return (*uint16)(unsafe.Pointer(uintptr(id)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func LOWORD(dw uint32) uint16 {
|
||||||
|
return uint16(dw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HIWORD(dw uint32) uint16 {
|
||||||
|
return uint16(dw >> 16 & 0xffff)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BoolToBOOL(value bool) BOOL {
|
||||||
|
if value {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func UTF16PtrToString(cstr *uint16) string {
|
||||||
|
if cstr != nil {
|
||||||
|
us := make([]uint16, 0, 256)
|
||||||
|
for p := uintptr(unsafe.Pointer(cstr)); ; p += 2 {
|
||||||
|
u := *(*uint16)(unsafe.Pointer(p))
|
||||||
|
if u == 0 {
|
||||||
|
return string(utf16.Decode(us))
|
||||||
|
}
|
||||||
|
us = append(us, u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func ComAddRef(unknown *IUnknown) int32 {
|
||||||
|
ret, _, _ := syscall.Syscall(unknown.lpVtbl.pAddRef, 1,
|
||||||
|
uintptr(unsafe.Pointer(unknown)),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
return int32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ComRelease(unknown *IUnknown) int32 {
|
||||||
|
ret, _, _ := syscall.Syscall(unknown.lpVtbl.pRelease, 1,
|
||||||
|
uintptr(unsafe.Pointer(unknown)),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
return int32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch {
|
||||||
|
var disp *IDispatch
|
||||||
|
hr, _, _ := syscall.Syscall(unknown.lpVtbl.pQueryInterface, 3,
|
||||||
|
uintptr(unsafe.Pointer(unknown)),
|
||||||
|
uintptr(unsafe.Pointer(id)),
|
||||||
|
uintptr(unsafe.Pointer(&disp)))
|
||||||
|
if hr != 0 {
|
||||||
|
panic("Invoke QieryInterface error.")
|
||||||
|
}
|
||||||
|
return disp
|
||||||
|
}
|
||||||
|
|
||||||
|
func ComGetIDsOfName(disp *IDispatch, names []string) []int32 {
|
||||||
|
wnames := make([]*uint16, len(names))
|
||||||
|
dispid := make([]int32, len(names))
|
||||||
|
for i := 0; i < len(names); i++ {
|
||||||
|
wnames[i] = syscall.StringToUTF16Ptr(names[i])
|
||||||
|
}
|
||||||
|
hr, _, _ := syscall.Syscall6(disp.lpVtbl.pGetIDsOfNames, 6,
|
||||||
|
uintptr(unsafe.Pointer(disp)),
|
||||||
|
uintptr(unsafe.Pointer(IID_NULL)),
|
||||||
|
uintptr(unsafe.Pointer(&wnames[0])),
|
||||||
|
uintptr(len(names)),
|
||||||
|
uintptr(GetUserDefaultLCID()),
|
||||||
|
uintptr(unsafe.Pointer(&dispid[0])))
|
||||||
|
if hr != 0 {
|
||||||
|
panic("Invoke GetIDsOfName error.")
|
||||||
|
}
|
||||||
|
return dispid
|
||||||
|
}
|
||||||
|
|
||||||
|
func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT) {
|
||||||
|
var dispparams DISPPARAMS
|
||||||
|
|
||||||
|
if dispatch&DISPATCH_PROPERTYPUT != 0 {
|
||||||
|
dispnames := [1]int32{DISPID_PROPERTYPUT}
|
||||||
|
dispparams.RgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
|
||||||
|
dispparams.CNamedArgs = 1
|
||||||
|
}
|
||||||
|
var vargs []VARIANT
|
||||||
|
if len(params) > 0 {
|
||||||
|
vargs = make([]VARIANT, len(params))
|
||||||
|
for i, v := range params {
|
||||||
|
//n := len(params)-i-1
|
||||||
|
n := len(params) - i - 1
|
||||||
|
VariantInit(&vargs[n])
|
||||||
|
switch v.(type) {
|
||||||
|
case bool:
|
||||||
|
if v.(bool) {
|
||||||
|
vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff}
|
||||||
|
} else {
|
||||||
|
vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0}
|
||||||
|
}
|
||||||
|
case *bool:
|
||||||
|
vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))}
|
||||||
|
case byte:
|
||||||
|
vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))}
|
||||||
|
case *byte:
|
||||||
|
vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))}
|
||||||
|
case int16:
|
||||||
|
vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))}
|
||||||
|
case *int16:
|
||||||
|
vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))}
|
||||||
|
case uint16:
|
||||||
|
vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))}
|
||||||
|
case *uint16:
|
||||||
|
vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))}
|
||||||
|
case int, int32:
|
||||||
|
vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))}
|
||||||
|
case *int, *int32:
|
||||||
|
vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))}
|
||||||
|
case uint, uint32:
|
||||||
|
vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))}
|
||||||
|
case *uint, *uint32:
|
||||||
|
vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))}
|
||||||
|
case int64:
|
||||||
|
vargs[n] = VARIANT{VT_I8, 0, 0, 0, v.(int64)}
|
||||||
|
case *int64:
|
||||||
|
vargs[n] = VARIANT{VT_I8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int64))))}
|
||||||
|
case uint64:
|
||||||
|
vargs[n] = VARIANT{VT_UI8, 0, 0, 0, int64(v.(uint64))}
|
||||||
|
case *uint64:
|
||||||
|
vargs[n] = VARIANT{VT_UI8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint64))))}
|
||||||
|
case float32:
|
||||||
|
vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))}
|
||||||
|
case *float32:
|
||||||
|
vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))}
|
||||||
|
case float64:
|
||||||
|
vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))}
|
||||||
|
case *float64:
|
||||||
|
vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))}
|
||||||
|
case string:
|
||||||
|
vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))}
|
||||||
|
case *string:
|
||||||
|
vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))}
|
||||||
|
case *IDispatch:
|
||||||
|
vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))}
|
||||||
|
case **IDispatch:
|
||||||
|
vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))}
|
||||||
|
case nil:
|
||||||
|
vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0}
|
||||||
|
case *VARIANT:
|
||||||
|
vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}
|
||||||
|
default:
|
||||||
|
panic("unknown type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dispparams.Rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
|
||||||
|
dispparams.CArgs = uint32(len(params))
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret VARIANT
|
||||||
|
var excepInfo EXCEPINFO
|
||||||
|
VariantInit(&ret)
|
||||||
|
hr, _, _ := syscall.Syscall9(disp.lpVtbl.pInvoke, 8,
|
||||||
|
uintptr(unsafe.Pointer(disp)),
|
||||||
|
uintptr(dispid),
|
||||||
|
uintptr(unsafe.Pointer(IID_NULL)),
|
||||||
|
uintptr(GetUserDefaultLCID()),
|
||||||
|
uintptr(dispatch),
|
||||||
|
uintptr(unsafe.Pointer(&dispparams)),
|
||||||
|
uintptr(unsafe.Pointer(&ret)),
|
||||||
|
uintptr(unsafe.Pointer(&excepInfo)),
|
||||||
|
0)
|
||||||
|
if hr != 0 {
|
||||||
|
if excepInfo.BstrDescription != nil {
|
||||||
|
bs := UTF16PtrToString(excepInfo.BstrDescription)
|
||||||
|
panic(bs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, varg := range vargs {
|
||||||
|
if varg.VT == VT_BSTR && varg.Val != 0 {
|
||||||
|
SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = &ret
|
||||||
|
return
|
||||||
|
}
|
||||||
13
vendor/github.com/apenwarr/w32/vars.go
generated
vendored
Normal file
13
vendor/github.com/apenwarr/w32/vars.go
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2010-2012 The W32 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 w32
|
||||||
|
|
||||||
|
var (
|
||||||
|
IID_NULL = &GUID{0x00000000, 0x0000, 0x0000, [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
|
||||||
|
IID_IUnknown = &GUID{0x00000000, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
|
||||||
|
IID_IDispatch = &GUID{0x00020400, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
|
||||||
|
IID_IConnectionPointContainer = &GUID{0xB196B284, 0xBAB4, 0x101A, [8]byte{0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}}
|
||||||
|
IID_IConnectionPoint = &GUID{0xB196B286, 0xBAB4, 0x101A, [8]byte{0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}}
|
||||||
|
)
|
||||||
3
vendor/github.com/go-chi/chi/v5/.gitignore
generated
vendored
Normal file
3
vendor/github.com/go-chi/chi/v5/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
.idea
|
||||||
|
*.sw?
|
||||||
|
.vscode
|
||||||
279
vendor/github.com/go-chi/chi/v5/CHANGELOG.md
generated
vendored
Normal file
279
vendor/github.com/go-chi/chi/v5/CHANGELOG.md
generated
vendored
Normal file
|
|
@ -0,0 +1,279 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## v5.0.0 (2021-02-27)
|
||||||
|
|
||||||
|
- chi v5, `github.com/go-chi/chi/v5` introduces the adoption of Go's SIV to adhere to the current state-of-the-tools in Go.
|
||||||
|
- chi v1.5.x did not work out as planned, as the Go tooling is too powerful and chi's adoption is too wide.
|
||||||
|
The most responsible thing to do for everyone's benefit is to just release v5 with SIV, so I present to you all,
|
||||||
|
chi v5 at `github.com/go-chi/chi/v5`. I hope someday the developer experience and ergonomics I've been seeking
|
||||||
|
will still come to fruition in some form, see https://github.com/golang/go/issues/44550
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v1.5.4...v5.0.0
|
||||||
|
|
||||||
|
|
||||||
|
## v1.5.4 (2021-02-27)
|
||||||
|
|
||||||
|
- Undo prior retraction in v1.5.3 as we prepare for v5.0.0 release
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v1.5.3...v1.5.4
|
||||||
|
|
||||||
|
|
||||||
|
## v1.5.3 (2021-02-21)
|
||||||
|
|
||||||
|
- Update go.mod to go 1.16 with new retract directive marking all versions without prior go.mod support
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v1.5.2...v1.5.3
|
||||||
|
|
||||||
|
|
||||||
|
## v1.5.2 (2021-02-10)
|
||||||
|
|
||||||
|
- Reverting allocation optimization as a precaution as go test -race fails.
|
||||||
|
- Minor improvements, see history below
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v1.5.1...v1.5.2
|
||||||
|
|
||||||
|
|
||||||
|
## v1.5.1 (2020-12-06)
|
||||||
|
|
||||||
|
- Performance improvement: removing 1 allocation by foregoing context.WithValue, thank you @bouk for
|
||||||
|
your contribution (https://github.com/go-chi/chi/pull/555). Note: new benchmarks posted in README.
|
||||||
|
- `middleware.CleanPath`: new middleware that clean's request path of double slashes
|
||||||
|
- deprecate & remove `chi.ServerBaseContext` in favour of stdlib `http.Server#BaseContext`
|
||||||
|
- plus other tiny improvements, see full commit history below
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v4.1.2...v1.5.1
|
||||||
|
|
||||||
|
|
||||||
|
## v1.5.0 (2020-11-12) - now with go.mod support
|
||||||
|
|
||||||
|
`chi` dates back to 2016 with it's original implementation as one of the first routers to adopt the newly introduced
|
||||||
|
context.Context api to the stdlib -- set out to design a router that is faster, more modular and simpler than anything
|
||||||
|
else out there -- while not introducing any custom handler types or dependencies. Today, `chi` still has zero dependencies,
|
||||||
|
and in many ways is future proofed from changes, given it's minimal nature. Between versions, chi's iterations have been very
|
||||||
|
incremental, with the architecture and api being the same today as it was originally designed in 2016. For this reason it
|
||||||
|
makes chi a pretty easy project to maintain, as well thanks to the many amazing community contributions over the years
|
||||||
|
to who all help make chi better (total of 86 contributors to date -- thanks all!).
|
||||||
|
|
||||||
|
Chi has been an labour of love, art and engineering, with the goals to offer beautiful ergonomics, flexibility, performance
|
||||||
|
and simplicity when building HTTP services with Go. I've strived to keep the router very minimal in surface area / code size,
|
||||||
|
and always improving the code wherever possible -- and as of today the `chi` package is just 1082 lines of code (not counting
|
||||||
|
middlewares, which are all optional). As well, I don't have the exact metrics, but from my analysis and email exchanges from
|
||||||
|
companies and developers, chi is used by thousands of projects around the world -- thank you all as there is no better form of
|
||||||
|
joy for me than to have art I had started be helpful and enjoyed by others. And of course I use chi in all of my own projects too :)
|
||||||
|
|
||||||
|
For me, the asthetics of chi's code and usage are very important. With the introduction of Go's module support
|
||||||
|
(which I'm a big fan of), chi's past versioning scheme choice to v2, v3 and v4 would mean I'd require the import path
|
||||||
|
of "github.com/go-chi/chi/v4", leading to the lengthy discussion at https://github.com/go-chi/chi/issues/462.
|
||||||
|
Haha, to some, you may be scratching your head why I've spent > 1 year stalling to adopt "/vXX" convention in the import
|
||||||
|
path -- which isn't horrible in general -- but for chi, I'm unable to accept it as I strive for perfection in it's API design,
|
||||||
|
aesthetics and simplicity. It just doesn't feel good to me given chi's simple nature -- I do not foresee a "v5" or "v6",
|
||||||
|
and upgrading between versions in the future will also be just incremental.
|
||||||
|
|
||||||
|
I do understand versioning is a part of the API design as well, which is why the solution for a while has been to "do nothing",
|
||||||
|
as Go supports both old and new import paths with/out go.mod. However, now that Go module support has had time to iron out kinks and
|
||||||
|
is adopted everywhere, it's time for chi to get with the times. Luckily, I've discovered a path forward that will make me happy,
|
||||||
|
while also not breaking anyone's app who adopted a prior versioning from tags in v2/v3/v4. I've made an experimental release of
|
||||||
|
v1.5.0 with go.mod silently, and tested it with new and old projects, to ensure the developer experience is preserved, and it's
|
||||||
|
largely unnoticed. Fortunately, Go's toolchain will check the tags of a repo and consider the "latest" tag the one with go.mod.
|
||||||
|
However, you can still request a specific older tag such as v4.1.2, and everything will "just work". But new users can just
|
||||||
|
`go get github.com/go-chi/chi` or `go get github.com/go-chi/chi@latest` and they will get the latest version which contains
|
||||||
|
go.mod support, which is v1.5.0+. `chi` will not change very much over the years, just like it hasn't changed much from 4 years ago.
|
||||||
|
Therefore, we will stay on v1.x from here on, starting from v1.5.0. Any breaking changes will bump a "minor" release and
|
||||||
|
backwards-compatible improvements/fixes will bump a "tiny" release.
|
||||||
|
|
||||||
|
For existing projects who want to upgrade to the latest go.mod version, run: `go get -u github.com/go-chi/chi@v1.5.0`,
|
||||||
|
which will get you on the go.mod version line (as Go's mod cache may still remember v4.x). Brand new systems can run
|
||||||
|
`go get -u github.com/go-chi/chi` or `go get -u github.com/go-chi/chi@latest` to install chi, which will install v1.5.0+
|
||||||
|
built with go.mod support.
|
||||||
|
|
||||||
|
My apologies to the developers who will disagree with the decisions above, but, hope you'll try it and see it's a very
|
||||||
|
minor request which is backwards compatible and won't break your existing installations.
|
||||||
|
|
||||||
|
Cheers all, happy coding!
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## v4.1.2 (2020-06-02)
|
||||||
|
|
||||||
|
- fix that handles MethodNotAllowed with path variables, thank you @caseyhadden for your contribution
|
||||||
|
- fix to replace nested wildcards correctly in RoutePattern, thank you @@unmultimedio for your contribution
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v4.1.1...v4.1.2
|
||||||
|
|
||||||
|
|
||||||
|
## v4.1.1 (2020-04-16)
|
||||||
|
|
||||||
|
- fix for issue https://github.com/go-chi/chi/issues/411 which allows for overlapping regexp
|
||||||
|
route to the correct handler through a recursive tree search, thanks to @Jahaja for the PR/fix!
|
||||||
|
- new middleware.RouteHeaders as a simple router for request headers with wildcard support
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v4.1.0...v4.1.1
|
||||||
|
|
||||||
|
|
||||||
|
## v4.1.0 (2020-04-1)
|
||||||
|
|
||||||
|
- middleware.LogEntry: Write method on interface now passes the response header
|
||||||
|
and an extra interface type useful for custom logger implementations.
|
||||||
|
- middleware.WrapResponseWriter: minor fix
|
||||||
|
- middleware.Recoverer: a bit prettier
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v4.0.4...v4.1.0
|
||||||
|
|
||||||
|
## v4.0.4 (2020-03-24)
|
||||||
|
|
||||||
|
- middleware.Recoverer: new pretty stack trace printing (https://github.com/go-chi/chi/pull/496)
|
||||||
|
- a few minor improvements and fixes
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v4.0.3...v4.0.4
|
||||||
|
|
||||||
|
|
||||||
|
## v4.0.3 (2020-01-09)
|
||||||
|
|
||||||
|
- core: fix regexp routing to include default value when param is not matched
|
||||||
|
- middleware: rewrite of middleware.Compress
|
||||||
|
- middleware: suppress http.ErrAbortHandler in middleware.Recoverer
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v4.0.2...v4.0.3
|
||||||
|
|
||||||
|
|
||||||
|
## v4.0.2 (2019-02-26)
|
||||||
|
|
||||||
|
- Minor fixes
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v4.0.1...v4.0.2
|
||||||
|
|
||||||
|
|
||||||
|
## v4.0.1 (2019-01-21)
|
||||||
|
|
||||||
|
- Fixes issue with compress middleware: #382 #385
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v4.0.0...v4.0.1
|
||||||
|
|
||||||
|
|
||||||
|
## v4.0.0 (2019-01-10)
|
||||||
|
|
||||||
|
- chi v4 requires Go 1.10.3+ (or Go 1.9.7+) - we have deprecated support for Go 1.7 and 1.8
|
||||||
|
- router: respond with 404 on router with no routes (#362)
|
||||||
|
- router: additional check to ensure wildcard is at the end of a url pattern (#333)
|
||||||
|
- middleware: deprecate use of http.CloseNotifier (#347)
|
||||||
|
- middleware: fix RedirectSlashes to include query params on redirect (#334)
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v3.3.4...v4.0.0
|
||||||
|
|
||||||
|
|
||||||
|
## v3.3.4 (2019-01-07)
|
||||||
|
|
||||||
|
- Minor middleware improvements. No changes to core library/router. Moving v3 into its
|
||||||
|
- own branch as a version of chi for Go 1.7, 1.8, 1.9, 1.10, 1.11
|
||||||
|
- History of changes: see https://github.com/go-chi/chi/compare/v3.3.3...v3.3.4
|
||||||
|
|
||||||
|
|
||||||
|
## v3.3.3 (2018-08-27)
|
||||||
|
|
||||||
|
- Minor release
|
||||||
|
- See https://github.com/go-chi/chi/compare/v3.3.2...v3.3.3
|
||||||
|
|
||||||
|
|
||||||
|
## v3.3.2 (2017-12-22)
|
||||||
|
|
||||||
|
- Support to route trailing slashes on mounted sub-routers (#281)
|
||||||
|
- middleware: new `ContentCharset` to check matching charsets. Thank you
|
||||||
|
@csucu for your community contribution!
|
||||||
|
|
||||||
|
|
||||||
|
## v3.3.1 (2017-11-20)
|
||||||
|
|
||||||
|
- middleware: new `AllowContentType` handler for explicit whitelist of accepted request Content-Types
|
||||||
|
- middleware: new `SetHeader` handler for short-hand middleware to set a response header key/value
|
||||||
|
- Minor bug fixes
|
||||||
|
|
||||||
|
|
||||||
|
## v3.3.0 (2017-10-10)
|
||||||
|
|
||||||
|
- New chi.RegisterMethod(method) to add support for custom HTTP methods, see _examples/custom-method for usage
|
||||||
|
- Deprecated LINK and UNLINK methods from the default list, please use `chi.RegisterMethod("LINK")` and `chi.RegisterMethod("UNLINK")` in an `init()` function
|
||||||
|
|
||||||
|
|
||||||
|
## v3.2.1 (2017-08-31)
|
||||||
|
|
||||||
|
- Add new `Match(rctx *Context, method, path string) bool` method to `Routes` interface
|
||||||
|
and `Mux`. Match searches the mux's routing tree for a handler that matches the method/path
|
||||||
|
- Add new `RouteMethod` to `*Context`
|
||||||
|
- Add new `Routes` pointer to `*Context`
|
||||||
|
- Add new `middleware.GetHead` to route missing HEAD requests to GET handler
|
||||||
|
- Updated benchmarks (see README)
|
||||||
|
|
||||||
|
|
||||||
|
## v3.1.5 (2017-08-02)
|
||||||
|
|
||||||
|
- Setup golint and go vet for the project
|
||||||
|
- As per golint, we've redefined `func ServerBaseContext(h http.Handler, baseCtx context.Context) http.Handler`
|
||||||
|
to `func ServerBaseContext(baseCtx context.Context, h http.Handler) http.Handler`
|
||||||
|
|
||||||
|
|
||||||
|
## v3.1.0 (2017-07-10)
|
||||||
|
|
||||||
|
- Fix a few minor issues after v3 release
|
||||||
|
- Move `docgen` sub-pkg to https://github.com/go-chi/docgen
|
||||||
|
- Move `render` sub-pkg to https://github.com/go-chi/render
|
||||||
|
- Add new `URLFormat` handler to chi/middleware sub-pkg to make working with url mime
|
||||||
|
suffixes easier, ie. parsing `/articles/1.json` and `/articles/1.xml`. See comments in
|
||||||
|
https://github.com/go-chi/chi/blob/master/middleware/url_format.go for example usage.
|
||||||
|
|
||||||
|
|
||||||
|
## v3.0.0 (2017-06-21)
|
||||||
|
|
||||||
|
- Major update to chi library with many exciting updates, but also some *breaking changes*
|
||||||
|
- URL parameter syntax changed from `/:id` to `/{id}` for even more flexible routing, such as
|
||||||
|
`/articles/{month}-{day}-{year}-{slug}`, `/articles/{id}`, and `/articles/{id}.{ext}` on the
|
||||||
|
same router
|
||||||
|
- Support for regexp for routing patterns, in the form of `/{paramKey:regExp}` for example:
|
||||||
|
`r.Get("/articles/{name:[a-z]+}", h)` and `chi.URLParam(r, "name")`
|
||||||
|
- Add `Method` and `MethodFunc` to `chi.Router` to allow routing definitions such as
|
||||||
|
`r.Method("GET", "/", h)` which provides a cleaner interface for custom handlers like
|
||||||
|
in `_examples/custom-handler`
|
||||||
|
- Deprecating `mux#FileServer` helper function. Instead, we encourage users to create their
|
||||||
|
own using file handler with the stdlib, see `_examples/fileserver` for an example
|
||||||
|
- Add support for LINK/UNLINK http methods via `r.Method()` and `r.MethodFunc()`
|
||||||
|
- Moved the chi project to its own organization, to allow chi-related community packages to
|
||||||
|
be easily discovered and supported, at: https://github.com/go-chi
|
||||||
|
- *NOTE:* please update your import paths to `"github.com/go-chi/chi"`
|
||||||
|
- *NOTE:* chi v2 is still available at https://github.com/go-chi/chi/tree/v2
|
||||||
|
|
||||||
|
|
||||||
|
## v2.1.0 (2017-03-30)
|
||||||
|
|
||||||
|
- Minor improvements and update to the chi core library
|
||||||
|
- Introduced a brand new `chi/render` sub-package to complete the story of building
|
||||||
|
APIs to offer a pattern for managing well-defined request / response payloads. Please
|
||||||
|
check out the updated `_examples/rest` example for how it works.
|
||||||
|
- Added `MethodNotAllowed(h http.HandlerFunc)` to chi.Router interface
|
||||||
|
|
||||||
|
|
||||||
|
## v2.0.0 (2017-01-06)
|
||||||
|
|
||||||
|
- After many months of v2 being in an RC state with many companies and users running it in
|
||||||
|
production, the inclusion of some improvements to the middlewares, we are very pleased to
|
||||||
|
announce v2.0.0 of chi.
|
||||||
|
|
||||||
|
|
||||||
|
## v2.0.0-rc1 (2016-07-26)
|
||||||
|
|
||||||
|
- Huge update! chi v2 is a large refactor targetting Go 1.7+. As of Go 1.7, the popular
|
||||||
|
community `"net/context"` package has been included in the standard library as `"context"` and
|
||||||
|
utilized by `"net/http"` and `http.Request` to managing deadlines, cancelation signals and other
|
||||||
|
request-scoped values. We're very excited about the new context addition and are proud to
|
||||||
|
introduce chi v2, a minimal and powerful routing package for building large HTTP services,
|
||||||
|
with zero external dependencies. Chi focuses on idiomatic design and encourages the use of
|
||||||
|
stdlib HTTP handlers and middlwares.
|
||||||
|
- chi v2 deprecates its `chi.Handler` interface and requires `http.Handler` or `http.HandlerFunc`
|
||||||
|
- chi v2 stores URL routing parameters and patterns in the standard request context: `r.Context()`
|
||||||
|
- chi v2 lower-level routing context is accessible by `chi.RouteContext(r.Context()) *chi.Context`,
|
||||||
|
which provides direct access to URL routing parameters, the routing path and the matching
|
||||||
|
routing patterns.
|
||||||
|
- Users upgrading from chi v1 to v2, need to:
|
||||||
|
1. Update the old chi.Handler signature, `func(ctx context.Context, w http.ResponseWriter, r *http.Request)` to
|
||||||
|
the standard http.Handler: `func(w http.ResponseWriter, r *http.Request)`
|
||||||
|
2. Use `chi.URLParam(r *http.Request, paramKey string) string`
|
||||||
|
or `URLParamFromCtx(ctx context.Context, paramKey string) string` to access a url parameter value
|
||||||
|
|
||||||
|
|
||||||
|
## v1.0.0 (2016-07-01)
|
||||||
|
|
||||||
|
- Released chi v1 stable https://github.com/go-chi/chi/tree/v1.0.0 for Go 1.6 and older.
|
||||||
|
|
||||||
|
|
||||||
|
## v0.9.0 (2016-03-31)
|
||||||
|
|
||||||
|
- Reuse context objects via sync.Pool for zero-allocation routing [#33](https://github.com/go-chi/chi/pull/33)
|
||||||
|
- BREAKING NOTE: due to subtle API changes, previously `chi.URLParams(ctx)["id"]` used to access url parameters
|
||||||
|
has changed to: `chi.URLParam(ctx, "id")`
|
||||||
31
vendor/github.com/go-chi/chi/v5/CONTRIBUTING.md
generated
vendored
Normal file
31
vendor/github.com/go-chi/chi/v5/CONTRIBUTING.md
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. [Install Go][go-install].
|
||||||
|
2. Download the sources and switch the working directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get -u -d github.com/go-chi/chi
|
||||||
|
cd $GOPATH/src/github.com/go-chi/chi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Submitting a Pull Request
|
||||||
|
|
||||||
|
A typical workflow is:
|
||||||
|
|
||||||
|
1. [Fork the repository.][fork] [This tip maybe also helpful.][go-fork-tip]
|
||||||
|
2. [Create a topic branch.][branch]
|
||||||
|
3. Add tests for your change.
|
||||||
|
4. Run `go test`. If your tests pass, return to the step 3.
|
||||||
|
5. Implement the change and ensure the steps from the previous step pass.
|
||||||
|
6. Run `goimports -w .`, to ensure the new code conforms to Go formatting guideline.
|
||||||
|
7. [Add, commit and push your changes.][git-help]
|
||||||
|
8. [Submit a pull request.][pull-req]
|
||||||
|
|
||||||
|
[go-install]: https://golang.org/doc/install
|
||||||
|
[go-fork-tip]: http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html
|
||||||
|
[fork]: https://help.github.com/articles/fork-a-repo
|
||||||
|
[branch]: http://learn.github.com/p/branching.html
|
||||||
|
[git-help]: https://guides.github.com
|
||||||
|
[pull-req]: https://help.github.com/articles/using-pull-requests
|
||||||
20
vendor/github.com/go-chi/chi/v5/LICENSE
generated
vendored
Normal file
20
vendor/github.com/go-chi/chi/v5/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
Copyright (c) 2015-present Peter Kieltyka (https://github.com/pkieltyka), Google Inc.
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
14
vendor/github.com/go-chi/chi/v5/Makefile
generated
vendored
Normal file
14
vendor/github.com/go-chi/chi/v5/Makefile
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
all:
|
||||||
|
@echo "**********************************************************"
|
||||||
|
@echo "** chi build tool **"
|
||||||
|
@echo "**********************************************************"
|
||||||
|
|
||||||
|
|
||||||
|
test:
|
||||||
|
go clean -testcache && $(MAKE) test-router && $(MAKE) test-middleware
|
||||||
|
|
||||||
|
test-router:
|
||||||
|
go test -race -v .
|
||||||
|
|
||||||
|
test-middleware:
|
||||||
|
go test -race -v ./middleware
|
||||||
511
vendor/github.com/go-chi/chi/v5/README.md
generated
vendored
Normal file
511
vendor/github.com/go-chi/chi/v5/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,511 @@
|
||||||
|
# <img alt="chi" src="https://cdn.rawgit.com/go-chi/chi/master/_examples/chi.svg" width="220" />
|
||||||
|
|
||||||
|
|
||||||
|
[![GoDoc Widget]][GoDoc] [![Travis Widget]][Travis]
|
||||||
|
|
||||||
|
`chi` is a lightweight, idiomatic and composable router for building Go HTTP services. It's
|
||||||
|
especially good at helping you write large REST API services that are kept maintainable as your
|
||||||
|
project grows and changes. `chi` is built on the new `context` package introduced in Go 1.7 to
|
||||||
|
handle signaling, cancelation and request-scoped values across a handler chain.
|
||||||
|
|
||||||
|
The focus of the project has been to seek out an elegant and comfortable design for writing
|
||||||
|
REST API servers, written during the development of the Pressly API service that powers our
|
||||||
|
public API service, which in turn powers all of our client-side applications.
|
||||||
|
|
||||||
|
The key considerations of chi's design are: project structure, maintainability, standard http
|
||||||
|
handlers (stdlib-only), developer productivity, and deconstructing a large system into many small
|
||||||
|
parts. The core router `github.com/go-chi/chi` is quite small (less than 1000 LOC), but we've also
|
||||||
|
included some useful/optional subpackages: [middleware](/middleware), [render](https://github.com/go-chi/render)
|
||||||
|
and [docgen](https://github.com/go-chi/docgen). We hope you enjoy it too!
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
`go get -u github.com/go-chi/chi/v5`
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* **Lightweight** - cloc'd in ~1000 LOC for the chi router
|
||||||
|
* **Fast** - yes, see [benchmarks](#benchmarks)
|
||||||
|
* **100% compatible with net/http** - use any http or middleware pkg in the ecosystem that is also compatible with `net/http`
|
||||||
|
* **Designed for modular/composable APIs** - middlewares, inline middlewares, route groups and sub-router mounting
|
||||||
|
* **Context control** - built on new `context` package, providing value chaining, cancellations and timeouts
|
||||||
|
* **Robust** - in production at Pressly, CloudFlare, Heroku, 99Designs, and many others (see [discussion](https://github.com/go-chi/chi/issues/91))
|
||||||
|
* **Doc generation** - `docgen` auto-generates routing documentation from your source to JSON or Markdown
|
||||||
|
* **Go.mod support** - v1.x of chi (starting from v1.5.0), now has go.mod support (see [CHANGELOG](https://github.com/go-chi/chi/blob/master/CHANGELOG.md#v150-2020-11-12---now-with-gomod-support))
|
||||||
|
* **No external dependencies** - plain ol' Go stdlib + net/http
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
See [_examples/](https://github.com/go-chi/chi/blob/master/_examples/) for a variety of examples.
|
||||||
|
|
||||||
|
|
||||||
|
**As easy as:**
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := chi.NewRouter()
|
||||||
|
r.Use(middleware.Logger)
|
||||||
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("welcome"))
|
||||||
|
})
|
||||||
|
http.ListenAndServe(":3000", r)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**REST Preview:**
|
||||||
|
|
||||||
|
Here is a little preview of how routing looks like with chi. Also take a look at the generated routing docs
|
||||||
|
in JSON ([routes.json](https://github.com/go-chi/chi/blob/master/_examples/rest/routes.json)) and in
|
||||||
|
Markdown ([routes.md](https://github.com/go-chi/chi/blob/master/_examples/rest/routes.md)).
|
||||||
|
|
||||||
|
I highly recommend reading the source of the [examples](https://github.com/go-chi/chi/blob/master/_examples/) listed
|
||||||
|
above, they will show you all the features of chi and serve as a good form of documentation.
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
//...
|
||||||
|
"context"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := chi.NewRouter()
|
||||||
|
|
||||||
|
// A good base middleware stack
|
||||||
|
r.Use(middleware.RequestID)
|
||||||
|
r.Use(middleware.RealIP)
|
||||||
|
r.Use(middleware.Logger)
|
||||||
|
r.Use(middleware.Recoverer)
|
||||||
|
|
||||||
|
// Set a timeout value on the request context (ctx), that will signal
|
||||||
|
// through ctx.Done() that the request has timed out and further
|
||||||
|
// processing should be stopped.
|
||||||
|
r.Use(middleware.Timeout(60 * time.Second))
|
||||||
|
|
||||||
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("hi"))
|
||||||
|
})
|
||||||
|
|
||||||
|
// RESTy routes for "articles" resource
|
||||||
|
r.Route("/articles", func(r chi.Router) {
|
||||||
|
r.With(paginate).Get("/", listArticles) // GET /articles
|
||||||
|
r.With(paginate).Get("/{month}-{day}-{year}", listArticlesByDate) // GET /articles/01-16-2017
|
||||||
|
|
||||||
|
r.Post("/", createArticle) // POST /articles
|
||||||
|
r.Get("/search", searchArticles) // GET /articles/search
|
||||||
|
|
||||||
|
// Regexp url parameters:
|
||||||
|
r.Get("/{articleSlug:[a-z-]+}", getArticleBySlug) // GET /articles/home-is-toronto
|
||||||
|
|
||||||
|
// Subrouters:
|
||||||
|
r.Route("/{articleID}", func(r chi.Router) {
|
||||||
|
r.Use(ArticleCtx)
|
||||||
|
r.Get("/", getArticle) // GET /articles/123
|
||||||
|
r.Put("/", updateArticle) // PUT /articles/123
|
||||||
|
r.Delete("/", deleteArticle) // DELETE /articles/123
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Mount the admin sub-router
|
||||||
|
r.Mount("/admin", adminRouter())
|
||||||
|
|
||||||
|
http.ListenAndServe(":3333", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ArticleCtx(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
articleID := chi.URLParam(r, "articleID")
|
||||||
|
article, err := dbGetArticle(articleID)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, http.StatusText(404), 404)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(r.Context(), "article", article)
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArticle(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
article, ok := ctx.Value("article").(*Article)
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, http.StatusText(422), 422)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Write([]byte(fmt.Sprintf("title:%s", article.Title)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// A completely separate router for administrator routes
|
||||||
|
func adminRouter() http.Handler {
|
||||||
|
r := chi.NewRouter()
|
||||||
|
r.Use(AdminOnly)
|
||||||
|
r.Get("/", adminIndex)
|
||||||
|
r.Get("/accounts", adminListAccounts)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func AdminOnly(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
perm, ok := ctx.Value("acl.permission").(YourPermissionType)
|
||||||
|
if !ok || !perm.IsAdmin() {
|
||||||
|
http.Error(w, http.StatusText(403), 403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Router interface
|
||||||
|
|
||||||
|
chi's router is based on a kind of [Patricia Radix trie](https://en.wikipedia.org/wiki/Radix_tree).
|
||||||
|
The router is fully compatible with `net/http`.
|
||||||
|
|
||||||
|
Built on top of the tree is the `Router` interface:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Router consisting of the core routing methods used by chi's Mux,
|
||||||
|
// using only the standard net/http.
|
||||||
|
type Router interface {
|
||||||
|
http.Handler
|
||||||
|
Routes
|
||||||
|
|
||||||
|
// Use appends one or more middlewares onto the Router stack.
|
||||||
|
Use(middlewares ...func(http.Handler) http.Handler)
|
||||||
|
|
||||||
|
// With adds inline middlewares for an endpoint handler.
|
||||||
|
With(middlewares ...func(http.Handler) http.Handler) Router
|
||||||
|
|
||||||
|
// Group adds a new inline-Router along the current routing
|
||||||
|
// path, with a fresh middleware stack for the inline-Router.
|
||||||
|
Group(fn func(r Router)) Router
|
||||||
|
|
||||||
|
// Route mounts a sub-Router along a `pattern`` string.
|
||||||
|
Route(pattern string, fn func(r Router)) Router
|
||||||
|
|
||||||
|
// Mount attaches another http.Handler along ./pattern/*
|
||||||
|
Mount(pattern string, h http.Handler)
|
||||||
|
|
||||||
|
// Handle and HandleFunc adds routes for `pattern` that matches
|
||||||
|
// all HTTP methods.
|
||||||
|
Handle(pattern string, h http.Handler)
|
||||||
|
HandleFunc(pattern string, h http.HandlerFunc)
|
||||||
|
|
||||||
|
// Method and MethodFunc adds routes for `pattern` that matches
|
||||||
|
// the `method` HTTP method.
|
||||||
|
Method(method, pattern string, h http.Handler)
|
||||||
|
MethodFunc(method, pattern string, h http.HandlerFunc)
|
||||||
|
|
||||||
|
// HTTP-method routing along `pattern`
|
||||||
|
Connect(pattern string, h http.HandlerFunc)
|
||||||
|
Delete(pattern string, h http.HandlerFunc)
|
||||||
|
Get(pattern string, h http.HandlerFunc)
|
||||||
|
Head(pattern string, h http.HandlerFunc)
|
||||||
|
Options(pattern string, h http.HandlerFunc)
|
||||||
|
Patch(pattern string, h http.HandlerFunc)
|
||||||
|
Post(pattern string, h http.HandlerFunc)
|
||||||
|
Put(pattern string, h http.HandlerFunc)
|
||||||
|
Trace(pattern string, h http.HandlerFunc)
|
||||||
|
|
||||||
|
// NotFound defines a handler to respond whenever a route could
|
||||||
|
// not be found.
|
||||||
|
NotFound(h http.HandlerFunc)
|
||||||
|
|
||||||
|
// MethodNotAllowed defines a handler to respond whenever a method is
|
||||||
|
// not allowed.
|
||||||
|
MethodNotAllowed(h http.HandlerFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routes interface adds two methods for router traversal, which is also
|
||||||
|
// used by the github.com/go-chi/docgen package to generate documentation for Routers.
|
||||||
|
type Routes interface {
|
||||||
|
// Routes returns the routing tree in an easily traversable structure.
|
||||||
|
Routes() []Route
|
||||||
|
|
||||||
|
// Middlewares returns the list of middlewares in use by the router.
|
||||||
|
Middlewares() Middlewares
|
||||||
|
|
||||||
|
// Match searches the routing tree for a handler that matches
|
||||||
|
// the method/path - similar to routing a http request, but without
|
||||||
|
// executing the handler thereafter.
|
||||||
|
Match(rctx *Context, method, path string) bool
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Each routing method accepts a URL `pattern` and chain of `handlers`. The URL pattern
|
||||||
|
supports named params (ie. `/users/{userID}`) and wildcards (ie. `/admin/*`). URL parameters
|
||||||
|
can be fetched at runtime by calling `chi.URLParam(r, "userID")` for named parameters
|
||||||
|
and `chi.URLParam(r, "*")` for a wildcard parameter.
|
||||||
|
|
||||||
|
|
||||||
|
### Middleware handlers
|
||||||
|
|
||||||
|
chi's middlewares are just stdlib net/http middleware handlers. There is nothing special
|
||||||
|
about them, which means the router and all the tooling is designed to be compatible and
|
||||||
|
friendly with any middleware in the community. This offers much better extensibility and reuse
|
||||||
|
of packages and is at the heart of chi's purpose.
|
||||||
|
|
||||||
|
Here is an example of a standard net/http middleware where we assign a context key `"user"`
|
||||||
|
the value of `"123"`. This middleware sets a hypothetical user identifier on the request
|
||||||
|
context and calls the next handler in the chain.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// HTTP middleware setting a value on the request context
|
||||||
|
func MyMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// create new context from `r` request context, and assign key `"user"`
|
||||||
|
// to value of `"123"`
|
||||||
|
ctx := context.WithValue(r.Context(), "user", "123")
|
||||||
|
|
||||||
|
// call the next handler in the chain, passing the response writer and
|
||||||
|
// the updated request object with the new context value.
|
||||||
|
//
|
||||||
|
// note: context.Context values are nested, so any previously set
|
||||||
|
// values will be accessible as well, and the new `"user"` key
|
||||||
|
// will be accessible from this point forward.
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Request handlers
|
||||||
|
|
||||||
|
chi uses standard net/http request handlers. This little snippet is an example of a http.Handler
|
||||||
|
func that reads a user identifier from the request context - hypothetically, identifying
|
||||||
|
the user sending an authenticated request, validated+set by a previous middleware handler.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// HTTP handler accessing data from the request context.
|
||||||
|
func MyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// here we read from the request context and fetch out `"user"` key set in
|
||||||
|
// the MyMiddleware example above.
|
||||||
|
user := r.Context().Value("user").(string)
|
||||||
|
|
||||||
|
// respond to the client
|
||||||
|
w.Write([]byte(fmt.Sprintf("hi %s", user)))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### URL parameters
|
||||||
|
|
||||||
|
chi's router parses and stores URL parameters right onto the request context. Here is
|
||||||
|
an example of how to access URL params in your net/http handlers. And of course, middlewares
|
||||||
|
are able to access the same information.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// HTTP handler accessing the url routing parameters.
|
||||||
|
func MyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// fetch the url parameter `"userID"` from the request of a matching
|
||||||
|
// routing pattern. An example routing pattern could be: /users/{userID}
|
||||||
|
userID := chi.URLParam(r, "userID")
|
||||||
|
|
||||||
|
// fetch `"key"` from the request context
|
||||||
|
ctx := r.Context()
|
||||||
|
key := ctx.Value("key").(string)
|
||||||
|
|
||||||
|
// respond to the client
|
||||||
|
w.Write([]byte(fmt.Sprintf("hi %v, %v", userID, key)))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Middlewares
|
||||||
|
|
||||||
|
chi comes equipped with an optional `middleware` package, providing a suite of standard
|
||||||
|
`net/http` middlewares. Please note, any middleware in the ecosystem that is also compatible
|
||||||
|
with `net/http` can be used with chi's mux.
|
||||||
|
|
||||||
|
### Core middlewares
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------------------------------
|
||||||
|
| chi/middleware Handler | description |
|
||||||
|
| :--------------------- | :---------------------------------------------------------------------- |
|
||||||
|
| [AllowContentEncoding] | Enforces a whitelist of request Content-Encoding headers |
|
||||||
|
| [AllowContentType] | Explicit whitelist of accepted request Content-Types |
|
||||||
|
| [BasicAuth] | Basic HTTP authentication |
|
||||||
|
| [Compress] | Gzip compression for clients that accept compressed responses |
|
||||||
|
| [ContentCharset] | Ensure charset for Content-Type request headers |
|
||||||
|
| [CleanPath] | Clean double slashes from request path |
|
||||||
|
| [GetHead] | Automatically route undefined HEAD requests to GET handlers |
|
||||||
|
| [Heartbeat] | Monitoring endpoint to check the servers pulse |
|
||||||
|
| [Logger] | Logs the start and end of each request with the elapsed processing time |
|
||||||
|
| [NoCache] | Sets response headers to prevent clients from caching |
|
||||||
|
| [Profiler] | Easily attach net/http/pprof to your routers |
|
||||||
|
| [RealIP] | Sets a http.Request's RemoteAddr to either X-Forwarded-For or X-Real-IP |
|
||||||
|
| [Recoverer] | Gracefully absorb panics and prints the stack trace |
|
||||||
|
| [RequestID] | Injects a request ID into the context of each request |
|
||||||
|
| [RedirectSlashes] | Redirect slashes on routing paths |
|
||||||
|
| [RouteHeaders] | Route handling for request headers |
|
||||||
|
| [SetHeader] | Short-hand middleware to set a response header key/value |
|
||||||
|
| [StripSlashes] | Strip slashes on routing paths |
|
||||||
|
| [Throttle] | Puts a ceiling on the number of concurrent requests |
|
||||||
|
| [Timeout] | Signals to the request context when the timeout deadline is reached |
|
||||||
|
| [URLFormat] | Parse extension from url and put it on request context |
|
||||||
|
| [WithValue] | Short-hand middleware to set a key/value on the request context |
|
||||||
|
----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[AllowContentEncoding]: https://pkg.go.dev/github.com/go-chi/chi/middleware#AllowContentEncoding
|
||||||
|
[AllowContentType]: https://pkg.go.dev/github.com/go-chi/chi/middleware#AllowContentType
|
||||||
|
[BasicAuth]: https://pkg.go.dev/github.com/go-chi/chi/middleware#BasicAuth
|
||||||
|
[Compress]: https://pkg.go.dev/github.com/go-chi/chi/middleware#Compress
|
||||||
|
[ContentCharset]: https://pkg.go.dev/github.com/go-chi/chi/middleware#ContentCharset
|
||||||
|
[CleanPath]: https://pkg.go.dev/github.com/go-chi/chi/middleware#CleanPath
|
||||||
|
[GetHead]: https://pkg.go.dev/github.com/go-chi/chi/middleware#GetHead
|
||||||
|
[GetReqID]: https://pkg.go.dev/github.com/go-chi/chi/middleware#GetReqID
|
||||||
|
[Heartbeat]: https://pkg.go.dev/github.com/go-chi/chi/middleware#Heartbeat
|
||||||
|
[Logger]: https://pkg.go.dev/github.com/go-chi/chi/middleware#Logger
|
||||||
|
[NoCache]: https://pkg.go.dev/github.com/go-chi/chi/middleware#NoCache
|
||||||
|
[Profiler]: https://pkg.go.dev/github.com/go-chi/chi/middleware#Profiler
|
||||||
|
[RealIP]: https://pkg.go.dev/github.com/go-chi/chi/middleware#RealIP
|
||||||
|
[Recoverer]: https://pkg.go.dev/github.com/go-chi/chi/middleware#Recoverer
|
||||||
|
[RedirectSlashes]: https://pkg.go.dev/github.com/go-chi/chi/middleware#RedirectSlashes
|
||||||
|
[RequestLogger]: https://pkg.go.dev/github.com/go-chi/chi/middleware#RequestLogger
|
||||||
|
[RequestID]: https://pkg.go.dev/github.com/go-chi/chi/middleware#RequestID
|
||||||
|
[RouteHeaders]: https://pkg.go.dev/github.com/go-chi/chi/middleware#RouteHeaders
|
||||||
|
[SetHeader]: https://pkg.go.dev/github.com/go-chi/chi/middleware#SetHeader
|
||||||
|
[StripSlashes]: https://pkg.go.dev/github.com/go-chi/chi/middleware#StripSlashes
|
||||||
|
[Throttle]: https://pkg.go.dev/github.com/go-chi/chi/middleware#Throttle
|
||||||
|
[ThrottleBacklog]: https://pkg.go.dev/github.com/go-chi/chi/middleware#ThrottleBacklog
|
||||||
|
[ThrottleWithOpts]: https://pkg.go.dev/github.com/go-chi/chi/middleware#ThrottleWithOpts
|
||||||
|
[Timeout]: https://pkg.go.dev/github.com/go-chi/chi/middleware#Timeout
|
||||||
|
[URLFormat]: https://pkg.go.dev/github.com/go-chi/chi/middleware#URLFormat
|
||||||
|
[WithLogEntry]: https://pkg.go.dev/github.com/go-chi/chi/middleware#WithLogEntry
|
||||||
|
[WithValue]: https://pkg.go.dev/github.com/go-chi/chi/middleware#WithValue
|
||||||
|
[Compressor]: https://pkg.go.dev/github.com/go-chi/chi/middleware#Compressor
|
||||||
|
[DefaultLogFormatter]: https://pkg.go.dev/github.com/go-chi/chi/middleware#DefaultLogFormatter
|
||||||
|
[EncoderFunc]: https://pkg.go.dev/github.com/go-chi/chi/middleware#EncoderFunc
|
||||||
|
[HeaderRoute]: https://pkg.go.dev/github.com/go-chi/chi/middleware#HeaderRoute
|
||||||
|
[HeaderRouter]: https://pkg.go.dev/github.com/go-chi/chi/middleware#HeaderRouter
|
||||||
|
[LogEntry]: https://pkg.go.dev/github.com/go-chi/chi/middleware#LogEntry
|
||||||
|
[LogFormatter]: https://pkg.go.dev/github.com/go-chi/chi/middleware#LogFormatter
|
||||||
|
[LoggerInterface]: https://pkg.go.dev/github.com/go-chi/chi/middleware#LoggerInterface
|
||||||
|
[ThrottleOpts]: https://pkg.go.dev/github.com/go-chi/chi/middleware#ThrottleOpts
|
||||||
|
[WrapResponseWriter]: https://pkg.go.dev/github.com/go-chi/chi/middleware#WrapResponseWriter
|
||||||
|
|
||||||
|
### Extra middlewares & packages
|
||||||
|
|
||||||
|
Please see https://github.com/go-chi for additional packages.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------------------------------------------
|
||||||
|
| package | description |
|
||||||
|
|:---------------------------------------------------|:-------------------------------------------------------------
|
||||||
|
| [cors](https://github.com/go-chi/cors) | Cross-origin resource sharing (CORS) |
|
||||||
|
| [docgen](https://github.com/go-chi/docgen) | Print chi.Router routes at runtime |
|
||||||
|
| [jwtauth](https://github.com/go-chi/jwtauth) | JWT authentication |
|
||||||
|
| [hostrouter](https://github.com/go-chi/hostrouter) | Domain/host based request routing |
|
||||||
|
| [httplog](https://github.com/go-chi/httplog) | Small but powerful structured HTTP request logging |
|
||||||
|
| [httprate](https://github.com/go-chi/httprate) | HTTP request rate limiter |
|
||||||
|
| [httptracer](https://github.com/go-chi/httptracer) | HTTP request performance tracing library |
|
||||||
|
| [httpvcr](https://github.com/go-chi/httpvcr) | Write deterministic tests for external sources |
|
||||||
|
| [stampede](https://github.com/go-chi/stampede) | HTTP request coalescer |
|
||||||
|
--------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
## context?
|
||||||
|
|
||||||
|
`context` is a tiny pkg that provides simple interface to signal context across call stacks
|
||||||
|
and goroutines. It was originally written by [Sameer Ajmani](https://github.com/Sajmani)
|
||||||
|
and is available in stdlib since go1.7.
|
||||||
|
|
||||||
|
Learn more at https://blog.golang.org/context
|
||||||
|
|
||||||
|
and..
|
||||||
|
* Docs: https://golang.org/pkg/context
|
||||||
|
* Source: https://github.com/golang/go/tree/master/src/context
|
||||||
|
|
||||||
|
|
||||||
|
## Benchmarks
|
||||||
|
|
||||||
|
The benchmark suite: https://github.com/pkieltyka/go-http-routing-benchmark
|
||||||
|
|
||||||
|
Results as of Nov 29, 2020 with Go 1.15.5 on Linux AMD 3950x
|
||||||
|
|
||||||
|
```shell
|
||||||
|
BenchmarkChi_Param 3075895 384 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_Param5 2116603 566 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_Param20 964117 1227 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_ParamWrite 2863413 420 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_GithubStatic 3045488 395 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_GithubParam 2204115 540 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_GithubAll 10000 113811 ns/op 81203 B/op 406 allocs/op
|
||||||
|
BenchmarkChi_GPlusStatic 3337485 359 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_GPlusParam 2825853 423 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_GPlus2Params 2471697 483 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_GPlusAll 194220 5950 ns/op 5200 B/op 26 allocs/op
|
||||||
|
BenchmarkChi_ParseStatic 3365324 356 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_ParseParam 2976614 404 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_Parse2Params 2638084 439 ns/op 400 B/op 2 allocs/op
|
||||||
|
BenchmarkChi_ParseAll 109567 11295 ns/op 10400 B/op 52 allocs/op
|
||||||
|
BenchmarkChi_StaticAll 16846 71308 ns/op 62802 B/op 314 allocs/op
|
||||||
|
```
|
||||||
|
|
||||||
|
Comparison with other routers: https://gist.github.com/pkieltyka/123032f12052520aaccab752bd3e78cc
|
||||||
|
|
||||||
|
NOTE: the allocs in the benchmark above are from the calls to http.Request's
|
||||||
|
`WithContext(context.Context)` method that clones the http.Request, sets the `Context()`
|
||||||
|
on the duplicated (alloc'd) request and returns it the new request object. This is just
|
||||||
|
how setting context on a request in Go works.
|
||||||
|
|
||||||
|
|
||||||
|
## Go module support & note on chi's versioning
|
||||||
|
|
||||||
|
* Go.mod support means we reset our versioning starting from v1.5 (see [CHANGELOG](https://github.com/go-chi/chi/blob/master/CHANGELOG.md#v150-2020-11-12---now-with-gomod-support))
|
||||||
|
* All older tags are preserved, are backwards-compatible and will "just work" as they
|
||||||
|
* Brand new systems can run `go get -u github.com/go-chi/chi` as normal, or `go get -u github.com/go-chi/chi@latest`
|
||||||
|
to install chi, which will install v1.x+ built with go.mod support, starting from v1.5.0.
|
||||||
|
* For existing projects who want to upgrade to the latest go.mod version, run: `go get -u github.com/go-chi/chi@v1.5.0`,
|
||||||
|
which will get you on the go.mod version line (as Go's mod cache may still remember v4.x).
|
||||||
|
* Any breaking changes will bump a "minor" release and backwards-compatible improvements/fixes will bump a "tiny" release.
|
||||||
|
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
* Carl Jackson for https://github.com/zenazn/goji
|
||||||
|
* Parts of chi's thinking comes from goji, and chi's middleware package
|
||||||
|
sources from goji.
|
||||||
|
* Armon Dadgar for https://github.com/armon/go-radix
|
||||||
|
* Contributions: [@VojtechVitek](https://github.com/VojtechVitek)
|
||||||
|
|
||||||
|
We'll be more than happy to see [your contributions](./CONTRIBUTING.md)!
|
||||||
|
|
||||||
|
|
||||||
|
## Beyond REST
|
||||||
|
|
||||||
|
chi is just a http router that lets you decompose request handling into many smaller layers.
|
||||||
|
Many companies use chi to write REST services for their public APIs. But, REST is just a convention
|
||||||
|
for managing state via HTTP, and there's a lot of other pieces required to write a complete client-server
|
||||||
|
system or network of microservices.
|
||||||
|
|
||||||
|
Looking beyond REST, I also recommend some newer works in the field:
|
||||||
|
* [webrpc](https://github.com/webrpc/webrpc) - Web-focused RPC client+server framework with code-gen
|
||||||
|
* [gRPC](https://github.com/grpc/grpc-go) - Google's RPC framework via protobufs
|
||||||
|
* [graphql](https://github.com/99designs/gqlgen) - Declarative query language
|
||||||
|
* [NATS](https://nats.io) - lightweight pub-sub
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright (c) 2015-present [Peter Kieltyka](https://github.com/pkieltyka)
|
||||||
|
|
||||||
|
Licensed under [MIT License](./LICENSE)
|
||||||
|
|
||||||
|
[GoDoc]: https://pkg.go.dev/github.com/go-chi/chi?tab=versions
|
||||||
|
[GoDoc Widget]: https://godoc.org/github.com/go-chi/chi?status.svg
|
||||||
|
[Travis]: https://travis-ci.org/go-chi/chi
|
||||||
|
[Travis Widget]: https://travis-ci.org/go-chi/chi.svg?branch=master
|
||||||
49
vendor/github.com/go-chi/chi/v5/chain.go
generated
vendored
Normal file
49
vendor/github.com/go-chi/chi/v5/chain.go
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
package chi
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
// Chain returns a Middlewares type from a slice of middleware handlers.
|
||||||
|
func Chain(middlewares ...func(http.Handler) http.Handler) Middlewares {
|
||||||
|
return Middlewares(middlewares)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler builds and returns a http.Handler from the chain of middlewares,
|
||||||
|
// with `h http.Handler` as the final handler.
|
||||||
|
func (mws Middlewares) Handler(h http.Handler) http.Handler {
|
||||||
|
return &ChainHandler{mws, h, chain(mws, h)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandlerFunc builds and returns a http.Handler from the chain of middlewares,
|
||||||
|
// with `h http.Handler` as the final handler.
|
||||||
|
func (mws Middlewares) HandlerFunc(h http.HandlerFunc) http.Handler {
|
||||||
|
return &ChainHandler{mws, h, chain(mws, h)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainHandler is a http.Handler with support for handler composition and
|
||||||
|
// execution.
|
||||||
|
type ChainHandler struct {
|
||||||
|
Middlewares Middlewares
|
||||||
|
Endpoint http.Handler
|
||||||
|
chain http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChainHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
c.chain.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// chain builds a http.Handler composed of an inline middleware stack and endpoint
|
||||||
|
// handler in the order they are passed.
|
||||||
|
func chain(middlewares []func(http.Handler) http.Handler, endpoint http.Handler) http.Handler {
|
||||||
|
// Return ahead of time if there aren't any middlewares for the chain
|
||||||
|
if len(middlewares) == 0 {
|
||||||
|
return endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap the end handler with the middleware chain
|
||||||
|
h := middlewares[len(middlewares)-1](endpoint)
|
||||||
|
for i := len(middlewares) - 2; i >= 0; i-- {
|
||||||
|
h = middlewares[i](h)
|
||||||
|
}
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
134
vendor/github.com/go-chi/chi/v5/chi.go
generated
vendored
Normal file
134
vendor/github.com/go-chi/chi/v5/chi.go
generated
vendored
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
//
|
||||||
|
// Package chi is a small, idiomatic and composable router for building HTTP services.
|
||||||
|
//
|
||||||
|
// chi requires Go 1.10 or newer.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// package main
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "net/http"
|
||||||
|
//
|
||||||
|
// "github.com/go-chi/chi/v5"
|
||||||
|
// "github.com/go-chi/chi/v5/middleware"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// func main() {
|
||||||
|
// r := chi.NewRouter()
|
||||||
|
// r.Use(middleware.Logger)
|
||||||
|
// r.Use(middleware.Recoverer)
|
||||||
|
//
|
||||||
|
// r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// w.Write([]byte("root."))
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// http.ListenAndServe(":3333", r)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// See github.com/go-chi/chi/_examples/ for more in-depth examples.
|
||||||
|
//
|
||||||
|
// URL patterns allow for easy matching of path components in HTTP
|
||||||
|
// requests. The matching components can then be accessed using
|
||||||
|
// chi.URLParam(). All patterns must begin with a slash.
|
||||||
|
//
|
||||||
|
// A simple named placeholder {name} matches any sequence of characters
|
||||||
|
// up to the next / or the end of the URL. Trailing slashes on paths must
|
||||||
|
// be handled explicitly.
|
||||||
|
//
|
||||||
|
// A placeholder with a name followed by a colon allows a regular
|
||||||
|
// expression match, for example {number:\\d+}. The regular expression
|
||||||
|
// syntax is Go's normal regexp RE2 syntax, except that regular expressions
|
||||||
|
// including { or } are not supported, and / will never be
|
||||||
|
// matched. An anonymous regexp pattern is allowed, using an empty string
|
||||||
|
// before the colon in the placeholder, such as {:\\d+}
|
||||||
|
//
|
||||||
|
// The special placeholder of asterisk matches the rest of the requested
|
||||||
|
// URL. Any trailing characters in the pattern are ignored. This is the only
|
||||||
|
// placeholder which will match / characters.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
// "/user/{name}" matches "/user/jsmith" but not "/user/jsmith/info" or "/user/jsmith/"
|
||||||
|
// "/user/{name}/info" matches "/user/jsmith/info"
|
||||||
|
// "/page/*" matches "/page/intro/latest"
|
||||||
|
// "/page/*/index" also matches "/page/intro/latest"
|
||||||
|
// "/date/{yyyy:\\d\\d\\d\\d}/{mm:\\d\\d}/{dd:\\d\\d}" matches "/date/2017/04/01"
|
||||||
|
//
|
||||||
|
package chi
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
// NewRouter returns a new Mux object that implements the Router interface.
|
||||||
|
func NewRouter() *Mux {
|
||||||
|
return NewMux()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Router consisting of the core routing methods used by chi's Mux,
|
||||||
|
// using only the standard net/http.
|
||||||
|
type Router interface {
|
||||||
|
http.Handler
|
||||||
|
Routes
|
||||||
|
|
||||||
|
// Use appends one or more middlewares onto the Router stack.
|
||||||
|
Use(middlewares ...func(http.Handler) http.Handler)
|
||||||
|
|
||||||
|
// With adds inline middlewares for an endpoint handler.
|
||||||
|
With(middlewares ...func(http.Handler) http.Handler) Router
|
||||||
|
|
||||||
|
// Group adds a new inline-Router along the current routing
|
||||||
|
// path, with a fresh middleware stack for the inline-Router.
|
||||||
|
Group(fn func(r Router)) Router
|
||||||
|
|
||||||
|
// Route mounts a sub-Router along a `pattern`` string.
|
||||||
|
Route(pattern string, fn func(r Router)) Router
|
||||||
|
|
||||||
|
// Mount attaches another http.Handler along ./pattern/*
|
||||||
|
Mount(pattern string, h http.Handler)
|
||||||
|
|
||||||
|
// Handle and HandleFunc adds routes for `pattern` that matches
|
||||||
|
// all HTTP methods.
|
||||||
|
Handle(pattern string, h http.Handler)
|
||||||
|
HandleFunc(pattern string, h http.HandlerFunc)
|
||||||
|
|
||||||
|
// Method and MethodFunc adds routes for `pattern` that matches
|
||||||
|
// the `method` HTTP method.
|
||||||
|
Method(method, pattern string, h http.Handler)
|
||||||
|
MethodFunc(method, pattern string, h http.HandlerFunc)
|
||||||
|
|
||||||
|
// HTTP-method routing along `pattern`
|
||||||
|
Connect(pattern string, h http.HandlerFunc)
|
||||||
|
Delete(pattern string, h http.HandlerFunc)
|
||||||
|
Get(pattern string, h http.HandlerFunc)
|
||||||
|
Head(pattern string, h http.HandlerFunc)
|
||||||
|
Options(pattern string, h http.HandlerFunc)
|
||||||
|
Patch(pattern string, h http.HandlerFunc)
|
||||||
|
Post(pattern string, h http.HandlerFunc)
|
||||||
|
Put(pattern string, h http.HandlerFunc)
|
||||||
|
Trace(pattern string, h http.HandlerFunc)
|
||||||
|
|
||||||
|
// NotFound defines a handler to respond whenever a route could
|
||||||
|
// not be found.
|
||||||
|
NotFound(h http.HandlerFunc)
|
||||||
|
|
||||||
|
// MethodNotAllowed defines a handler to respond whenever a method is
|
||||||
|
// not allowed.
|
||||||
|
MethodNotAllowed(h http.HandlerFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routes interface adds two methods for router traversal, which is also
|
||||||
|
// used by the `docgen` subpackage to generation documentation for Routers.
|
||||||
|
type Routes interface {
|
||||||
|
// Routes returns the routing tree in an easily traversable structure.
|
||||||
|
Routes() []Route
|
||||||
|
|
||||||
|
// Middlewares returns the list of middlewares in use by the router.
|
||||||
|
Middlewares() Middlewares
|
||||||
|
|
||||||
|
// Match searches the routing tree for a handler that matches
|
||||||
|
// the method/path - similar to routing a http request, but without
|
||||||
|
// executing the handler thereafter.
|
||||||
|
Match(rctx *Context, method, path string) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Middlewares type is a slice of standard middleware handlers with methods
|
||||||
|
// to compose middleware chains and http.Handler's.
|
||||||
|
type Middlewares []func(http.Handler) http.Handler
|
||||||
157
vendor/github.com/go-chi/chi/v5/context.go
generated
vendored
Normal file
157
vendor/github.com/go-chi/chi/v5/context.go
generated
vendored
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
package chi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// URLParam returns the url parameter from a http.Request object.
|
||||||
|
func URLParam(r *http.Request, key string) string {
|
||||||
|
if rctx := RouteContext(r.Context()); rctx != nil {
|
||||||
|
return rctx.URLParam(key)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// URLParamFromCtx returns the url parameter from a http.Request Context.
|
||||||
|
func URLParamFromCtx(ctx context.Context, key string) string {
|
||||||
|
if rctx := RouteContext(ctx); rctx != nil {
|
||||||
|
return rctx.URLParam(key)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// RouteContext returns chi's routing Context object from a
|
||||||
|
// http.Request Context.
|
||||||
|
func RouteContext(ctx context.Context) *Context {
|
||||||
|
val, _ := ctx.Value(RouteCtxKey).(*Context)
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRouteContext returns a new routing Context object.
|
||||||
|
func NewRouteContext() *Context {
|
||||||
|
return &Context{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// RouteCtxKey is the context.Context key to store the request context.
|
||||||
|
RouteCtxKey = &contextKey{"RouteContext"}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Context is the default routing context set on the root node of a
|
||||||
|
// request context to track route patterns, URL parameters and
|
||||||
|
// an optional routing path.
|
||||||
|
type Context struct {
|
||||||
|
Routes Routes
|
||||||
|
|
||||||
|
// Routing path/method override used during the route search.
|
||||||
|
// See Mux#routeHTTP method.
|
||||||
|
RoutePath string
|
||||||
|
RouteMethod string
|
||||||
|
|
||||||
|
// Routing pattern stack throughout the lifecycle of the request,
|
||||||
|
// across all connected routers. It is a record of all matching
|
||||||
|
// patterns across a stack of sub-routers.
|
||||||
|
RoutePatterns []string
|
||||||
|
|
||||||
|
// URLParams are the stack of routeParams captured during the
|
||||||
|
// routing lifecycle across a stack of sub-routers.
|
||||||
|
URLParams RouteParams
|
||||||
|
|
||||||
|
// The endpoint routing pattern that matched the request URI path
|
||||||
|
// or `RoutePath` of the current sub-router. This value will update
|
||||||
|
// during the lifecycle of a request passing through a stack of
|
||||||
|
// sub-routers.
|
||||||
|
routePattern string
|
||||||
|
|
||||||
|
// Route parameters matched for the current sub-router. It is
|
||||||
|
// intentionally unexported so it cant be tampered.
|
||||||
|
routeParams RouteParams
|
||||||
|
|
||||||
|
// methodNotAllowed hint
|
||||||
|
methodNotAllowed bool
|
||||||
|
|
||||||
|
// parentCtx is the parent of this one, for using Context as a
|
||||||
|
// context.Context directly. This is an optimization that saves
|
||||||
|
// 1 allocation.
|
||||||
|
parentCtx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset a routing context to its initial state.
|
||||||
|
func (x *Context) Reset() {
|
||||||
|
x.Routes = nil
|
||||||
|
x.RoutePath = ""
|
||||||
|
x.RouteMethod = ""
|
||||||
|
x.RoutePatterns = x.RoutePatterns[:0]
|
||||||
|
x.URLParams.Keys = x.URLParams.Keys[:0]
|
||||||
|
x.URLParams.Values = x.URLParams.Values[:0]
|
||||||
|
|
||||||
|
x.routePattern = ""
|
||||||
|
x.routeParams.Keys = x.routeParams.Keys[:0]
|
||||||
|
x.routeParams.Values = x.routeParams.Values[:0]
|
||||||
|
x.methodNotAllowed = false
|
||||||
|
x.parentCtx = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// URLParam returns the corresponding URL parameter value from the request
|
||||||
|
// routing context.
|
||||||
|
func (x *Context) URLParam(key string) string {
|
||||||
|
for k := len(x.URLParams.Keys) - 1; k >= 0; k-- {
|
||||||
|
if x.URLParams.Keys[k] == key {
|
||||||
|
return x.URLParams.Values[k]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoutePattern builds the routing pattern string for the particular
|
||||||
|
// request, at the particular point during routing. This means, the value
|
||||||
|
// will change throughout the execution of a request in a router. That is
|
||||||
|
// why its advised to only use this value after calling the next handler.
|
||||||
|
//
|
||||||
|
// For example,
|
||||||
|
//
|
||||||
|
// func Instrument(next http.Handler) http.Handler {
|
||||||
|
// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// next.ServeHTTP(w, r)
|
||||||
|
// routePattern := chi.RouteContext(r.Context()).RoutePattern()
|
||||||
|
// measure(w, r, routePattern)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
func (x *Context) RoutePattern() string {
|
||||||
|
routePattern := strings.Join(x.RoutePatterns, "")
|
||||||
|
return replaceWildcards(routePattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaceWildcards takes a route pattern and recursively replaces all
|
||||||
|
// occurrences of "/*/" to "/".
|
||||||
|
func replaceWildcards(p string) string {
|
||||||
|
if strings.Contains(p, "/*/") {
|
||||||
|
return replaceWildcards(strings.Replace(p, "/*/", "/", -1))
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// RouteParams is a structure to track URL routing parameters efficiently.
|
||||||
|
type RouteParams struct {
|
||||||
|
Keys, Values []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add will append a URL parameter to the end of the route param
|
||||||
|
func (s *RouteParams) Add(key, value string) {
|
||||||
|
s.Keys = append(s.Keys, key)
|
||||||
|
s.Values = append(s.Values, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// contextKey is a value for use with context.WithValue. It's used as
|
||||||
|
// a pointer so it fits in an interface{} without allocation. This technique
|
||||||
|
// for defining context keys was copied from Go 1.7's new use of context in net/http.
|
||||||
|
type contextKey struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *contextKey) String() string {
|
||||||
|
return "chi context value " + k.name
|
||||||
|
}
|
||||||
33
vendor/github.com/go-chi/chi/v5/middleware/basic_auth.go
generated
vendored
Normal file
33
vendor/github.com/go-chi/chi/v5/middleware/basic_auth.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BasicAuth implements a simple middleware handler for adding basic http auth to a route.
|
||||||
|
func BasicAuth(realm string, creds map[string]string) func(next http.Handler) http.Handler {
|
||||||
|
return func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
user, pass, ok := r.BasicAuth()
|
||||||
|
if !ok {
|
||||||
|
basicAuthFailed(w, realm)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
credPass, credUserOk := creds[user]
|
||||||
|
if !credUserOk || subtle.ConstantTimeCompare([]byte(pass), []byte(credPass)) != 1 {
|
||||||
|
basicAuthFailed(w, realm)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func basicAuthFailed(w http.ResponseWriter, realm string) {
|
||||||
|
w.Header().Add("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s"`, realm))
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
}
|
||||||
28
vendor/github.com/go-chi/chi/v5/middleware/clean_path.go
generated
vendored
Normal file
28
vendor/github.com/go-chi/chi/v5/middleware/clean_path.go
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CleanPath middleware will clean out double slash mistakes from a user's request path.
|
||||||
|
// For example, if a user requests /users//1 or //users////1 will both be treated as: /users/1
|
||||||
|
func CleanPath(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
rctx := chi.RouteContext(r.Context())
|
||||||
|
|
||||||
|
routePath := rctx.RoutePath
|
||||||
|
if routePath == "" {
|
||||||
|
if r.URL.RawPath != "" {
|
||||||
|
routePath = r.URL.RawPath
|
||||||
|
} else {
|
||||||
|
routePath = r.URL.Path
|
||||||
|
}
|
||||||
|
rctx.RoutePath = path.Clean(routePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
399
vendor/github.com/go-chi/chi/v5/middleware/compress.go
generated
vendored
Normal file
399
vendor/github.com/go-chi/chi/v5/middleware/compress.go
generated
vendored
Normal file
|
|
@ -0,0 +1,399 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"compress/flate"
|
||||||
|
"compress/gzip"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultCompressibleContentTypes = []string{
|
||||||
|
"text/html",
|
||||||
|
"text/css",
|
||||||
|
"text/plain",
|
||||||
|
"text/javascript",
|
||||||
|
"application/javascript",
|
||||||
|
"application/x-javascript",
|
||||||
|
"application/json",
|
||||||
|
"application/atom+xml",
|
||||||
|
"application/rss+xml",
|
||||||
|
"image/svg+xml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compress is a middleware that compresses response
|
||||||
|
// body of a given content types to a data format based
|
||||||
|
// on Accept-Encoding request header. It uses a given
|
||||||
|
// compression level.
|
||||||
|
//
|
||||||
|
// NOTE: make sure to set the Content-Type header on your response
|
||||||
|
// otherwise this middleware will not compress the response body. For ex, in
|
||||||
|
// your handler you should set w.Header().Set("Content-Type", http.DetectContentType(yourBody))
|
||||||
|
// or set it manually.
|
||||||
|
//
|
||||||
|
// Passing a compression level of 5 is sensible value
|
||||||
|
func Compress(level int, types ...string) func(next http.Handler) http.Handler {
|
||||||
|
compressor := NewCompressor(level, types...)
|
||||||
|
return compressor.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compressor represents a set of encoding configurations.
|
||||||
|
type Compressor struct {
|
||||||
|
level int // The compression level.
|
||||||
|
// The mapping of encoder names to encoder functions.
|
||||||
|
encoders map[string]EncoderFunc
|
||||||
|
// The mapping of pooled encoders to pools.
|
||||||
|
pooledEncoders map[string]*sync.Pool
|
||||||
|
// The set of content types allowed to be compressed.
|
||||||
|
allowedTypes map[string]struct{}
|
||||||
|
allowedWildcards map[string]struct{}
|
||||||
|
// The list of encoders in order of decreasing precedence.
|
||||||
|
encodingPrecedence []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCompressor creates a new Compressor that will handle encoding responses.
|
||||||
|
//
|
||||||
|
// The level should be one of the ones defined in the flate package.
|
||||||
|
// The types are the content types that are allowed to be compressed.
|
||||||
|
func NewCompressor(level int, types ...string) *Compressor {
|
||||||
|
// If types are provided, set those as the allowed types. If none are
|
||||||
|
// provided, use the default list.
|
||||||
|
allowedTypes := make(map[string]struct{})
|
||||||
|
allowedWildcards := make(map[string]struct{})
|
||||||
|
if len(types) > 0 {
|
||||||
|
for _, t := range types {
|
||||||
|
if strings.Contains(strings.TrimSuffix(t, "/*"), "*") {
|
||||||
|
panic(fmt.Sprintf("middleware/compress: Unsupported content-type wildcard pattern '%s'. Only '/*' supported", t))
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(t, "/*") {
|
||||||
|
allowedWildcards[strings.TrimSuffix(t, "/*")] = struct{}{}
|
||||||
|
} else {
|
||||||
|
allowedTypes[t] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, t := range defaultCompressibleContentTypes {
|
||||||
|
allowedTypes[t] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &Compressor{
|
||||||
|
level: level,
|
||||||
|
encoders: make(map[string]EncoderFunc),
|
||||||
|
pooledEncoders: make(map[string]*sync.Pool),
|
||||||
|
allowedTypes: allowedTypes,
|
||||||
|
allowedWildcards: allowedWildcards,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the default encoders. The precedence order uses the reverse
|
||||||
|
// ordering that the encoders were added. This means adding new encoders
|
||||||
|
// will move them to the front of the order.
|
||||||
|
//
|
||||||
|
// TODO:
|
||||||
|
// lzma: Opera.
|
||||||
|
// sdch: Chrome, Android. Gzip output + dictionary header.
|
||||||
|
// br: Brotli, see https://github.com/go-chi/chi/pull/326
|
||||||
|
|
||||||
|
// HTTP 1.1 "deflate" (RFC 2616) stands for DEFLATE data (RFC 1951)
|
||||||
|
// wrapped with zlib (RFC 1950). The zlib wrapper uses Adler-32
|
||||||
|
// checksum compared to CRC-32 used in "gzip" and thus is faster.
|
||||||
|
//
|
||||||
|
// But.. some old browsers (MSIE, Safari 5.1) incorrectly expect
|
||||||
|
// raw DEFLATE data only, without the mentioned zlib wrapper.
|
||||||
|
// Because of this major confusion, most modern browsers try it
|
||||||
|
// both ways, first looking for zlib headers.
|
||||||
|
// Quote by Mark Adler: http://stackoverflow.com/a/9186091/385548
|
||||||
|
//
|
||||||
|
// The list of browsers having problems is quite big, see:
|
||||||
|
// http://zoompf.com/blog/2012/02/lose-the-wait-http-compression
|
||||||
|
// https://web.archive.org/web/20120321182910/http://www.vervestudios.co/projects/compression-tests/results
|
||||||
|
//
|
||||||
|
// That's why we prefer gzip over deflate. It's just more reliable
|
||||||
|
// and not significantly slower than gzip.
|
||||||
|
c.SetEncoder("deflate", encoderDeflate)
|
||||||
|
|
||||||
|
// TODO: Exception for old MSIE browsers that can't handle non-HTML?
|
||||||
|
// https://zoompf.com/blog/2012/02/lose-the-wait-http-compression
|
||||||
|
c.SetEncoder("gzip", encoderGzip)
|
||||||
|
|
||||||
|
// NOTE: Not implemented, intentionally:
|
||||||
|
// case "compress": // LZW. Deprecated.
|
||||||
|
// case "bzip2": // Too slow on-the-fly.
|
||||||
|
// case "zopfli": // Too slow on-the-fly.
|
||||||
|
// case "xz": // Too slow on-the-fly.
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEncoder can be used to set the implementation of a compression algorithm.
|
||||||
|
//
|
||||||
|
// The encoding should be a standardised identifier. See:
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
|
||||||
|
//
|
||||||
|
// For example, add the Brotli algortithm:
|
||||||
|
//
|
||||||
|
// import brotli_enc "gopkg.in/kothar/brotli-go.v0/enc"
|
||||||
|
//
|
||||||
|
// compressor := middleware.NewCompressor(5, "text/html")
|
||||||
|
// compressor.SetEncoder("br", func(w http.ResponseWriter, level int) io.Writer {
|
||||||
|
// params := brotli_enc.NewBrotliParams()
|
||||||
|
// params.SetQuality(level)
|
||||||
|
// return brotli_enc.NewBrotliWriter(params, w)
|
||||||
|
// })
|
||||||
|
func (c *Compressor) SetEncoder(encoding string, fn EncoderFunc) {
|
||||||
|
encoding = strings.ToLower(encoding)
|
||||||
|
if encoding == "" {
|
||||||
|
panic("the encoding can not be empty")
|
||||||
|
}
|
||||||
|
if fn == nil {
|
||||||
|
panic("attempted to set a nil encoder function")
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are adding a new encoder that is already registered, we have to
|
||||||
|
// clear that one out first.
|
||||||
|
if _, ok := c.pooledEncoders[encoding]; ok {
|
||||||
|
delete(c.pooledEncoders, encoding)
|
||||||
|
}
|
||||||
|
if _, ok := c.encoders[encoding]; ok {
|
||||||
|
delete(c.encoders, encoding)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the encoder supports Resetting (IoReseterWriter), then it can be pooled.
|
||||||
|
encoder := fn(ioutil.Discard, c.level)
|
||||||
|
if encoder != nil {
|
||||||
|
if _, ok := encoder.(ioResetterWriter); ok {
|
||||||
|
pool := &sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return fn(ioutil.Discard, c.level)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c.pooledEncoders[encoding] = pool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the encoder is not in the pooledEncoders, add it to the normal encoders.
|
||||||
|
if _, ok := c.pooledEncoders[encoding]; !ok {
|
||||||
|
c.encoders[encoding] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v := range c.encodingPrecedence {
|
||||||
|
if v == encoding {
|
||||||
|
c.encodingPrecedence = append(c.encodingPrecedence[:i], c.encodingPrecedence[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.encodingPrecedence = append([]string{encoding}, c.encodingPrecedence...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler returns a new middleware that will compress the response based on the
|
||||||
|
// current Compressor.
|
||||||
|
func (c *Compressor) Handler(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
encoder, encoding, cleanup := c.selectEncoder(r.Header, w)
|
||||||
|
|
||||||
|
cw := &compressResponseWriter{
|
||||||
|
ResponseWriter: w,
|
||||||
|
w: w,
|
||||||
|
contentTypes: c.allowedTypes,
|
||||||
|
contentWildcards: c.allowedWildcards,
|
||||||
|
encoding: encoding,
|
||||||
|
compressable: false, // determined in post-handler
|
||||||
|
}
|
||||||
|
if encoder != nil {
|
||||||
|
cw.w = encoder
|
||||||
|
}
|
||||||
|
// Re-add the encoder to the pool if applicable.
|
||||||
|
defer cleanup()
|
||||||
|
defer cw.Close()
|
||||||
|
|
||||||
|
next.ServeHTTP(cw, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// selectEncoder returns the encoder, the name of the encoder, and a closer function.
|
||||||
|
func (c *Compressor) selectEncoder(h http.Header, w io.Writer) (io.Writer, string, func()) {
|
||||||
|
header := h.Get("Accept-Encoding")
|
||||||
|
|
||||||
|
// Parse the names of all accepted algorithms from the header.
|
||||||
|
accepted := strings.Split(strings.ToLower(header), ",")
|
||||||
|
|
||||||
|
// Find supported encoder by accepted list by precedence
|
||||||
|
for _, name := range c.encodingPrecedence {
|
||||||
|
if matchAcceptEncoding(accepted, name) {
|
||||||
|
if pool, ok := c.pooledEncoders[name]; ok {
|
||||||
|
encoder := pool.Get().(ioResetterWriter)
|
||||||
|
cleanup := func() {
|
||||||
|
pool.Put(encoder)
|
||||||
|
}
|
||||||
|
encoder.Reset(w)
|
||||||
|
return encoder, name, cleanup
|
||||||
|
|
||||||
|
}
|
||||||
|
if fn, ok := c.encoders[name]; ok {
|
||||||
|
return fn(w, c.level), name, func() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// No encoder found to match the accepted encoding
|
||||||
|
return nil, "", func() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchAcceptEncoding(accepted []string, encoding string) bool {
|
||||||
|
for _, v := range accepted {
|
||||||
|
if strings.Contains(v, encoding) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// An EncoderFunc is a function that wraps the provided io.Writer with a
|
||||||
|
// streaming compression algorithm and returns it.
|
||||||
|
//
|
||||||
|
// In case of failure, the function should return nil.
|
||||||
|
type EncoderFunc func(w io.Writer, level int) io.Writer
|
||||||
|
|
||||||
|
// Interface for types that allow resetting io.Writers.
|
||||||
|
type ioResetterWriter interface {
|
||||||
|
io.Writer
|
||||||
|
Reset(w io.Writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
type compressResponseWriter struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
|
||||||
|
// The streaming encoder writer to be used if there is one. Otherwise,
|
||||||
|
// this is just the normal writer.
|
||||||
|
w io.Writer
|
||||||
|
encoding string
|
||||||
|
contentTypes map[string]struct{}
|
||||||
|
contentWildcards map[string]struct{}
|
||||||
|
wroteHeader bool
|
||||||
|
compressable bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *compressResponseWriter) isCompressable() bool {
|
||||||
|
// Parse the first part of the Content-Type response header.
|
||||||
|
contentType := cw.Header().Get("Content-Type")
|
||||||
|
if idx := strings.Index(contentType, ";"); idx >= 0 {
|
||||||
|
contentType = contentType[0:idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the content type compressable?
|
||||||
|
if _, ok := cw.contentTypes[contentType]; ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if idx := strings.Index(contentType, "/"); idx > 0 {
|
||||||
|
contentType = contentType[0:idx]
|
||||||
|
_, ok := cw.contentWildcards[contentType]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *compressResponseWriter) WriteHeader(code int) {
|
||||||
|
if cw.wroteHeader {
|
||||||
|
cw.ResponseWriter.WriteHeader(code) // Allow multiple calls to propagate.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cw.wroteHeader = true
|
||||||
|
defer cw.ResponseWriter.WriteHeader(code)
|
||||||
|
|
||||||
|
// Already compressed data?
|
||||||
|
if cw.Header().Get("Content-Encoding") != "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cw.isCompressable() {
|
||||||
|
cw.compressable = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if cw.encoding != "" {
|
||||||
|
cw.compressable = true
|
||||||
|
cw.Header().Set("Content-Encoding", cw.encoding)
|
||||||
|
cw.Header().Set("Vary", "Accept-Encoding")
|
||||||
|
|
||||||
|
// The content-length after compression is unknown
|
||||||
|
cw.Header().Del("Content-Length")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *compressResponseWriter) Write(p []byte) (int, error) {
|
||||||
|
if !cw.wroteHeader {
|
||||||
|
cw.WriteHeader(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cw.writer().Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *compressResponseWriter) writer() io.Writer {
|
||||||
|
if cw.compressable {
|
||||||
|
return cw.w
|
||||||
|
} else {
|
||||||
|
return cw.ResponseWriter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type compressFlusher interface {
|
||||||
|
Flush() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *compressResponseWriter) Flush() {
|
||||||
|
if f, ok := cw.writer().(http.Flusher); ok {
|
||||||
|
f.Flush()
|
||||||
|
}
|
||||||
|
// If the underlying writer has a compression flush signature,
|
||||||
|
// call this Flush() method instead
|
||||||
|
if f, ok := cw.writer().(compressFlusher); ok {
|
||||||
|
f.Flush()
|
||||||
|
|
||||||
|
// Also flush the underlying response writer
|
||||||
|
if f, ok := cw.ResponseWriter.(http.Flusher); ok {
|
||||||
|
f.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *compressResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
if hj, ok := cw.writer().(http.Hijacker); ok {
|
||||||
|
return hj.Hijack()
|
||||||
|
}
|
||||||
|
return nil, nil, errors.New("chi/middleware: http.Hijacker is unavailable on the writer")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *compressResponseWriter) Push(target string, opts *http.PushOptions) error {
|
||||||
|
if ps, ok := cw.writer().(http.Pusher); ok {
|
||||||
|
return ps.Push(target, opts)
|
||||||
|
}
|
||||||
|
return errors.New("chi/middleware: http.Pusher is unavailable on the writer")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *compressResponseWriter) Close() error {
|
||||||
|
if c, ok := cw.writer().(io.WriteCloser); ok {
|
||||||
|
return c.Close()
|
||||||
|
}
|
||||||
|
return errors.New("chi/middleware: io.WriteCloser is unavailable on the writer")
|
||||||
|
}
|
||||||
|
|
||||||
|
func encoderGzip(w io.Writer, level int) io.Writer {
|
||||||
|
gw, err := gzip.NewWriterLevel(w, level)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return gw
|
||||||
|
}
|
||||||
|
|
||||||
|
func encoderDeflate(w io.Writer, level int) io.Writer {
|
||||||
|
dw, err := flate.NewWriter(w, level)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return dw
|
||||||
|
}
|
||||||
51
vendor/github.com/go-chi/chi/v5/middleware/content_charset.go
generated
vendored
Normal file
51
vendor/github.com/go-chi/chi/v5/middleware/content_charset.go
generated
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContentCharset generates a handler that writes a 415 Unsupported Media Type response if none of the charsets match.
|
||||||
|
// An empty charset will allow requests with no Content-Type header or no specified charset.
|
||||||
|
func ContentCharset(charsets ...string) func(next http.Handler) http.Handler {
|
||||||
|
for i, c := range charsets {
|
||||||
|
charsets[i] = strings.ToLower(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !contentEncoding(r.Header.Get("Content-Type"), charsets...) {
|
||||||
|
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the content encoding against a list of acceptable values.
|
||||||
|
func contentEncoding(ce string, charsets ...string) bool {
|
||||||
|
_, ce = split(strings.ToLower(ce), ";")
|
||||||
|
_, ce = split(ce, "charset=")
|
||||||
|
ce, _ = split(ce, ";")
|
||||||
|
for _, c := range charsets {
|
||||||
|
if ce == c {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split a string in two parts, cleaning any whitespace.
|
||||||
|
func split(str, sep string) (string, string) {
|
||||||
|
var a, b string
|
||||||
|
var parts = strings.SplitN(str, sep, 2)
|
||||||
|
a = strings.TrimSpace(parts[0])
|
||||||
|
if len(parts) == 2 {
|
||||||
|
b = strings.TrimSpace(parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return a, b
|
||||||
|
}
|
||||||
34
vendor/github.com/go-chi/chi/v5/middleware/content_encoding.go
generated
vendored
Normal file
34
vendor/github.com/go-chi/chi/v5/middleware/content_encoding.go
generated
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllowContentEncoding enforces a whitelist of request Content-Encoding otherwise responds
|
||||||
|
// with a 415 Unsupported Media Type status.
|
||||||
|
func AllowContentEncoding(contentEncoding ...string) func(next http.Handler) http.Handler {
|
||||||
|
allowedEncodings := make(map[string]struct{}, len(contentEncoding))
|
||||||
|
for _, encoding := range contentEncoding {
|
||||||
|
allowedEncodings[strings.TrimSpace(strings.ToLower(encoding))] = struct{}{}
|
||||||
|
}
|
||||||
|
return func(next http.Handler) http.Handler {
|
||||||
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
requestEncodings := r.Header["Content-Encoding"]
|
||||||
|
// skip check for empty content body or no Content-Encoding
|
||||||
|
if r.ContentLength == 0 {
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// All encodings in the request must be allowed
|
||||||
|
for _, encoding := range requestEncodings {
|
||||||
|
if _, ok := allowedEncodings[strings.TrimSpace(strings.ToLower(encoding))]; !ok {
|
||||||
|
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
return http.HandlerFunc(fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue