1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cloud_print/virtual_driver/win/port_monitor/port_monitor.h"
7 #include "base/file_util.h"
8 #include "base/path_service.h"
9 #include "base/strings/string16.h"
10 #include "base/win/registry.h"
11 #include "base/win/scoped_handle.h"
12 #include "cloud_print/virtual_driver/win/port_monitor/spooler_win.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace cloud_print {
17 const wchar_t kChromeExePath[] = L"google\\chrome\\application\\chrometest.exe";
18 const wchar_t kChromeExePathRegValue[] = L"PathToChromeTestExe";
19 const wchar_t kChromeProfilePathRegValue[] = L"PathToChromeTestProfile";
20 const bool kIsUnittest = true;
24 const wchar_t kAlternateChromeExePath[] =
25 L"google\\chrome\\application\\chrometestalternate.exe";
27 const wchar_t kCloudPrintRegKey[] = L"Software\\Google\\CloudPrint";
31 class PortMonitorTest : public testing::Test {
35 // Creates a registry entry pointing at a chrome
36 virtual void SetUpChromeExeRegistry() {
37 // Create a temporary chrome.exe location value.
38 base::win::RegKey key(HKEY_CURRENT_USER,
39 cloud_print::kCloudPrintRegKey,
43 PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
44 path = path.Append(kAlternateChromeExePath);
45 ASSERT_EQ(ERROR_SUCCESS,
46 key.WriteValue(cloud_print::kChromeExePathRegValue,
47 path.value().c_str()));
49 PathService::Get(base::DIR_TEMP, &temp);
50 // Write any dir here.
51 ASSERT_EQ(ERROR_SUCCESS,
52 key.WriteValue(cloud_print::kChromeProfilePathRegValue,
53 temp.value().c_str()));
55 // Deletes the registry entry created in SetUpChromeExeRegistry
56 virtual void DeleteChromeExeRegistry() {
57 base::win::RegKey key(HKEY_CURRENT_USER,
58 cloud_print::kCloudPrintRegKey,
60 key.DeleteValue(cloud_print::kChromeExePathRegValue);
61 key.DeleteValue(cloud_print::kChromeProfilePathRegValue);
64 virtual void CreateTempChromeExeFiles() {
66 PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
67 base::FilePath main_path = path.Append(kChromeExePath);
68 ASSERT_TRUE(file_util::CreateDirectory(main_path));
69 base::FilePath alternate_path = path.Append(kAlternateChromeExePath);
70 ASSERT_TRUE(file_util::CreateDirectory(alternate_path));
73 virtual void DeleteTempChromeExeFiles() {
75 PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
76 base::FilePath main_path = path.Append(kChromeExePath);
77 ASSERT_TRUE(base::DeleteFile(main_path, true));
78 PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
79 base::FilePath alternate_path = path.Append(kAlternateChromeExePath);
80 ASSERT_TRUE(base::DeleteFile(alternate_path, true));
84 virtual void SetUp() {
85 SetUpChromeExeRegistry();
88 virtual void TearDown() {
89 DeleteChromeExeRegistry();
93 DISALLOW_COPY_AND_ASSIGN(PortMonitorTest);
96 TEST_F(PortMonitorTest, GetChromeExePathTest) {
97 CreateTempChromeExeFiles();
98 base::FilePath chrome_path = cloud_print::GetChromeExePath();
99 EXPECT_FALSE(chrome_path.empty());
101 chrome_path.value().rfind(kAlternateChromeExePath) != std::string::npos);
102 EXPECT_TRUE(base::PathExists(chrome_path));
103 DeleteChromeExeRegistry();
104 chrome_path = cloud_print::GetChromeExePath();
105 // No Chrome or regular chrome path.
106 EXPECT_TRUE(chrome_path.empty() ||
107 chrome_path.value().rfind(kChromeExePath) == std::string::npos);
110 TEST_F(PortMonitorTest, GetChromeProfilePathTest) {
111 base::FilePath data_path = cloud_print::GetChromeProfilePath();
112 EXPECT_FALSE(data_path.empty());
114 PathService::Get(base::DIR_TEMP, &temp);
115 EXPECT_EQ(data_path, temp);
116 EXPECT_TRUE(base::DirectoryExists(data_path));
117 DeleteChromeExeRegistry();
118 data_path = cloud_print::GetChromeProfilePath();
119 EXPECT_TRUE(data_path.empty());
122 TEST_F(PortMonitorTest, EnumPortsTest) {
123 DWORD needed_bytes = 0;
125 EXPECT_FALSE(Monitor2EnumPorts(NULL,
132 EXPECT_EQ(ERROR_INSUFFICIENT_BUFFER, GetLastError());
133 EXPECT_NE(0u, needed_bytes);
134 EXPECT_EQ(0u, returned);
136 BYTE* buffer = new BYTE[needed_bytes];
137 ASSERT_TRUE(buffer != NULL);
138 EXPECT_TRUE(Monitor2EnumPorts(NULL,
145 EXPECT_NE(0u, needed_bytes);
146 EXPECT_EQ(1u, returned);
147 PORT_INFO_1* port_info_1 = reinterpret_cast<PORT_INFO_1*>(buffer);
148 EXPECT_TRUE(port_info_1->pName != NULL);
153 EXPECT_FALSE(Monitor2EnumPorts(NULL,
160 EXPECT_EQ(ERROR_INSUFFICIENT_BUFFER, GetLastError());
161 EXPECT_NE(0u, needed_bytes);
162 EXPECT_EQ(0u, returned);
164 buffer = new BYTE[needed_bytes];
165 ASSERT_TRUE(buffer != NULL);
166 EXPECT_TRUE(Monitor2EnumPorts(NULL,
173 EXPECT_NE(0u, needed_bytes);
174 EXPECT_EQ(1u, returned);
175 PORT_INFO_2* port_info_2 = reinterpret_cast<PORT_INFO_2*>(buffer);
176 EXPECT_TRUE(port_info_2->pPortName != NULL);
180 TEST_F(PortMonitorTest, FlowTest) {
181 const wchar_t kXcvDataItem[] = L"MonitorUI";
182 MONITORINIT monitor_init = {0};
183 HANDLE monitor_handle = NULL;
184 HANDLE port_handle = NULL;
185 HANDLE xcv_handle = NULL;
186 DWORD bytes_processed = 0;
187 DWORD bytes_needed = 0;
188 const size_t kBufferSize = 100;
189 BYTE buffer[kBufferSize] = {0};
191 // Initialize the print monitor
192 MONITOR2* monitor2 = InitializePrintMonitor2(&monitor_init, &monitor_handle);
193 EXPECT_TRUE(monitor2 != NULL);
194 EXPECT_TRUE(monitor_handle != NULL);
196 // Test the XCV functions. Used for reporting the location of the
197 // UI portion of the port monitor.
198 EXPECT_TRUE(monitor2->pfnXcvOpenPort != NULL);
199 EXPECT_TRUE(monitor2->pfnXcvOpenPort(monitor_handle, NULL, 0, &xcv_handle));
200 EXPECT_TRUE(xcv_handle != NULL);
201 EXPECT_TRUE(monitor2->pfnXcvDataPort != NULL);
202 EXPECT_EQ(ERROR_ACCESS_DENIED,
203 monitor2->pfnXcvDataPort(xcv_handle,
210 EXPECT_TRUE(monitor2->pfnXcvClosePort != NULL);
211 EXPECT_TRUE(monitor2->pfnXcvClosePort(xcv_handle));
212 EXPECT_TRUE(monitor2->pfnXcvOpenPort(monitor_handle,
214 SERVER_ACCESS_ADMINISTER,
216 EXPECT_TRUE(xcv_handle != NULL);
217 EXPECT_TRUE(monitor2->pfnXcvDataPort != NULL);
218 EXPECT_EQ(ERROR_SUCCESS,
219 monitor2->pfnXcvDataPort(xcv_handle,
226 EXPECT_TRUE(monitor2->pfnXcvClosePort != NULL);
227 EXPECT_TRUE(monitor2->pfnXcvClosePort(xcv_handle));
229 // Test opening the port and running a print job.
230 EXPECT_TRUE(monitor2->pfnOpenPort != NULL);
231 EXPECT_TRUE(monitor2->pfnOpenPort(monitor_handle, NULL, &port_handle));
232 EXPECT_TRUE(port_handle != NULL);
233 EXPECT_TRUE(monitor2->pfnStartDocPort != NULL);
234 EXPECT_TRUE(monitor2->pfnWritePort != NULL);
235 EXPECT_TRUE(monitor2->pfnReadPort != NULL);
236 EXPECT_TRUE(monitor2->pfnEndDocPort != NULL);
238 // These functions should fail if we have not impersonated the user.
239 EXPECT_FALSE(monitor2->pfnStartDocPort(port_handle, L"", 0, 0, NULL));
240 EXPECT_FALSE(monitor2->pfnWritePort(port_handle,
244 EXPECT_EQ(0, bytes_processed);
245 EXPECT_FALSE(monitor2->pfnReadPort(port_handle,
249 EXPECT_EQ(0u, bytes_processed);
250 EXPECT_FALSE(monitor2->pfnEndDocPort(port_handle));
252 // Now impersonate so we can test the success case.
253 ASSERT_TRUE(ImpersonateSelf(SecurityImpersonation));
254 EXPECT_TRUE(monitor2->pfnStartDocPort(port_handle, L"", 0, 0, NULL));
255 EXPECT_TRUE(monitor2->pfnWritePort(port_handle,
259 EXPECT_EQ(kBufferSize, bytes_processed);
260 EXPECT_FALSE(monitor2->pfnReadPort(port_handle,
264 EXPECT_EQ(0u, bytes_processed);
265 EXPECT_TRUE(monitor2->pfnEndDocPort(port_handle));
267 EXPECT_TRUE(monitor2->pfnClosePort != NULL);
268 EXPECT_TRUE(monitor2->pfnClosePort(port_handle));
269 // Shutdown the port monitor.
270 Monitor2Shutdown(monitor_handle);
273 } // namespace cloud_print