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 #include <winspool.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"
     14 
     15 namespace cloud_print {
     16 
     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;
     21 
     22 namespace {
     23 
     24 const wchar_t kAlternateChromeExePath[] =
     25     L"google\\chrome\\application\\chrometestalternate.exe";
     26 
     27 const wchar_t kCloudPrintRegKey[] = L"Software\\Google\\CloudPrint";
     28 
     29 }  // namespace
     30 
     31 class PortMonitorTest : public testing::Test  {
     32  public:
     33   PortMonitorTest() {}
     34  protected:
     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,
     40                           KEY_ALL_ACCESS);
     41 
     42     base::FilePath path;
     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()));
     48     base::FilePath temp;
     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()));
     54   }
     55   // Deletes the registry entry created in SetUpChromeExeRegistry
     56   virtual void DeleteChromeExeRegistry() {
     57     base::win::RegKey key(HKEY_CURRENT_USER,
     58                           cloud_print::kCloudPrintRegKey,
     59                           KEY_ALL_ACCESS);
     60     key.DeleteValue(cloud_print::kChromeExePathRegValue);
     61     key.DeleteValue(cloud_print::kChromeProfilePathRegValue);
     62   }
     63 
     64   virtual void CreateTempChromeExeFiles() {
     65     base::FilePath path;
     66     PathService::Get(base::DIR_LOCAL_APP_DATA, &path);
     67     base::FilePath main_path = path.Append(kChromeExePath);
     68     ASSERT_TRUE(base::CreateDirectory(main_path));
     69     base::FilePath alternate_path = path.Append(kAlternateChromeExePath);
     70     ASSERT_TRUE(base::CreateDirectory(alternate_path));
     71   }
     72 
     73   virtual void DeleteTempChromeExeFiles() {
     74     base::FilePath path;
     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));
     81   }
     82 
     83  protected:
     84   virtual void SetUp() {
     85     SetUpChromeExeRegistry();
     86   }
     87 
     88   virtual void TearDown() {
     89     DeleteChromeExeRegistry();
     90   }
     91 
     92  private:
     93   DISALLOW_COPY_AND_ASSIGN(PortMonitorTest);
     94 };
     95 
     96 TEST_F(PortMonitorTest, GetChromeExePathTest) {
     97   CreateTempChromeExeFiles();
     98   base::FilePath chrome_path = cloud_print::GetChromeExePath();
     99   EXPECT_FALSE(chrome_path.empty());
    100   EXPECT_TRUE(
    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);
    108 }
    109 
    110 TEST_F(PortMonitorTest, GetChromeProfilePathTest) {
    111   base::FilePath data_path = cloud_print::GetChromeProfilePath();
    112   EXPECT_FALSE(data_path.empty());
    113   base::FilePath temp;
    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());
    120 }
    121 
    122 TEST_F(PortMonitorTest, EnumPortsTest) {
    123   DWORD needed_bytes = 0;
    124   DWORD returned = 0;
    125   EXPECT_FALSE(Monitor2EnumPorts(NULL,
    126                                  NULL,
    127                                  1,
    128                                  NULL,
    129                                  0,
    130                                  &needed_bytes,
    131                                  &returned));
    132   EXPECT_EQ(ERROR_INSUFFICIENT_BUFFER, GetLastError());
    133   EXPECT_NE(0u, needed_bytes);
    134   EXPECT_EQ(0u, returned);
    135 
    136   BYTE* buffer = new BYTE[needed_bytes];
    137   ASSERT_TRUE(buffer != NULL);
    138   EXPECT_TRUE(Monitor2EnumPorts(NULL,
    139                                 NULL,
    140                                 1,
    141                                 buffer,
    142                                 needed_bytes,
    143                                 &needed_bytes,
    144                                 &returned));
    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);
    149   delete[] buffer;
    150 
    151   returned = 0;
    152   needed_bytes = 0;
    153   EXPECT_FALSE(Monitor2EnumPorts(NULL,
    154                                  NULL,
    155                                  2,
    156                                  NULL,
    157                                  0,
    158                                  &needed_bytes,
    159                                  &returned));
    160   EXPECT_EQ(ERROR_INSUFFICIENT_BUFFER, GetLastError());
    161   EXPECT_NE(0u, needed_bytes);
    162   EXPECT_EQ(0u, returned);
    163 
    164   buffer = new BYTE[needed_bytes];
    165   ASSERT_TRUE(buffer != NULL);
    166   EXPECT_TRUE(Monitor2EnumPorts(NULL,
    167                                 NULL,
    168                                 2,
    169                                 buffer,
    170                                 needed_bytes,
    171                                 &needed_bytes,
    172                                 &returned));
    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);
    177   delete[] buffer;
    178 }
    179 
    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};
    190 
    191   // Initialize the print monitor
    192   MONITOR2* monitor2 = InitializePrintMonitor2(&monitor_init, &monitor_handle);
    193   EXPECT_TRUE(monitor2 != NULL);
    194   EXPECT_TRUE(monitor_handle != NULL);
    195 
    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,
    204                                      kXcvDataItem,
    205                                      NULL,
    206                                      0,
    207                                      buffer,
    208                                      kBufferSize,
    209                                      &bytes_needed));
    210   EXPECT_TRUE(monitor2->pfnXcvClosePort != NULL);
    211   EXPECT_TRUE(monitor2->pfnXcvClosePort(xcv_handle));
    212   EXPECT_TRUE(monitor2->pfnXcvOpenPort(monitor_handle,
    213                                        NULL,
    214                                        SERVER_ACCESS_ADMINISTER,
    215                                        &xcv_handle));
    216   EXPECT_TRUE(xcv_handle != NULL);
    217   EXPECT_TRUE(monitor2->pfnXcvDataPort != NULL);
    218   EXPECT_EQ(ERROR_SUCCESS,
    219             monitor2->pfnXcvDataPort(xcv_handle,
    220                                      kXcvDataItem,
    221                                      NULL,
    222                                      0,
    223                                      buffer,
    224                                      kBufferSize,
    225                                      &bytes_needed));
    226   EXPECT_TRUE(monitor2->pfnXcvClosePort != NULL);
    227   EXPECT_TRUE(monitor2->pfnXcvClosePort(xcv_handle));
    228 
    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);
    237 
    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,
    241                                      buffer,
    242                                      kBufferSize,
    243                                      &bytes_processed));
    244   EXPECT_EQ(0, bytes_processed);
    245   EXPECT_FALSE(monitor2->pfnReadPort(port_handle,
    246                                      buffer,
    247                                      sizeof(buffer),
    248                                      &bytes_processed));
    249   EXPECT_EQ(0u, bytes_processed);
    250   EXPECT_FALSE(monitor2->pfnEndDocPort(port_handle));
    251 
    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,
    256                                      buffer,
    257                                      kBufferSize,
    258                                      &bytes_processed));
    259   EXPECT_EQ(kBufferSize, bytes_processed);
    260   EXPECT_FALSE(monitor2->pfnReadPort(port_handle,
    261                                      buffer,
    262                                      sizeof(buffer),
    263                                      &bytes_processed));
    264   EXPECT_EQ(0u, bytes_processed);
    265   EXPECT_TRUE(monitor2->pfnEndDocPort(port_handle));
    266   RevertToSelf();
    267   EXPECT_TRUE(monitor2->pfnClosePort != NULL);
    268   EXPECT_TRUE(monitor2->pfnClosePort(port_handle));
    269   // Shutdown the port monitor.
    270   Monitor2Shutdown(monitor_handle);
    271 }
    272 
    273 }  // namespace cloud_print
    274 
    275