15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/clipboard.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string16.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/win/message_window.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_hglobal.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/constants.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/event.pb.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/clipboard_stub.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A scoper class that opens and closes the clipboard.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class was adapted from the ScopedClipboard class in
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ui/base/clipboard/clipboard_win.cc.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedClipboard {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedClipboard() : opened_(false) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ScopedClipboard() {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (opened_) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ::CloseClipboard();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Init(HWND owner) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kMaxAttemptsToOpenClipboard = 5;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::TimeDelta kSleepTimeBetweenAttempts =
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(5);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (opened_) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This code runs on the UI thread, so we can block only very briefly.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int attempt = 0; attempt < kMaxAttemptsToOpenClipboard; ++attempt) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (attempt > 0) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::PlatformThread::Sleep(kSleepTimeBetweenAttempts);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (::OpenClipboard(owner)) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        opened_ = true;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL Empty() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!opened_) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ::EmptyClipboard();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetData(UINT uFormat, HANDLE hMem) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!opened_) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The caller must not close the handle that ::SetClipboardData returns.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::SetClipboardData(uFormat, hMem);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The caller must not free the handle. The caller should lock the handle,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // copy the clipboard data, and unlock the handle. All this must be done
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before this ScopedClipboard is destroyed.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE GetData(UINT format) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!opened_) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ::GetClipboardData(format);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool opened_;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef BOOL (WINAPI AddClipboardFormatListenerFn)(HWND);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef BOOL (WINAPI RemoveClipboardFormatListenerFn)(HWND);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass ClipboardWin : public Clipboard {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClipboardWin();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Start(
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void InjectClipboardEvent(
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const protocol::ClipboardEvent& event) OVERRIDE;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Stop() OVERRIDE;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnClipboardUpdate();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles messages received by |window_|.
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool HandleMessage(UINT message,
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     WPARAM wparam,
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     LPARAM lparam,
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     LRESULT* result);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<protocol::ClipboardStub> client_clipboard_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddClipboardFormatListenerFn* add_clipboard_format_listener_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveClipboardFormatListenerFn* remove_clipboard_format_listener_;
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Used to subscribe to WM_CLIPBOARDUPDATE messages.
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::win::MessageWindow> window_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ClipboardWin);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClipboardWin::ClipboardWin()
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : add_clipboard_format_listener_(NULL),
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      remove_clipboard_format_listener_(NULL) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClipboardWin::Start(
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<protocol::ClipboardStub> client_clipboard) {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!add_clipboard_format_listener_);
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!remove_clipboard_format_listener_);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!window_);
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_clipboard_.swap(client_clipboard);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // user32.dll is statically linked.
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  HMODULE user32 = GetModuleHandle(L"user32.dll");
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(user32);
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  add_clipboard_format_listener_ =
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      reinterpret_cast<AddClipboardFormatListenerFn*>(
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProcAddress(user32, "AddClipboardFormatListener"));
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (add_clipboard_format_listener_) {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    remove_clipboard_format_listener_ =
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        reinterpret_cast<RemoveClipboardFormatListenerFn*>(
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            GetProcAddress(user32, "RemoveClipboardFormatListener"));
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // If AddClipboardFormatListener() present, RemoveClipboardFormatListener()
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // should be available too.
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK(remove_clipboard_format_listener_);
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "AddClipboardFormatListener() is not available.";
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  window_.reset(new base::win::MessageWindow());
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!window_->Create(base::Bind(&ClipboardWin::HandleMessage,
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  base::Unretained(this)))) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Couldn't create clipboard window.";
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window_.reset();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (add_clipboard_format_listener_) {
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!(*add_clipboard_format_listener_)(window_->hwnd())) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "AddClipboardFormatListener() failed: " << GetLastError();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClipboardWin::Stop() {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_clipboard_.reset();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (window_ && remove_clipboard_format_listener_)
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    (*remove_clipboard_format_listener_)(window_->hwnd());
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  window_.reset();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClipboardWin::InjectClipboardEvent(
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const protocol::ClipboardEvent& event) {
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!window_)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Currently we only handle UTF-8 text.
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event.mime_type().compare(kMimeTypeTextUtf8) != 0)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!StringIsUtf8(event.data().c_str(), event.data().length())) {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "ClipboardEvent: data is not UTF-8 encoded.";
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 text = base::UTF8ToUTF16(ReplaceLfByCrLf(event.data()));
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedClipboard clipboard;
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!clipboard.Init(window_->hwnd())) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Couldn't open the clipboard.";
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clipboard.Empty();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HGLOBAL text_global =
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ::GlobalAlloc(GMEM_MOVEABLE, (text.size() + 1) * sizeof(WCHAR));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!text_global) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Couldn't allocate global memory.";
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LPWSTR text_global_locked =
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<LPWSTR>(::GlobalLock(text_global));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(text_global_locked, text.data(), text.size() * sizeof(WCHAR));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  text_global_locked[text.size()] = (WCHAR)0;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::GlobalUnlock(text_global);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clipboard.SetData(CF_UNICODETEXT, text_global);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClipboardWin::OnClipboardUpdate() {
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(window_);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::IsClipboardFormatAvailable(CF_UNICODETEXT)) {
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::string16 text;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add a scope, so that we keep the clipboard open for as short a time as
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // possible.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScopedClipboard clipboard;
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!clipboard.Init(window_->hwnd())) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Couldn't open the clipboard." << GetLastError();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HGLOBAL text_global = clipboard.GetData(CF_UNICODETEXT);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!text_global) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Couldn't get data from the clipboard: "
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << GetLastError();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::win::ScopedHGlobal<WCHAR*> text_lock(text_global);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!text_lock.get()) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Couldn't lock clipboard data: " << GetLastError();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text.assign(text_lock.get());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protocol::ClipboardEvent event;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event.set_mime_type(kMimeTypeTextUtf8);
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    event.set_data(ReplaceCrLfByLf(base::UTF16ToUTF8(text)));
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (client_clipboard_.get()) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_clipboard_->InjectClipboardEvent(event);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ClipboardWin::HandleMessage(
264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result) {
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (message == WM_CLIPBOARDUPDATE) {
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OnClipboardUpdate();
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *result = 0;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<Clipboard> Clipboard::Create() {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scoped_ptr<Clipboard>(new ClipboardWin());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
279