package rdp import ( "io" "sync" "time" "unicode/utf16" ) const ( fastPathInputEventScancode = 0 fastPathInputEventMouse = 1 fastPathInputEventUnicode = 4 fastPathInputKBRelease = 0x01 fastPathInputKBExtended = 0x02 fastPathInputKBExtended1 = 0x04 ptrFlagsMove = 0x0800 ptrFlagsDown = 0x8000 ptrFlagsBtn1 = 0x1000 ptrFlagsBtn2 = 0x2000 ptrFlagsBtn3 = 0x4000 ptrFlagsWheel = 0x0200 ) // InputSender 通过 Fast-Path Input 向远端发送键鼠事件 // Logan.Li type InputSender struct { w io.Writer mu *sync.Mutex } func NewInputSender(w io.Writer) *InputSender { return &InputSender{w: w} } func NewInputSenderWithLock(w io.Writer, mu *sync.Mutex) *InputSender { return &InputSender{w: w, mu: mu} } func (s *InputSender) Send(events []byte) error { if s.mu != nil { s.mu.Lock() defer s.mu.Unlock() } return WriteFastPathInput(s.w, events) } func (s *InputSender) Key(scancode int, down bool) error { flags := byte(0) if !down { flags |= fastPathInputKBRelease } code := uint16(scancode) if scancode&0xFF00 == 0xE000 { flags |= fastPathInputKBExtended code = uint16(scancode & 0xFF) } buf := []byte{byte(fastPathInputEventScancode<<5) | flags} buf = append(buf, byte(code)) return s.Send(buf) } func (s *InputSender) MouseMove(x, y int) error { return s.mouseEvent(ptrFlagsMove, x, y) } func (s *InputSender) MouseButton(x, y, button int, down bool) error { flags := ptrFlagsDown // 浏览器 MouseEvent.button 使用 0/1/2 表示左/中/右键,RDP BTN2 才是右键。 // Logan.Li switch button { case 2: flags |= ptrFlagsBtn2 case 1: flags |= ptrFlagsBtn3 default: flags |= ptrFlagsBtn1 } if !down { flags &^= ptrFlagsDown } return s.mouseEvent(flags, x, y) } func (s *InputSender) MouseWheel(x, y, deltaY int) error { scroll := -deltaY * 120 / 100 if scroll == 0 && deltaY != 0 { if deltaY > 0 { scroll = -120 } else { scroll = 120 } } flags := uint16(ptrFlagsWheel | 0x0001) if scroll < 0 { flags |= 0x0100 scroll = -scroll } buf := []byte{byte(fastPathInputEventMouse << 5)} buf = append(buf, byte(flags), byte(flags>>8)) buf = append(buf, byte(x), byte(x>>8), byte(y), byte(y>>8)) buf = append(buf, byte(scroll), byte(scroll>>8)) return s.Send(buf) } func (s *InputSender) mouseEvent(flags int, x, y int) error { buf := []byte{byte(fastPathInputEventMouse << 5)} buf = append(buf, byte(flags), byte(flags>>8)) buf = append(buf, byte(x), byte(x>>8), byte(y), byte(y>>8)) return s.Send(buf) } func (s *InputSender) TypeText(text string) error { for _, r := range utf16.Encode([]rune(text)) { if err := s.unicodeKey(uint16(r), true); err != nil { return err } if err := s.unicodeKey(uint16(r), false); err != nil { return err } time.Sleep(5 * time.Millisecond) } return nil } func (s *InputSender) unicodeKey(code uint16, down bool) error { flags := byte(0) if !down { flags |= fastPathInputKBRelease } buf := []byte{byte(fastPathInputEventUnicode<<5) | flags, byte(code), byte(code >> 8)} return s.Send(buf) } func (s *InputSender) AutoExec(command string) error { if err := s.Key(0xE05B, true); err != nil { return err } if err := s.Key(0x0013, true); err != nil { return err } if err := s.Key(0x0013, false); err != nil { return err } if err := s.Key(0xE05B, false); err != nil { return err } time.Sleep(200 * time.Millisecond) if err := s.TypeText(command); err != nil { return err } time.Sleep(80 * time.Millisecond) if err := s.Key(0x001C, true); err != nil { return err } time.Sleep(20 * time.Millisecond) return s.Key(0x001C, false) }