OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / inconshreveable / mousetrap / trap_windows.go
1 // +build windows
2 // +build !go1.4
3
4 package mousetrap
5
6 import (
7         "fmt"
8         "os"
9         "syscall"
10         "unsafe"
11 )
12
13 const (
14         // defined by the Win32 API
15         th32cs_snapprocess uintptr = 0x2
16 )
17
18 var (
19         kernel                   = syscall.MustLoadDLL("kernel32.dll")
20         CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot")
21         Process32First           = kernel.MustFindProc("Process32FirstW")
22         Process32Next            = kernel.MustFindProc("Process32NextW")
23 )
24
25 // ProcessEntry32 structure defined by the Win32 API
26 type processEntry32 struct {
27         dwSize              uint32
28         cntUsage            uint32
29         th32ProcessID       uint32
30         th32DefaultHeapID   int
31         th32ModuleID        uint32
32         cntThreads          uint32
33         th32ParentProcessID uint32
34         pcPriClassBase      int32
35         dwFlags             uint32
36         szExeFile           [syscall.MAX_PATH]uint16
37 }
38
39 func getProcessEntry(pid int) (pe *processEntry32, err error) {
40         snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0))
41         if snapshot == uintptr(syscall.InvalidHandle) {
42                 err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1)
43                 return
44         }
45         defer syscall.CloseHandle(syscall.Handle(snapshot))
46
47         var processEntry processEntry32
48         processEntry.dwSize = uint32(unsafe.Sizeof(processEntry))
49         ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
50         if ok == 0 {
51                 err = fmt.Errorf("Process32First: %v", e1)
52                 return
53         }
54
55         for {
56                 if processEntry.th32ProcessID == uint32(pid) {
57                         pe = &processEntry
58                         return
59                 }
60
61                 ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
62                 if ok == 0 {
63                         err = fmt.Errorf("Process32Next: %v", e1)
64                         return
65                 }
66         }
67 }
68
69 func getppid() (pid int, err error) {
70         pe, err := getProcessEntry(os.Getpid())
71         if err != nil {
72                 return
73         }
74
75         pid = int(pe.th32ParentProcessID)
76         return
77 }
78
79 // StartedByExplorer returns true if the program was invoked by the user double-clicking
80 // on the executable from explorer.exe
81 //
82 // It is conservative and returns false if any of the internal calls fail.
83 // It does not guarantee that the program was run from a terminal. It only can tell you
84 // whether it was launched from explorer.exe
85 func StartedByExplorer() bool {
86         ppid, err := getppid()
87         if err != nil {
88                 return false
89         }
90
91         pe, err := getProcessEntry(ppid)
92         if err != nil {
93                 return false
94         }
95
96         name := syscall.UTF16ToString(pe.szExeFile[:])
97         return name == "explorer.exe"
98 }