Home | History | Annotate | Download | only in port_monitor
      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.
      4 
      5 #include "cloud_print/virtual_driver/win/port_monitor/port_monitor.h"
      6 
      7 #include <winspool.h>
      8 
      9 #include "base/files/file_util.h"
     10 #include "base/path_service.h"
     11 #include "base/strings/string16.h"
     12 #include "base/win/registry.h"
     13 #include "base/win/scoped_handle.h"
     14 #include "cloud_print/virtual_driver/win/port_monitor/spooler_win.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace cloud_print {
     18 
     19 const wchar_t kChromeExePath[] = L"google\\chrome\\application\\chrometest.exe";
     20 const wchar_t kChromeExePathRegValue[] = L"PathToChromeTestExe";
     21 const wchar_t kChromeProfilePathRegValue[] = L"PathToChromeTestProfile";
     22 const bool kIsUnittest = true;
     23 
     24 namespace {
     25 
     26 const wchar_t kAlternateChromeExePath[] =
     27     L"google\\chrome\\application\\chrometestalternate.exe";
     28 
     29 const wchar_t kCloudPrintRegKey[] = L"Software\\Google\\CloudPrint";
     30 
     31 }  // namespace
     32 
     33 class PortMonitorTest : public testing::Test  {
     34  public:
     35   PortMonitorTest() {}
     36  protected:
     37   // Creates a registry entry pointing at a chrome
     38   virtual void SetUpChromeExeRegistry() {
     39     // Create a temporary chrome.exe location value.
     40     base::win::RegKey key(HKEY_CURRENT_USER,
     41                           cloud_print::kCloudPrintRegKey,
     42                           KEY_ALL_ACCESS);
     43 
     44     base::FilePath path;
     45     PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
     46     path = path.Append(kAlternateChromeExePath);
     47     ASSERT_EQ(ERROR_SUCCESS,
     48               key.WriteValue(cloud_print::kChromeExePathRegValue,
     49                              path.value().c_str()));
     50     base::FilePath temp;
     51     PathService::Get(base::DIR_TEMP, &temp);
     52     // Write any dir here.
     53     ASSERT_EQ(ERROR_SUCCESS,
     54               key.WriteValue(cloud_print::kChromeProfilePathRegValue,
     55                              temp.value().c_str()));
     56   }
     57   // Deletes the registry entry created in SetUpChromeExeRegistry
     58   virtual void DeleteChromeExeRegistry() {
     59     base::win::RegKey key(HKEY_CURRENT_USER,
     60                           cloud_print::kCloudPrintRegKey,
     61                           KEY_ALL_ACCESS);
     62     key.DeleteValue(cloud_print::kChromeExePathRegValue);
     63     key.DeleteValue(cloud_print::kChromeProfilePathRegValue);
     64   }
     65 
     66   virtual void CreateTempChromeExeFiles() {
     67     base::FilePath path;
     68     PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
     69     base::FilePath main_path = path.Append(kChromeExePath);
     70     ASSERT_TRUE(base::CreateDirectory(main_path));
     71     base::FilePath alternate_path = path.Append(kAlternateChromeExePath);
     72     ASSERT_TRUE(base::CreateDirectory(alternate_path));
     73   }
     74 
     75   virtual void DeleteTempChromeExeFiles() {
     76     base::FilePath path;
     77     PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
     78     base::FilePath main_path = path.Append(kChromeExePath);
     79     ASSERT_TRUE(base::DeleteFile(main_path, true));
     80     PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
     81     base::FilePath alternate_path = path.Append(kAlternateChromeExePath);
     82     ASSERT_TRUE(base::DeleteFile(alternate_path, true));
     83   }
     84 
     85  protected:
     86   virtual void SetUp() {
     87     SetUpChromeExeRegistry();
     88   }
     89 
     90   virtual void TearDown() {
     91     DeleteChromeExeRegistry();
     92   }
     93 
     94  private:
     95   DISALLOW_COPY_AND_ASSIGN(PortMonitorTest);
     96 };
     97 
     98 TEST_F(PortMonitorTest, GetChromeExePathTest) {
     99   CreateTempChromeExeFiles();
    100   base::FilePath chrome_path = cloud_print::GetChromeExePath();
    101   EXPECT_FALSE(chrome_path.empty());
    102   EXPECT_TRUE(
    103       chrome_path.value().rfind(kAlternateChromeExePath) != std::string::npos);
    104   EXPECT_TRUE(base::PathExists(chrome_path));
    105   DeleteChromeExeRegistry();
    106   chrome_path = cloud_print::GetChromeExePath();
    107   // No Chrome or regular chrome path.
    108   EXPECT_TRUE(chrome_path.empty() ||
    109               chrome_path.value().rfind(kChromeExePath) == std::string::npos);
    110 }
    111 
    112 TEST_F(PortMonitorTest, GetChromeProfilePathTest) {
    113   base::FilePath data_path = cloud_print::GetChromeProfilePath();
    114   EXPECT_FALSE(data_path.empty());
    115   base::FilePath temp;
    116   PathService::Get(base::DIR_TEMP, &temp);
    117   EXPECT_EQ(data_path, temp);
    118   EXPECT_TRUE(base::DirectoryExists(data_path));
    119   DeleteChromeExeRegistry();
    120   data_path = cloud_print::GetChromeProfilePath();
    121   EXPECT_TRUE(data_path.empty());
    122 }
    123 
    124 TEST_F(PortMonitorTest, EnumPortsTest) {
    125   DWORD needed_bytes = 0;
    126   DWORD returned = 0;
    127   EXPECT_FALSE(Monitor2EnumPorts(NULL,
    128                                  NULL,
    129                                  1,
    130                                  NULL,
    131                                  0,
    132                                  &needed_bytes,
    133                                  &returned));
    134   EXPECT_EQ(ERROR_INSUFFICIENT_BUFFER, GetLastError());
    135   EXPECT_NE(0u, needed_bytes);
    136   EXPECT_EQ(0u, returned);
    137 
    138   BYTE* buffer = new BYTE[needed_bytes];
    139   ASSERT_TRUE(buffer != NULL);
    140   EXPECT_TRUE(Monitor2EnumPorts(NULL,
    141                                 NULL,
    142                                 1,
    143                                 buffer,
    144                                 needed_bytes,
    145                                 &needed_bytes,
    146                                 &returned));
    147   EXPECT_NE(0u, needed_bytes);
    148   EXPECT_EQ(1u, returned);
    149   PORT_INFO_1* port_info_1 = reinterpret_cast<PORT_INFO_1*>(buffer);
    150   EXPECT_TRUE(port_info_1->pName != NULL);
    151   delete[] buffer;
    152 
    153   returned = 0;
    154   needed_bytes = 0;
    155   EXPECT_FALSE(Monitor2EnumPorts(NULL,
    156                                  NULL,
    157                                  2,
    158                                  NULL,
    159                                  0,
    160                                  &needed_bytes,
    161                                  &returned));
    162   EXPECT_EQ(ERROR_INSUFFICIENT_BUFFER, GetLastError());
    163   EXPECT_NE(0u, needed_bytes);
    164   EXPECT_EQ(0u, returned);
    165 
    166   buffer = new BYTE[needed_bytes];
    167   ASSERT_TRUE(buffer != NULL);
    168   EXPECT_TRUE(Monitor2EnumPorts(NULL,
    169                                 NULL,
    170                                 2,
    171                                 buffer,
    172                                 needed_bytes,
    173                                 &needed_bytes,
    174                                 &returned));
    175   EXPECT_NE(0u, needed_bytes);
    176   EXPECT_EQ(1u, returned);
    177   PORT_INFO_2* port_info_2 = reinterpret_cast<PORT_INFO_2*>(buffer);
    178   EXPECT_TRUE(port_info_2->pPortName != NULL);
    179   delete[] buffer;
    180 }
    181 
    182 TEST_F(PortMonitorTest, FlowTest) {
    183   const wchar_t kXcvDataItem[] = L"MonitorUI";
    184   MONITORINIT monitor_init = {0};
    185   HANDLE monitor_handle = NULL;
    186   HANDLE port_handle = NULL;
    187   HANDLE xcv_handle = NULL;
    188   DWORD bytes_processed = 0;
    189   DWORD bytes_needed = 0;
    190   const size_t kBufferSize = 100;
    191   BYTE buffer[kBufferSize] = {0};
    192 
    193   // Initialize the print monitor
    194   MONITOR2* monitor2 = InitializePrintMonitor2(&monitor_init, &monitor_handle);
    195   EXPECT_TRUE(monitor2 != NULL);
    196   EXPECT_TRUE(monitor_handle != NULL);
    197 
    198   // Test the XCV functions.  Used for reporting the location of the
    199   // UI portion of the port monitor.
    200   EXPECT_TRUE(monitor2->pfnXcvOpenPort != NULL);
    201   EXPECT_TRUE(monitor2->pfnXcvOpenPort(monitor_handle, NULL, 0, &xcv_handle));
    202   EXPECT_TRUE(xcv_handle != NULL);
    203   EXPECT_TRUE(monitor2->pfnXcvDataPort != NULL);
    204   EXPECT_EQ(ERROR_ACCESS_DENIED,
    205             monitor2->pfnXcvDataPort(xcv_handle,
    206                                      kXcvDataItem,
    207                                      NULL,
    208                                      0,
    209                                      buffer,
    210                                      kBufferSize,
    211                                      &bytes_needed));
    212   EXPECT_TRUE(monitor2->pfnXcvClosePort != NULL);
    213   EXPECT_TRUE(monitor2->pfnXcvClosePort(xcv_handle));
    214   EXPECT_TRUE(monitor2->pfnXcvOpenPort(monitor_handle,
    215                                        NULL,
    216                                        SERVER_ACCESS_ADMINISTER,
    217                                        &xcv_handle));
    218   EXPECT_TRUE(xcv_handle != NULL);
    219   EXPECT_TRUE(monitor2->pfnXcvDataPort != NULL);
    220   EXPECT_EQ(ERROR_SUCCESS,
    221             monitor2->pfnXcvDataPort(xcv_handle,
    222                                      kXcvDataItem,
    223                                      NULL,
    224                                      0,
    225                                      buffer,
    226                                      kBufferSize,
    227                                      &bytes_needed));
    228   EXPECT_TRUE(monitor2->pfnXcvClosePort != NULL);
    229   EXPECT_TRUE(monitor2->pfnXcvClosePort(xcv_handle));
    230 
    231   // Test opening the port and running a print job.
    232   EXPECT_TRUE(monitor2->pfnOpenPort != NULL);
    233   EXPECT_TRUE(monitor2->pfnOpenPort(monitor_handle, NULL, &port_handle));
    234   EXPECT_TRUE(port_handle != NULL);
    235   EXPECT_TRUE(monitor2->pfnStartDocPort != NULL);
    236   EXPECT_TRUE(monitor2->pfnWritePort != NULL);
    237   EXPECT_TRUE(monitor2->pfnReadPort != NULL);
    238   EXPECT_TRUE(monitor2->pfnEndDocPort != NULL);
    239 
    240   // These functions should fail if we have not impersonated the user.
    241   EXPECT_FALSE(monitor2->pfnStartDocPort(
    242       port_handle, const_cast<wchar_t*>(L""), 0, 0, NULL));
    243   EXPECT_FALSE(monitor2->pfnWritePort(port_handle,
    244                                      buffer,
    245                                      kBufferSize,
    246                                      &bytes_processed));
    247   EXPECT_EQ(0, bytes_processed);
    248   EXPECT_FALSE(monitor2->pfnReadPort(port_handle,
    249                                      buffer,
    250                                      sizeof(buffer),
    251                                      &bytes_processed));
    252   EXPECT_EQ(0u, bytes_processed);
    253   EXPECT_FALSE(monitor2->pfnEndDocPort(port_handle));
    254 
    255   // Now impersonate so we can test the success case.
    256   ASSERT_TRUE(ImpersonateSelf(SecurityImpersonation));
    257   EXPECT_TRUE(monitor2->pfnStartDocPort(
    258       port_handle, const_cast<wchar_t*>(L""), 0, 0, NULL));
    259   EXPECT_TRUE(monitor2->pfnWritePort(port_handle,
    260                                      buffer,
    261                                      kBufferSize,
    262                                      &bytes_processed));
    263   EXPECT_EQ(kBufferSize, bytes_processed);
    264   EXPECT_FALSE(monitor2->pfnReadPort(port_handle,
    265                                      buffer,
    266                                      sizeof(buffer),
    267                                      &bytes_processed));
    268   EXPECT_EQ(0u, bytes_processed);
    269   EXPECT_TRUE(monitor2->pfnEndDocPort(port_handle));
    270   RevertToSelf();
    271   EXPECT_TRUE(monitor2->pfnClosePort != NULL);
    272   EXPECT_TRUE(monitor2->pfnClosePort(port_handle));
    273   // Shutdown the port monitor.
    274   Monitor2Shutdown(monitor_handle);
    275 }
    276 
    277 }  // namespace cloud_print
    278 
    279