diff options
author | abodenha@chromium.org <abodenha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-10 00:12:56 +0000 |
---|---|---|
committer | abodenha@chromium.org <abodenha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-10 00:12:56 +0000 |
commit | 4072805a4252409a786d8b8a2e0b35e7c374ff0c (patch) | |
tree | fdb655d0364e5bda044361e401655fd6a1d9db14 /cloud_print/virtual_driver/win | |
parent | 544df7c7697ec1e7d2005b953ed5983114268ad5 (diff) | |
download | chromium_src-4072805a4252409a786d8b8a2e0b35e7c374ff0c.zip chromium_src-4072805a4252409a786d8b8a2e0b35e7c374ff0c.tar.gz chromium_src-4072805a4252409a786d8b8a2e0b35e7c374ff0c.tar.bz2 |
Remove extranious fonts from the ppd file
Properly handle dependencies for installing the ppd
Register for uninstall
BUG=106094
TEST=Copy port monitor dlls, virtual_driver_setup.exe, and gcp-driver.ppd into a single folder and launch the setup as admin. The driver should be installed. Run it again with --uninstall (or choose the cloud print driver in add/remove programs) and the driver should be uninstalled and the containing folder removed.
Review URL: http://codereview.chromium.org/8770019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113889 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cloud_print/virtual_driver/win')
3 files changed, 181 insertions, 73 deletions
diff --git a/cloud_print/virtual_driver/win/install/setup.cc b/cloud_print/virtual_driver/win/install/setup.cc index 1b83cbb..d64ea9a 100644 --- a/cloud_print/virtual_driver/win/install/setup.cc +++ b/cloud_print/virtual_driver/win/install/setup.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include <windows.h> +#include <setupapi.h> // Must be included after windows.h #include <winspool.h> #include "base/at_exit.h" @@ -19,14 +20,24 @@ #include "cloud_print/virtual_driver/win/virtual_driver_helpers.h" #include "grit/virtual_driver_setup_resources.h" +#include <strsafe.h> // Must be after base headers to avoid deprecation + // warnings. + namespace { const wchar_t kVersionKey[] = L"pv"; const wchar_t kNameKey[] = L"name"; -const wchar_t kLangKey[] = L"lang"; const wchar_t kNameValue[] = L"GCP Virtual Driver"; -const wchar_t kLangValue[] = L"rn"; +const wchar_t kPpdName[] = L"GCP-DRIVER.PPD"; +const wchar_t kDriverName[] = L"MXDWDRV.DLL"; +const wchar_t kUiDriverName[] = L"PS5UI.DLL"; +const wchar_t kHelpName[] = L"PSCRIPT.HLP"; +const wchar_t* kDependencyList[] = {kDriverName, kUiDriverName, kHelpName}; +const wchar_t kUninstallRegistry[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + L"{74AA24E0-AC50-4B28-BA46-9CF05467C9B7}"; +const wchar_t kInstallerName[] = L"virtual_driver_setup.exe"; -void SetRegistryKeys() { +void SetOmahaKeys() { base::win::RegKey key; if (key.Create(HKEY_LOCAL_MACHINE, cloud_print::kKeyLocation, KEY_SET_VALUE) != ERROR_SUCCESS) { @@ -49,13 +60,12 @@ void SetRegistryKeys() { } if (key.WriteValue(kVersionKey, version_string.c_str()) != ERROR_SUCCESS || - key.WriteValue(kNameKey, kNameValue) != ERROR_SUCCESS || - key.WriteValue(kLangKey, kLangValue) != ERROR_SUCCESS) { + key.WriteValue(kNameKey, kNameValue) != ERROR_SUCCESS) { LOG(ERROR) << "Unable to set registry keys"; } } -void DeleteRegistryKeys() { +void DeleteOmahaKeys() { base::win::RegKey key; if (key.Open(HKEY_LOCAL_MACHINE, cloud_print::kKeyLocation, DELETE) != ERROR_SUCCESS) { @@ -66,25 +76,7 @@ void DeleteRegistryKeys() { } } -HRESULT GetPpdPath(FilePath* path) { - if (!PathService::Get(base::DIR_EXE, path)) { - LOG(ERROR) << "Unable to get install path."; - return ERROR_PATH_NOT_FOUND; - } - *path = path->Append(L"GCP-driver.ppd"); - return S_OK; -} - -HRESULT GetPortMonitorDllPath(FilePath* path) { - if (!PathService::Get(base::DIR_EXE, path)) { - LOG(ERROR) << "Unable to get install path."; - return ERROR_PATH_NOT_FOUND; - } - *path = path->Append(cloud_print::GetPortMonitorDllName()); - return S_OK; -} - -HRESULT GetPortMonitorInstallPath(FilePath* path) { +HRESULT GetNativeSystemPath(FilePath* path) { if (cloud_print::IsSystem64Bit()) { if (!PathService::Get(base::DIR_WINDOWS, path)) { return ERROR_PATH_NOT_FOUND; @@ -98,34 +90,35 @@ HRESULT GetPortMonitorInstallPath(FilePath* path) { return ERROR_PATH_NOT_FOUND; } } - *path = path->Append(cloud_print::GetPortMonitorDllName()); return S_OK; } +HRESULT GetPortMonitorTargetPath(FilePath* path) { + HRESULT result = GetNativeSystemPath(path); + if (SUCCEEDED(result)) + *path = path->Append(cloud_print::GetPortMonitorDllName()); + return result; +} + HRESULT GetRegsvr32Path(FilePath* path) { - if (!PathService::Get(base::DIR_SYSTEM, path)) { - LOG(ERROR) << "Unable to get system path."; - return ERROR_PATH_NOT_FOUND; - } - *path = path->Append(FilePath(L"regsvr32.exe")); - return S_OK; + HRESULT result = GetNativeSystemPath(path); + if (SUCCEEDED(result)) + *path = path->Append(FilePath(L"regsvr32.exe")); + return result; } -HRESULT RegisterPortMonitor(bool install) { +HRESULT RegisterPortMonitor(bool install, const FilePath& install_path) { FilePath target_path; HRESULT result = S_OK; - result = GetPortMonitorInstallPath(&target_path); + result = GetPortMonitorTargetPath(&target_path); if (!SUCCEEDED(result)) { LOG(ERROR) << "Unable to get port monitor target path."; return result; } - FilePath source_path; - result = GetPortMonitorDllPath(&source_path); - if (!SUCCEEDED(result)) { - LOG(ERROR) << "Unable to get dll source path."; - return result; - } + string16 source; + source = cloud_print::GetPortMonitorDllName(); if (install) { + FilePath source_path = install_path.Append(source); if (!file_util::CopyFileW(source_path, target_path)) { LOG(ERROR) << "Unable copy port monitor dll from " << source_path.value() << " to " << target_path.value(); @@ -144,7 +137,14 @@ HRESULT RegisterPortMonitor(bool install) { if (!install) { command_line.AppendArg("/u"); } - command_line.AppendArgPath(source_path); + + FilePath final_path; + if (!PathService::Get(base::DIR_SYSTEM, &final_path)) { + LOG(ERROR) << "Unable to get system path."; + return ERROR_PATH_NOT_FOUND; + } + final_path = final_path.Append(cloud_print::GetPortMonitorDllName()); + command_line.AppendArgPath(final_path); base::LaunchOptions options; HANDLE process_handle; @@ -189,24 +189,63 @@ DWORDLONG GetVersionNumber() { return retval; } -HRESULT InstallPpd() { +UINT CALLBACK CabinetCallback(PVOID data, + UINT notification, + UINT_PTR param1, + UINT_PTR param2 ) { + FilePath* temp_path = reinterpret_cast<FilePath*>(data); + if (notification == SPFILENOTIFY_FILEINCABINET) { + FILE_IN_CABINET_INFO* info = + reinterpret_cast<FILE_IN_CABINET_INFO*>(param1); + for (int i = 0; i < arraysize(kDependencyList); i++) { + if (wcsstr(info->NameInCabinet, kDependencyList[i])) { + StringCchCopy(info->FullTargetName, MAX_PATH, + temp_path->Append(kDependencyList[i]).value().c_str()); + return FILEOP_DOIT; + } + } + + return FILEOP_SKIP; + } + return NO_ERROR; +} + +void ReadyPpdDependencies(const FilePath& install_path) { + CORE_PRINTER_DRIVER driver; + GetCorePrinterDrivers(NULL, + NULL, + L"{D20EA372-DD35-4950-9ED8-A6335AFE79F0}", + 1, + &driver); + DWORD size = MAX_PATH; + wchar_t package_path[MAX_PATH]; + GetPrinterDriverPackagePath(NULL, + NULL, + NULL, + driver.szPackageID, + package_path, + MAX_PATH, + &size); + + SetupIterateCabinet(package_path, + 0, + CabinetCallback, + const_cast<FilePath*>(&install_path)); +} + +HRESULT InstallPpd(const FilePath& install_path) { DRIVER_INFO_6 driver_info = {0}; HRESULT result = S_OK; // Set up paths for the files we depend on. - FilePath source_path; - FilePath driver_dir; - cloud_print::GetPrinterDriverDir(&driver_dir); - FilePath xps_path = driver_dir.Append(L"mxdwdrv.dll"); - FilePath ui_path = driver_dir.Append(L"ps5ui.dll"); - FilePath ui_help_path = driver_dir.Append(L"unidrv.hlp"); - result = GetPpdPath(&source_path); - if (!SUCCEEDED(result)) { - return result; - } + FilePath ppd_path = install_path.Append(kPpdName); + FilePath xps_path = install_path.Append(kDriverName); + FilePath ui_path = install_path.Append(kUiDriverName); + FilePath ui_help_path = install_path.Append(kHelpName); + ReadyPpdDependencies(install_path); // None of the print API structures likes constant strings even though they // don't modify the string. const_casting is the cleanest option. - driver_info.pDataFile = const_cast<LPWSTR>(source_path.value().c_str()); + driver_info.pDataFile = const_cast<LPWSTR>(ppd_path.value().c_str()); driver_info.pHelpFile = const_cast<LPWSTR>(ui_help_path.value().c_str()); driver_info.pDriverPath = const_cast<LPWSTR>(xps_path.value().c_str()); driver_info.pConfigFile = const_cast<LPWSTR>(ui_path.value().c_str()); @@ -223,19 +262,14 @@ HRESULT InstallPpd() { // Set up supported print system version. Must be 3. driver_info.cVersion = 3; - // TODO(abodenha@chromium.org) Properly handle dependencies. - // GPD files are often dependent on various Windows core drivers. - // I haven't found a reliable way to express those dependencies - // other than using an INF for installation. if (!AddPrinterDriverEx(NULL, 6, reinterpret_cast<BYTE*>(&driver_info), APD_COPY_NEW_FILES|APD_COPY_FROM_DIRECTORY)) { result = cloud_print::GetLastHResult(); LOG(ERROR) << "Unable to add printer driver"; - return result; } - return S_OK; + return result; } HRESULT UninstallPpd() { @@ -309,14 +343,59 @@ HRESULT UninstallPrinter(void) { return S_OK; } -HRESULT InstallVirtualDriver(void) { +void SetupUninstall(const FilePath& install_path) { + // Now write the Windows Uninstall entries + // Minimal error checking here since the install can contiunue + // if this fails. + base::win::RegKey key; + if (key.Create(HKEY_LOCAL_MACHINE, kUninstallRegistry, + KEY_SET_VALUE) != ERROR_SUCCESS) { + LOG(ERROR) << "Unable to open key"; + return; + } + CommandLine uninstall_command(install_path.Append(kInstallerName)); + uninstall_command.AppendArg("--uninstall"); + key.WriteValue(L"UninstallString", + uninstall_command.GetCommandLineString().c_str()); + key.WriteValue(L"InstallLocation", install_path.value().c_str()); + + + // Get the version resource. + scoped_ptr<FileVersionInfo> version_info( + FileVersionInfo::CreateFileVersionInfoForCurrentModule()); + + if (version_info.get()) { + FileVersionInfoWin* version_info_win = + static_cast<FileVersionInfoWin*>(version_info.get()); + key.WriteValue(L"DisplayVersion", + version_info_win->file_version().c_str()); + key.WriteValue(L"Publisher", version_info_win->company_name().c_str()); + } else { + LOG(ERROR) << "Unable to get version string"; + } + key.WriteValue(L"DisplayName", + cloud_print::LoadLocalString(IDS_DRIVER_NAME).c_str()); + key.WriteValue(L"NoModify", 1); + key.WriteValue(L"NoRepair", 1); +} + +void CleanupUninstall() { + ::RegDeleteKey(HKEY_LOCAL_MACHINE, kUninstallRegistry); +} + +HRESULT InstallVirtualDriver(const FilePath& install_path) { HRESULT result = S_OK; - result = RegisterPortMonitor(true); + if (!file_util::CreateDirectory(install_path)) { + LOG(ERROR) << "Can't create install directory"; + return ERROR_ACCESS_DENIED; + } + SetupUninstall(install_path); + result = RegisterPortMonitor(true, install_path); if (!SUCCEEDED(result)) { LOG(ERROR) << "Unable to register port monitor."; return result; } - result = InstallPpd(); + result = InstallPpd(install_path); if (!SUCCEEDED(result)) { LOG(ERROR) << "Unable to install Ppd."; return result; @@ -326,11 +405,11 @@ HRESULT InstallVirtualDriver(void) { LOG(ERROR) << "Unable to install printer."; return result; } - SetRegistryKeys(); + SetOmahaKeys(); return S_OK; } -HRESULT UninstallVirtualDriver(void) { +HRESULT UninstallVirtualDriver(const FilePath& install_path) { HRESULT result = S_OK; result = UninstallPrinter(); if (!SUCCEEDED(result)) { @@ -342,15 +421,35 @@ HRESULT UninstallVirtualDriver(void) { LOG(ERROR) << "Unable to remove Ppd."; return result; } - result = RegisterPortMonitor(false); + result = RegisterPortMonitor(false, install_path); if (!SUCCEEDED(result)) { LOG(ERROR) << "Unable to remove port monitor."; return result; } - DeleteRegistryKeys(); + DeleteOmahaKeys(); + file_util::Delete(install_path, true); + CleanupUninstall(); return S_OK; } +HRESULT LaunchChildForUninstall() { + FilePath installer_source; + if (PathService::Get(base::FILE_EXE, &installer_source)) { + FilePath temp_path; + if (file_util::CreateTemporaryFile(&temp_path)) { + file_util::Move(installer_source, temp_path); + file_util::DeleteAfterReboot(temp_path); + CommandLine command_line(temp_path); + command_line.AppendArg("--douninstall"); + base::LaunchOptions options; + if (!base::LaunchProcess(command_line, options, NULL)) { + LOG(ERROR) << "Unable to launch child uninstall."; + return ERROR_NOT_SUPPORTED; + } + } + } + return S_OK; +} } // namespace int WINAPI WinMain(__in HINSTANCE hInstance, @@ -359,11 +458,17 @@ int WINAPI WinMain(__in HINSTANCE hInstance, __in int nCmdShow) { base::AtExitManager at_exit_manager; CommandLine::Init(0, NULL); - HRESULT retval = S_OK; - if (CommandLine::ForCurrentProcess()->HasSwitch("uninstall")) { - retval = UninstallVirtualDriver(); - } else { - retval = InstallVirtualDriver(); + + FilePath install_path; + HRESULT retval = PathService::Get(base::DIR_EXE, &install_path); + if (SUCCEEDED(retval)) { + if (CommandLine::ForCurrentProcess()->HasSwitch("douninstall")) { + retval = UninstallVirtualDriver(install_path); + } else if (CommandLine::ForCurrentProcess()->HasSwitch("uninstall")) { + retval = LaunchChildForUninstall(); + } else { + retval = InstallVirtualDriver(install_path); + } } // Installer is silent by default as required by Omaha. if (CommandLine::ForCurrentProcess()->HasSwitch("verbose")) { diff --git a/cloud_print/virtual_driver/win/install/virtual_driver_install.gyp b/cloud_print/virtual_driver/win/install/virtual_driver_install.gyp index 37ca71c..696a4c6 100644 --- a/cloud_print/virtual_driver/win/install/virtual_driver_install.gyp +++ b/cloud_print/virtual_driver/win/install/virtual_driver_install.gyp @@ -32,6 +32,9 @@ 'msvs_settings': { 'VCLinkerTool': { 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS + 'AdditionalDependencies': [ + 'setupapi.lib', + ], }, }, }, diff --git a/cloud_print/virtual_driver/win/virtual_driver_common_resources.rc b/cloud_print/virtual_driver/win/virtual_driver_common_resources.rc index d90c230..1c03825 100644 --- a/cloud_print/virtual_driver/win/virtual_driver_common_resources.rc +++ b/cloud_print/virtual_driver/win/virtual_driver_common_resources.rc @@ -25,10 +25,10 @@ BEGIN BEGIN VALUE "CompanyName", "Google Inc." VALUE "FileDescription", "GCP Virtual Driver" - VALUE "FileVersion", "0, 1, 0, 1" + VALUE "FileVersion", "0.1.0.1" VALUE "InternalName", "GCP Virtual Driver" VALUE "ProductName", "GCP Virtual Driver" - VALUE "ProductVersion", "0, 1, 0, 1" + VALUE "ProductVersion", "0.1.0.1" VALUE "LegalCopyright", "Copyright (c) 2011 The Chromium Authors. All rights reserved." END END |