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 "cloud_print/virtual_driver/win/port_monitor/port_monitor.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <windows.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <lmcons.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shellapi.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlobj.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <strsafe.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <userenv.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winspool.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 21bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h" 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/process/process.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_switches.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/launcher_support/chrome_launcher_support.h" 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/common/win/cloud_print_utils.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "cloud_print/virtual_driver/win/port_monitor/spooler_win.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "cloud_print/virtual_driver/win/virtual_driver_consts.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "cloud_print/virtual_driver/win/virtual_driver_helpers.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace cloud_print { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kIePath[] = L"Internet Explorer\\iexplore.exe"; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kChromeInstallUrl[] = 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "http://google.com/cloudprint/learn/chrome.html"; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kCloudPrintRegKey[] = L"Software\\Google\\CloudPrint"; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kXpsMimeType[] = L"application/vnd.ms-xpsdocument"; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const wchar_t kAppDataDir[] = L"Google\\Cloud Printer"; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct MonitorData { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::AtExitManager> at_exit_manager; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PortData { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PortData() : job_id(0), printer_handle(NULL), file(0) { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~PortData() { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Close(); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Close() { 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (printer_handle) { 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClosePrinter(printer_handle); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printer_handle = NULL; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (file) { 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::CloseFile(file); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file = NULL; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD job_id; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE printer_handle; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* file; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file_path; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACCESS_MASK granted_access; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} XcvUiData; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MONITORUI g_monitor_ui = { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(MONITORUI), 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MonitorUiAddPortUi, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MonitorUiConfigureOrDeletePortUI, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MonitorUiConfigureOrDeletePortUI 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MONITOR2 g_monitor_2 = { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(MONITOR2), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2EnumPorts, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2OpenPort, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // OpenPortEx is not supported. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2StartDocPort, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2WritePort, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2ReadPort, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2EndDocPort, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2ClosePort, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // AddPort is not supported. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // AddPortEx is not supported. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // ConfigurePort is not supported. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // DeletePort is not supported. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // SetPortTimeOuts is not supported. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2XcvOpenPort, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2XcvDataPort, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2XcvClosePort, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Monitor2Shutdown 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetAppDataDir() { 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file_path; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::Version version = base::win::GetVersion(); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int path_id = (version >= base::win::VERSION_VISTA) ? 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DIR_LOCAL_APP_DATA_LOW : base::DIR_LOCAL_APP_DATA; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!PathService::Get(path_id, &file_path)) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Can't get DIR_LOCAL_APP_DATA"; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return file_path.Append(kAppDataDir); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Delete files which where not deleted by chrome. 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeleteLeakedFiles(const base::FilePath& dir) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time delete_before = base::Time::Now() - base::TimeDelta::FromDays(1); 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator enumerator(dir, false, base::FileEnumerator::FILES); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_path = enumerator.Next()) { 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (enumerator.GetInfo().GetLastModifiedTime() < delete_before) 1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(file_path, false); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Attempts to retrieve the title of the specified print job. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On success returns TRUE and the first title_chars characters of the job title 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are copied into title. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On failure returns FALSE and title is unmodified. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetJobTitle(HANDLE printer_handle, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD job_id, 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 *title) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(printer_handle != NULL); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(title != NULL); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD bytes_needed = 0; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetJob(printer_handle, job_id, 1, NULL, 0, &bytes_needed); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_needed == 0) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to get bytes needed for job info."; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<BYTE[]> buffer(new BYTE[bytes_needed]); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetJob(printer_handle, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_id, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer.get(), 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_needed, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bytes_needed)) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to get job info."; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JOB_INFO_1* job_info = reinterpret_cast<JOB_INFO_1*>(buffer.get()); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *title = job_info->pDocument; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for the UI functions exported by the port monitor. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies that a valid parent Window exists and then just displays an 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// error message to let the user know that there is no interactive 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// configuration. 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HandlePortUi(HWND hwnd, const base::string16& caption) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hwnd != NULL && IsWindow(hwnd)) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisplayWindowsMessage(hwnd, CO_E_NOT_SUPPORTED, cloud_print::kPortName); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets the primary token for the user that submitted the print job. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetUserToken(HANDLE* primary_token) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE token = NULL; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!OpenThreadToken(GetCurrentThread(), 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FALSE, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &token)) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to get thread token."; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle token_scoped(token); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!DuplicateTokenEx(token, 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecurityImpersonation, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TokenPrimary, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) primary_token)) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to get primary thread token."; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Launches the Cloud Print dialog in Chrome. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// xps_path references a file to print. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// job_title is the title to be used for the resulting print job. 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LaunchPrintDialog(const base::FilePath& xps_path, 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& job_title) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE token = NULL; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetUserToken(&token)) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to get user token."; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle primary_token_scoped(token); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_path = GetChromeExePath(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chrome_path.empty()) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to get chrome exe path."; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine command_line(chrome_path); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_profile = GetChromeProfilePath(); 216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!chrome_profile.empty()) 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) command_line.AppendSwitchPath(switches::kUserDataDir, chrome_profile); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) command_line.AppendSwitchPath(switches::kCloudPrintFile, xps_path); 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) command_line.AppendSwitchNative(switches::kCloudPrintFileType, kXpsMimeType); 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) command_line.AppendSwitchNative(switches::kCloudPrintJobTitle, job_title); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci options.as_user = primary_token_scoped.Get(); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchProcess(command_line, options, NULL); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Launches a page to allow the user to download chrome. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(abodenha@chromium.org) Point to a custom page explaining what's wrong 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// rather than the generic chrome download page. See 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/chromium/issues/detail?id=112019 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LaunchChromeDownloadPage() { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kIsUnittest) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE token = NULL; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetUserToken(&token)) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to get user token."; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle token_scoped(token); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath ie_path; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathService::Get(base::DIR_PROGRAM_FILESX86, &ie_path); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ie_path = ie_path.Append(kIePath); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine command_line(ie_path); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.AppendArg(kChromeInstallUrl); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci options.as_user = token_scoped.Get(); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchProcess(command_line, options, NULL); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns false if the print job is being run in a context 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that shouldn't be launching Chrome. 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ValidateCurrentUser() { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE token = NULL; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetUserToken(&token)) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we can't get the token we're probably not impersonating 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the user, so validation should fail. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle token_scoped(token); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD session_id = 0; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dummy; 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!GetTokenInformation(token_scoped.Get(), 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TokenSessionId, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void *>(&session_id), 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(DWORD), 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dummy)) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (session_id == 0) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath ReadPathFromRegistry(HKEY root, const wchar_t* path_name) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::RegKey gcp_key(HKEY_CURRENT_USER, kCloudPrintRegKey, KEY_READ); 284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 data; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(gcp_key.ReadValue(path_name, &data)) && 2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::PathExists(base::FilePath(data))) { 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(data); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath ReadPathFromAnyRegistry(const wchar_t* path_name) { 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath result = ReadPathFromRegistry(HKEY_CURRENT_USER, path_name); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result.empty()) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path_name); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetChromeExePath() { 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = ReadPathFromAnyRegistry(kChromeExePathRegValue); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!path.empty()) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return chrome_launcher_support::GetAnyChromePath(); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetChromeProfilePath() { 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = ReadPathFromAnyRegistry(kChromeProfilePathRegValue); 3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!path.empty() && base::DirectoryExists(path)) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path; 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2EnumPorts(HANDLE, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t*, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD level, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE* ports, 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD ports_size, 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* needed_bytes, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* returned) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (needed_bytes == NULL) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "needed_bytes should not be NULL."; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (level == 1) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *needed_bytes = sizeof(PORT_INFO_1); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (level == 2) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *needed_bytes = sizeof(PORT_INFO_2); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Level " << level << "is not supported."; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_LEVEL); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *needed_bytes += static_cast<DWORD>(cloud_print::kPortNameSize); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ports_size < *needed_bytes) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << *needed_bytes << " bytes are required. Only " 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ports_size << " were allocated."; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INSUFFICIENT_BUFFER); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ports == NULL) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "ports should not be NULL."; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (returned == NULL) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "returned should not be NULL."; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Windows expects any strings refernced by PORT_INFO_X structures to 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appear at the END of the buffer referenced by ports. Placing 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // strings immediately after the PORT_INFO_X structure will cause 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EnumPorts to fail until the spooler is restarted. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is NOT mentioned in the documentation. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* string_target = 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<wchar_t*>(ports + ports_size - 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortNameSize); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (level == 1) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_INFO_1* port_info = reinterpret_cast<PORT_INFO_1*>(ports); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->pName = string_target; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringCbCopy(port_info->pName, 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortNameSize, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortName); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_INFO_2* port_info = reinterpret_cast<PORT_INFO_2*>(ports); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->pPortName = string_target; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringCbCopy(port_info->pPortName, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortNameSize, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortName); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->pMonitorName = NULL; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->pDescription = NULL; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->fPortType = PORT_TYPE_WRITE; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->Reserved = 0; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *returned = 1; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2OpenPort(HANDLE, wchar_t*, HANDLE* handle) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle == NULL) { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "handle should not be NULL."; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *handle = new PortData(); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2StartDocPort(HANDLE port_handle, 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* printer_name, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD job_id, 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE*) { 396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetGoogleUpdateUsage(kGoogleUpdateProductId); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_handle == NULL) { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "port_handle should not be NULL."; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (printer_name == NULL) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "printer_name should not be NULL."; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ValidateCurrentUser()) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(abodenha@chromium.org) Abort the print job. 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PortData* port_data = reinterpret_cast<PortData*>(port_handle); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_data->job_id = job_id; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!OpenPrinter(printer_name, &(port_data->printer_handle), NULL)) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Unable to open printer " << printer_name << "."; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can continue without a handle to the printer. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It just means we can't get the job title or tell the spooler that 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the print job is complete. 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is the normal flow during a unit test. 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_data->printer_handle = NULL; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath& file_path = port_data->file_path; 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath app_data_dir = GetAppDataDir(); 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (app_data_dir.empty()) 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteLeakedFiles(app_data_dir); 426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateDirectory(app_data_dir) || 427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !base::CreateTemporaryFileInDir(app_data_dir, &file_path)) { 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Can't create temporary file in " << app_data_dir.value(); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) port_data->file = base::OpenFile(file_path, "wb+"); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_data->file == NULL) { 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Error opening file " << file_path.value() << "."; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2WritePort(HANDLE port_handle, 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE* buffer, 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD buffer_size, 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* bytes_written) { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PortData* port_data = reinterpret_cast<PortData*>(port_handle); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ValidateCurrentUser()) { 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(abodenha@chromium.org) Abort the print job. 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes_written = 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<DWORD>(fwrite(buffer, 1, buffer_size, port_data->file)); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*bytes_written > 0) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2ReadPort(HANDLE, BYTE*, DWORD, DWORD* read_bytes) { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Read is not supported."; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *read_bytes = 0; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_NOT_SUPPORTED); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2EndDocPort(HANDLE port_handle) { 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ValidateCurrentUser()) { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(abodenha@chromium.org) Abort the print job. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PortData* port_data = reinterpret_cast<PortData*>(port_handle); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_data == NULL) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_data->file != NULL) { 476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::CloseFile(port_data->file); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_data->file = NULL; 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool delete_file = true; 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 file_size = 0; 480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::GetFileSize(port_data->file_path, &file_size); 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (file_size > 0) { 482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 job_title; 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (port_data->printer_handle != NULL) { 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetJobTitle(port_data->printer_handle, 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) port_data->job_id, 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &job_title); 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!LaunchPrintDialog(port_data->file_path, job_title)) { 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LaunchChromeDownloadPage(); 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_file = false; 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delete_file) 4957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(port_data->file_path, false); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_data->printer_handle != NULL) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tell the spooler that the job is complete. 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetJob(port_data->printer_handle, 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_data->job_id, 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JOB_CONTROL_SENT_TO_PRINTER); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) port_data->Close(); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return success even if we can't display the dialog. 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(abodenha@chromium.org) Come up with a better way of handling 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this situation. 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2ClosePort(HANDLE port_handle) { 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_handle == NULL) { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "port_handle should not be NULL."; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delete reinterpret_cast<PortData*>(port_handle); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VOID WINAPI Monitor2Shutdown(HANDLE monitor_handle) { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (monitor_handle != NULL) { 5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delete reinterpret_cast<MonitorData*>(monitor_handle); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2XcvOpenPort(HANDLE, 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t*, 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACCESS_MASK granted_access, 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE* handle) { 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle == NULL) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "handle should not be NULL."; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XcvUiData* xcv_data = new XcvUiData(); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xcv_data->granted_access = granted_access; 5394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *handle = xcv_data; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD WINAPI Monitor2XcvDataPort(HANDLE xcv_handle, 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* data_name, 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE*, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE* output_data, 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD output_data_bytes, 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* output_data_bytes_needed) { 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XcvUiData* xcv_data = reinterpret_cast<XcvUiData*>(xcv_handle); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD ret_val = ERROR_SUCCESS; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((xcv_data->granted_access & SERVER_ACCESS_ADMINISTER) == 0) { 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_ACCESS_DENIED; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (output_data == NULL || output_data_bytes == 0) { 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_INVALID_PARAMETER; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't handle AddPort or DeletePort since we don't support 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dynamic creation of ports. 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lstrcmp(L"MonitorUI", data_name) == 0) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dll_path_len = 0; 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath dll_path(GetPortMonitorDllName()); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dll_path_len = static_cast<DWORD>(dll_path.value().length()); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (output_data_bytes_needed != NULL) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *output_data_bytes_needed = dll_path_len; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (output_data_bytes < dll_path_len) { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_INSUFFICIENT_BUFFER; 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_val = StringCbCopy(reinterpret_cast<wchar_t*>(output_data), 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_data_bytes, 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dll_path.value().c_str()); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_INVALID_PARAMETER; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret_val; 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2XcvClosePort(HANDLE handle) { 5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delete reinterpret_cast<XcvUiData*>(handle); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI MonitorUiAddPortUi(const wchar_t*, 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND hwnd, 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* monitor_name, 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t**) { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandlePortUi(hwnd, monitor_name); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI MonitorUiConfigureOrDeletePortUI(const wchar_t*, 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND hwnd, 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* port_name) { 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandlePortUi(hwnd, port_name); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace cloud_print 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MONITOR2* WINAPI InitializePrintMonitor2(MONITORINIT*, 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE* handle) { 6044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (handle == NULL) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cloud_print::MonitorData* monitor_data = new cloud_print::MonitorData; 6094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *handle = monitor_data; 6104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!cloud_print::kIsUnittest) { 6114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Unit tests set up their own AtExitManager 6124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) monitor_data->at_exit_manager.reset(new base::AtExitManager()); 6134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Single spooler.exe handles verbose users. 6144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PathService::DisableCache(); 6154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &cloud_print::g_monitor_2; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MONITORUI* WINAPI InitializePrintMonitorUI(void) { 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &cloud_print::g_monitor_ui; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 623