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 "base/bind.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/scoped_native_library.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/auto_thread.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <objbase.h> 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/windows_version.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kThreadName[] = "Test thread"; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetFlagTask(bool* success) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *success = true; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PostSetFlagTask( 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::TaskRunner> task_runner, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* success) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_runner->PostTask(FROM_HERE, base::Bind(&SetFlagTask, success)); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CheckComAptTypeTask(APTTYPE* apt_type_out, HRESULT* hresult) { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef HRESULT (WINAPI * CoGetApartmentTypeFunc) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (APTTYPE*, APTTYPEQUALIFIER*); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CoGetApartmentType requires Windows 7 or above. 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_WIN7) { 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *hresult = E_NOTIMPL; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Dynamic link to the API so the same test binary can run on older systems. 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ScopedNativeLibrary com_library(base::FilePath(L"ole32.dll")); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(com_library.is_valid()); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CoGetApartmentTypeFunc co_get_apartment_type = 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch reinterpret_cast<CoGetApartmentTypeFunc>( 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) com_library.GetFunctionPointer("CoGetApartmentType")); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(co_get_apartment_type != NULL); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) APTTYPEQUALIFIER apt_type_qualifier; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *hresult = (*co_get_apartment_type)(apt_type_out, &apt_type_qualifier); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AutoThreadTest : public testing::Test { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoThreadTest() : message_loop_quit_correctly_(false) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunMessageLoop() { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release |main_task_runner_|, then run |message_loop_| until other 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // references created in tests are gone. We also post a delayed quit 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // task to |message_loop_| so the test will not hang on failure. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_task_runner_ = NULL; 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_.PostDelayedTask(FROM_HERE, 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::QuitClosure(), 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::TimeDelta::FromSeconds(5)); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_.Run(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() OVERRIDE { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_task_runner_ = new AutoThreadTaskRunner( 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_.message_loop_proxy(), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&AutoThreadTest::QuitMainMessageLoop, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() OVERRIDE { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that |message_loop_| was quit by the AutoThreadTaskRunner. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(message_loop_quit_correctly_); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void QuitMainMessageLoop() { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_quit_correctly_ = true; 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop message_loop_; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool message_loop_quit_correctly_; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> main_task_runner_; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AutoThreadTest, StartAndStop) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an AutoThread joined by our MessageLoop. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::TaskRunner> task_runner = 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoThread::Create(kThreadName, main_task_runner_); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(task_runner.get()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_runner = NULL; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunMessageLoop(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AutoThreadTest, ProcessTask) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an AutoThread joined by our MessageLoop. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::TaskRunner> task_runner = 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoThread::Create(kThreadName, main_task_runner_); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(task_runner.get()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Post a task to it. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_runner->PostTask(FROM_HERE, base::Bind(&SetFlagTask, &success)); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_runner = NULL; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunMessageLoop(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(success); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AutoThreadTest, ThreadDependency) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create two AutoThreads joined by our MessageLoop. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::TaskRunner> task_runner1 = 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoThread::Create(kThreadName, main_task_runner_); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(task_runner1.get()); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::TaskRunner> task_runner2 = 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoThread::Create(kThreadName, main_task_runner_); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(task_runner2.get()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Post a task to thread 1 that will post a task to thread 2. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_runner1->PostTask(FROM_HERE, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&PostSetFlagTask, task_runner2, &success)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_runner1 = NULL; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_runner2 = NULL; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunMessageLoop(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(success); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(AutoThreadTest, ThreadWithComMta) { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::TaskRunner> task_runner = 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AutoThread::CreateWithLoopAndComInitTypes(kThreadName, 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) main_task_runner_, 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::TYPE_DEFAULT, 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AutoThread::COM_INIT_MTA); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(task_runner.get()); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Post a task to query the COM apartment type. 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hresult = E_FAIL; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) APTTYPE apt_type = APTTYPE_NA; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task_runner->PostTask(FROM_HERE, 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CheckComAptTypeTask, &apt_type, &hresult)); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task_runner = NULL; 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunMessageLoop(); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CoGetApartmentType requires Windows 7 or above. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::win::GetVersion() >= base::win::VERSION_WIN7) { 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(S_OK, hresult); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(APTTYPE_MTA, apt_type); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(E_NOTIMPL, hresult); 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(AutoThreadTest, ThreadWithComSta) { 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::TaskRunner> task_runner = 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AutoThread::CreateWithLoopAndComInitTypes(kThreadName, 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) main_task_runner_, 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::TYPE_UI, 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AutoThread::COM_INIT_STA); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(task_runner.get()); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Post a task to query the COM apartment type. 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HRESULT hresult = E_FAIL; 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) APTTYPE apt_type = APTTYPE_NA; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task_runner->PostTask(FROM_HERE, 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CheckComAptTypeTask, &apt_type, &hresult)); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task_runner = NULL; 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunMessageLoop(); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CoGetApartmentType requires Windows 7 or above. 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::win::GetVersion() >= base::win::VERSION_WIN7) { 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(S_OK, hresult); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Whether the thread is the "main" STA apartment depends upon previous 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // COM activity in this test process, so allow both types here. 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(apt_type == APTTYPE_MAINSTA || apt_type == APTTYPE_STA); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(E_NOTIMPL, hresult); 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // defined(OS_WIN) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 202