github.com/puellanivis/breton@v0.2.16/lib/files/clipboard/clip_windows.go (about) 1 package clipboard 2 3 import ( 4 "net/url" 5 "os" 6 "os/exec" 7 "syscall" 8 "time" 9 "unsafe" 10 11 "github.com/puellanivis/breton/lib/files/wrapper" 12 ) 13 14 var ( 15 osdir = os.Getenv("SystemRoot") + "\\System32\\" 16 pasteCmd = []string{osdir + "WindowsPowerShell\\v1.0\\powershell.exe", "Get-Clipboard"} 17 copyCmd = []string{osdir + "clip.exe"} 18 selParam = []string{} 19 ) 20 21 const ( 22 cfUnicodetext = 13 23 ) 24 25 var ( 26 user32 = syscall.MustLoadDLL("user32") 27 openClipboard = user32.MustFindProc("OpenClipboard") 28 closeClipboard = user32.MustFindProc("CloseClipboard") 29 getClipboardData = user32.MustFindProc("GetClipboardData") 30 31 kernel32 = syscall.NewLazyDLL("kernel32") 32 globalLock = kernel32.NewProc("GlobalLock") 33 globalUnlock = kernel32.NewProc("GlobalUnlock") 34 ) 35 36 type winClip struct { 37 name *url.URL 38 } 39 40 var defaultClipboard clipboard = winClip{name: &url.URL{Scheme: "clipboard"}} 41 42 func init() { 43 clipboards[""] = defaultClipboard 44 } 45 46 func (c winClip) Read() ([]byte, error) { 47 r, _, err := openClipboard.Call(0) 48 if r == 0 { 49 return nil, err 50 } 51 defer closeClipboard.Call() 52 53 h, _, err := getClipboardData.Call(cfUnicodetext) 54 if r == 0 { 55 return nil, err 56 } 57 58 l, _, err := globalLock.Call(h) 59 if l == 0 { 60 return nil, err 61 } 62 defer globalUnlock.Call(h) 63 64 text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(l))[:]) 65 66 return []byte(text), nil 67 } 68 69 func (c winClip) Write(b []byte) error { 70 cmd := exec.Command(copyCmd[0]) 71 72 wr, err := cmd.StdinPipe() 73 if err != nil { 74 return err 75 } 76 77 if err := cmd.Start(); err != nil { 78 return err 79 } 80 81 if _, err := wr.Write(b); err != nil { 82 _ = wr.Close() // explicitly throwing away error here 83 return err 84 } 85 86 if err := wr.Close(); err != nil { 87 return err 88 } 89 90 return cmd.Wait() 91 } 92 93 func (c winClip) Stat() (os.FileInfo, error) { 94 uri := &url.URL{ 95 Scheme: "clipboard", 96 } 97 98 b, err := c.Read() 99 if err != nil { 100 return nil, err 101 } 102 103 return wrapper.NewInfo(uri, len(b), time.Now()), nil 104 }