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  }