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) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <lmcons.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shellapi.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlobj.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <strsafe.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <userenv.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.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" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 21bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/process.h" 22bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.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) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_util::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, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 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. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HandlePortUi(HWND hwnd, const 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, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const 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(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!chrome_profile.empty()) { 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) command_line.AppendSwitchPath(switches::kUserDataDir, chrome_profile); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.AppendSwitchPath(switches::kCloudPrintFile, 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xps_path); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.AppendSwitchNative(switches::kCloudPrintFileType, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kXpsMimeType); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.AppendSwitchNative(switches::kCloudPrintJobTitle, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_title); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.AppendSwitch(switches::kCloudPrintDeleteFile); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.as_user = primary_token_scoped; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchProcess(command_line, options, NULL); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Launches a page to allow the user to download chrome. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(abodenha@chromium.org) Point to a custom page explaining what's wrong 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// rather than the generic chrome download page. See 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/chromium/issues/detail?id=112019 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LaunchChromeDownloadPage() { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kIsUnittest) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE token = NULL; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetUserToken(&token)) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to get user token."; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle token_scoped(token); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath ie_path; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathService::Get(base::DIR_PROGRAM_FILESX86, &ie_path); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ie_path = ie_path.Append(kIePath); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine command_line(ie_path); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.AppendArg(kChromeInstallUrl); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.as_user = token_scoped; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchProcess(command_line, options, NULL); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns false if the print job is being run in a context 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that shouldn't be launching Chrome. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ValidateCurrentUser() { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE token = NULL; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetUserToken(&token)) { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we can't get the token we're probably not impersonating 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the user, so validation should fail. 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle token_scoped(token); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD session_id = 0; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dummy; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetTokenInformation(token_scoped, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TokenSessionId, 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void *>(&session_id), 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(DWORD), 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dummy)) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (session_id == 0) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath ReadPathFromRegistry(HKEY root, const wchar_t* path_name) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::RegKey gcp_key(HKEY_CURRENT_USER, kCloudPrintRegKey, KEY_READ); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 data; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(gcp_key.ReadValue(path_name, &data)) && 2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::PathExists(base::FilePath(data))) { 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(data); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath ReadPathFromAnyRegistry(const wchar_t* path_name) { 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath result = ReadPathFromRegistry(HKEY_CURRENT_USER, path_name); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result.empty()) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path_name); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetChromeExePath() { 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = ReadPathFromAnyRegistry(kChromeExePathRegValue); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!path.empty()) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return chrome_launcher_support::GetAnyChromePath(); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetChromeProfilePath() { 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = ReadPathFromAnyRegistry(kChromeProfilePathRegValue); 3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!path.empty() && base::DirectoryExists(path)) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path; 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2EnumPorts(HANDLE, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t*, 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD level, 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE* ports, 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD ports_size, 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* needed_bytes, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* returned) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (needed_bytes == NULL) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "needed_bytes should not be NULL."; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (level == 1) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *needed_bytes = sizeof(PORT_INFO_1); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (level == 2) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *needed_bytes = sizeof(PORT_INFO_2); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Level " << level << "is not supported."; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_LEVEL); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *needed_bytes += static_cast<DWORD>(cloud_print::kPortNameSize); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ports_size < *needed_bytes) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << *needed_bytes << " bytes are required. Only " 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ports_size << " were allocated."; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INSUFFICIENT_BUFFER); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ports == NULL) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "ports should not be NULL."; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (returned == NULL) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "returned should not be NULL."; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Windows expects any strings refernced by PORT_INFO_X structures to 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appear at the END of the buffer referenced by ports. Placing 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // strings immediately after the PORT_INFO_X structure will cause 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EnumPorts to fail until the spooler is restarted. 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is NOT mentioned in the documentation. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* string_target = 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<wchar_t*>(ports + ports_size - 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortNameSize); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (level == 1) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_INFO_1* port_info = reinterpret_cast<PORT_INFO_1*>(ports); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->pName = string_target; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringCbCopy(port_info->pName, 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortNameSize, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortName); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_INFO_2* port_info = reinterpret_cast<PORT_INFO_2*>(ports); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->pPortName = string_target; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringCbCopy(port_info->pPortName, 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortNameSize, 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print::kPortName); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->pMonitorName = NULL; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->pDescription = NULL; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->fPortType = PORT_TYPE_WRITE; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_info->Reserved = 0; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *returned = 1; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2OpenPort(HANDLE, wchar_t*, HANDLE* handle) { 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PortData* port_data = new PortData(); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_data == NULL) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to allocate memory for internal structures."; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(E_OUTOFMEMORY); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle == NULL) { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "handle should not be NULL."; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *handle = (HANDLE)port_data; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2StartDocPort(HANDLE port_handle, 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* printer_name, 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD job_id, 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD, 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE*) { 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetGoogleUpdateUsage(kGoogleUpdateProductId); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_handle == NULL) { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "port_handle should not be NULL."; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (printer_name == NULL) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "printer_name should not be NULL."; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ValidateCurrentUser()) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(abodenha@chromium.org) Abort the print job. 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PortData* port_data = reinterpret_cast<PortData*>(port_handle); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_data->job_id = job_id; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!OpenPrinter(printer_name, &(port_data->printer_handle), NULL)) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Unable to open printer " << printer_name << "."; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can continue without a handle to the printer. 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It just means we can't get the job title or tell the spooler that 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the print job is complete. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is the normal flow during a unit test. 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_data->printer_handle = NULL; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath& file_path = port_data->file_path; 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath app_data_dir = GetAppDataDir(); 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (app_data_dir.empty()) 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteLeakedFiles(app_data_dir); 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!file_util::CreateDirectory(app_data_dir) || 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !file_util::CreateTemporaryFileInDir(app_data_dir, &file_path)) { 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Can't create temporary file in " << app_data_dir.value(); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) port_data->file = file_util::OpenFile(file_path, "wb+"); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_data->file == NULL) { 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Error opening file " << file_path.value() << "."; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2WritePort(HANDLE port_handle, 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE* buffer, 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD buffer_size, 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* bytes_written) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PortData* port_data = reinterpret_cast<PortData*>(port_handle); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ValidateCurrentUser()) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(abodenha@chromium.org) Abort the print job. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes_written = 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<DWORD>(fwrite(buffer, 1, buffer_size, port_data->file)); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*bytes_written > 0) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2ReadPort(HANDLE, BYTE*, DWORD, DWORD* read_bytes) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Read is not supported."; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *read_bytes = 0; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_NOT_SUPPORTED); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2EndDocPort(HANDLE port_handle) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ValidateCurrentUser()) { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(abodenha@chromium.org) Abort the print job. 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PortData* port_data = reinterpret_cast<PortData*>(port_handle); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_data == NULL) { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_data->file != NULL) { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::CloseFile(port_data->file); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_data->file = NULL; 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool delete_file = true; 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 file_size = 0; 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_util::GetFileSize(port_data->file_path, &file_size); 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (file_size > 0) { 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string16 job_title; 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (port_data->printer_handle != NULL) { 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetJobTitle(port_data->printer_handle, 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) port_data->job_id, 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &job_title); 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!LaunchPrintDialog(port_data->file_path, job_title)) { 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LaunchChromeDownloadPage(); 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_file = false; 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delete_file) 5067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(port_data->file_path, false); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_data->printer_handle != NULL) { 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tell the spooler that the job is complete. 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetJob(port_data->printer_handle, 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_data->job_id, 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JOB_CONTROL_SENT_TO_PRINTER); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) port_data->Close(); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return success even if we can't display the dialog. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(abodenha@chromium.org) Come up with a better way of handling 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this situation. 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2ClosePort(HANDLE port_handle) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port_handle == NULL) { 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "port_handle should not be NULL."; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PortData* port_data = reinterpret_cast<PortData*>(port_handle); 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete port_data; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VOID WINAPI Monitor2Shutdown(HANDLE monitor_handle) { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (monitor_handle != NULL) { 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MonitorData* monitor_data = 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<MonitorData*>(monitor_handle); 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete monitor_handle; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2XcvOpenPort(HANDLE, 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t*, 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACCESS_MASK granted_access, 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE* handle) { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle == NULL) { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "handle should not be NULL."; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XcvUiData* xcv_data = new XcvUiData(); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (xcv_data == NULL) { 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to allocate memory for internal structures."; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(E_OUTOFMEMORY); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xcv_data->granted_access = granted_access; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *handle = (HANDLE)xcv_data; 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD WINAPI Monitor2XcvDataPort(HANDLE xcv_handle, 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* data_name, 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE*, 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD, 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE* output_data, 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD output_data_bytes, 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* output_data_bytes_needed) { 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XcvUiData* xcv_data = reinterpret_cast<XcvUiData*>(xcv_handle); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD ret_val = ERROR_SUCCESS; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((xcv_data->granted_access & SERVER_ACCESS_ADMINISTER) == 0) { 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_ACCESS_DENIED; 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (output_data == NULL || output_data_bytes == 0) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_INVALID_PARAMETER; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't handle AddPort or DeletePort since we don't support 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dynamic creation of ports. 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lstrcmp(L"MonitorUI", data_name) == 0) { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dll_path_len = 0; 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath dll_path(GetPortMonitorDllName()); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dll_path_len = static_cast<DWORD>(dll_path.value().length()); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (output_data_bytes_needed != NULL) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *output_data_bytes_needed = dll_path_len; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (output_data_bytes < dll_path_len) { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_INSUFFICIENT_BUFFER; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_val = StringCbCopy(reinterpret_cast<wchar_t*>(output_data), 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_data_bytes, 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dll_path.value().c_str()); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_INVALID_PARAMETER; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret_val; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI Monitor2XcvClosePort(HANDLE handle) { 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XcvUiData* xcv_data = reinterpret_cast<XcvUiData*>(handle); 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete xcv_data; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI MonitorUiAddPortUi(const wchar_t*, 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND hwnd, 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* monitor_name, 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t**) { 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandlePortUi(hwnd, monitor_name); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI MonitorUiConfigureOrDeletePortUI(const wchar_t*, 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND hwnd, 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* port_name) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandlePortUi(hwnd, port_name); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace cloud_print 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MONITOR2* WINAPI InitializePrintMonitor2(MONITORINIT*, 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE* handle) { 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cloud_print::MonitorData* monitor_data = new cloud_print::MonitorData; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (monitor_data == NULL) { 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle != NULL) { 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *handle = (HANDLE)monitor_data; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cloud_print::kIsUnittest) { 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unit tests set up their own AtExitManager 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) monitor_data->at_exit_manager.reset(new base::AtExitManager()); 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Single spooler.exe handles verbose users. 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PathService::DisableCache(); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &cloud_print::g_monitor_2; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MONITORUI* WINAPI InitializePrintMonitorUI(void) { 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &cloud_print::g_monitor_ui; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 647