blob: 25393f0e2a1b87d9a4630430db0984386337288b [file] [log] [blame]
// Copyright 2008-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
#include "omaha/goopdate/goopdate_command_line_validator.h"
#include "omaha/common/const_cmd_line.h"
#include "omaha/common/debug.h"
#include "omaha/common/error.h"
#include "omaha/common/logging.h"
#include "omaha/common/string.h"
#include "omaha/goopdate/command_line.h"
#include "omaha/goopdate/command_line_parser.h"
#include "omaha/goopdate/command_line_validator.h"
#include "omaha/goopdate/extra_args_parser.h"
namespace omaha {
GoopdateCommandLineValidator::GoopdateCommandLineValidator() {
}
GoopdateCommandLineValidator::~GoopdateCommandLineValidator() {
}
HRESULT GoopdateCommandLineValidator::Setup() {
validator_.reset(new CommandLineValidator);
CString cmd_line;
// gu.exe
cmd_line.Empty();
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnNoArgs);
// gu.exe /c [/nocrashserver
cmd_line.Format(_T("/%s [/%s"), kCmdLineCore, kCmdLineNoCrashHandler);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnCore);
// gu.exe /crashhandler
cmd_line.Format(_T("/%s"), kCmdLineCrashHandler);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnCrashHandler);
// gu.exe /svc
cmd_line.Format(_T("/%s"), kCmdLineService);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnService);
// gu.exe /regsvc
cmd_line.Format(_T("/%s"), kCmdLineRegisterService);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnServiceRegister);
// gu.exe /unregsvc
cmd_line.Format(_T("/%s"), kCmdLineUnregisterService);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnServiceUnregister);
// gu.exe /regserver
cmd_line.Format(_T("/%s"), kCmdRegServer);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnRegServer);
// gu.exe /unregserver
cmd_line.Format(_T("/%s"), kCmdUnregServer);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnUnregServer);
// gu.exe /netdiags
cmd_line.Format(_T("/%s"), kCmdLineNetDiags);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnNetDiags);
// gu.exe /crash
cmd_line.Format(_T("/%s"), kCmdLineCrash);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnCrash);
// gu.exe -Embedding. The -Embedding text is injected via COM.
CreateScenario(kCmdLineComServerDash,
&GoopdateCommandLineValidator::OnComServer);
// gu.exe /install <extraargs> [/appargs <appargs> [/installsource source
// [/silent [/eularequired [/oem [/installelevated
cmd_line.Format(_T("/%s extra [/%s appargs [/%s src [/%s [/%s [/%s [/%s"),
kCmdLineInstall,
kCmdLineAppArgs,
kCmdLineInstallSource,
kCmdLineSilent,
kCmdLineEulaRequired,
kCmdLineOem,
kCmdLineInstallElevated);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnInstall);
// gu.exe /update
cmd_line.Format(_T("/%s"), kCmdLineUpdate);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnUpdate);
// gu.exe /ig <extraargs> [/appargs <appargs> [/installsource source
// [/silent [/eularequired [/offlineinstall
cmd_line.Format(_T("/%s extraargs [/%s appargs [/%s source [/%s [/%s [/%s"),
kCmdLineFinishGoogleUpdateInstall,
kCmdLineAppArgs,
kCmdLineInstallSource,
kCmdLineSilent,
kCmdLineEulaRequired,
kCmdLineOfflineInstall);
CreateScenario(cmd_line,
&GoopdateCommandLineValidator::OnFinishInstallGoopdate);
// gu.exe /handoff <extraargs> [/appargs <appargs> [/installsource source
// [/silent [/eularequired [/offlineinstall
cmd_line.Format(_T("/%s extra [/%s appargs [/%s source [/%s [/%s [/%s"),
kCmdLineAppHandoffInstall,
kCmdLineAppArgs,
kCmdLineInstallSource,
kCmdLineSilent,
kCmdLineEulaRequired,
kCmdLineOfflineInstall);
CreateScenario(cmd_line,
&GoopdateCommandLineValidator::OnInstallHandoffWorker);
// gu.exe /ua [/installsource source [/uninstall
cmd_line.Format(_T("/%s [/%s source [/%s"),
kCmdLineUpdateApps, kCmdLineInstallSource, kCmdLineUninstall);
CreateScenario(cmd_line,
&GoopdateCommandLineValidator::OnUpdateApps);
// gu.exe /ug [/machine
cmd_line.Format(_T("/%s [/%s"),
kCmdLineFinishGoogleUpdateUpdate, kCmdLineMachine);
CreateScenario(cmd_line,
&GoopdateCommandLineValidator::OnFinishUpdateGoopdate);
// gu.exe /report <crash_filename> [/machine
// [/custom_info <custom_info_filename>
cmd_line.Format(_T("/%s filename [/%s [/%s customfilename"),
kCmdLineReport,
kCmdLineMachine,
kCmdLineCustomInfoFileName);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnReportCrash);
// gu.exe /report /i <crash_filename> [/machine
cmd_line.Format(_T("/%s /%s filename [/%s"),
kCmdLineReport,
kCmdLineInteractive,
kCmdLineMachine);
CreateScenario(cmd_line,
&GoopdateCommandLineValidator::OnReportCrashInteractive);
// gu.exe /pi <domainurl> <args> /installsource oneclick
cmd_line.Format(_T("/%s domainurl args /%s oneclick"),
kCmdLineWebPlugin,
kCmdLineInstallSource);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnWebPlugin);
// gu.exe /cr
cmd_line.Format(_T("/%s"), kCmdLineCodeRedCheck);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnCodeRed);
// gu.exe /recover <repair_file>
cmd_line.Format(_T("/%s repairfile"), kCmdLineRecover);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnRecover);
// gu.exe /recover /machine <repair_file>
cmd_line.Format(_T("/%s /%s repairfile"), kCmdLineRecover, kCmdLineMachine);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnRecoverMachine);
// gu.exe /registerproduct "extraargs" [/installsource source
cmd_line.Format(_T("/%s extraargs [/%s source"),
kCmdLineRegisterProduct,
kCmdLineInstallSource);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnRegisterProduct);
// gu.exe /unregisterproduct "extraargs"
cmd_line.Format(_T("/%s extraargs"), kCmdLineUnregisterProduct);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnUnregisterProduct);
//
// Legacy support command lines.
//
// gu.exe /uiuser <manifestfilename>
cmd_line.Format(_T("/%s filename"),
kCmdLineLegacyUserManifest);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnUiUserManifest);
// TODO(omaha): Can we remove this case or is it here for back compat?
// gu.exe /ui /lang en <manifestfilename>
cmd_line.Format(_T("/%s /%s en filename"),
kCmdLineLegacyUi,
kCmdLineLegacyLang);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnUiLangManifest);
// gu.exe /ui <manifestfilename>
cmd_line.Format(_T("/%s filename"), kCmdLineLegacyUi);
CreateScenario(cmd_line, &GoopdateCommandLineValidator::OnUiManifest);
// gu.exe /handoff <extraargs> /lang <en> [/installsource source
cmd_line.Format(_T("/%s extraargs /%s en [/%s source"),
kCmdLineAppHandoffInstall,
kCmdLineLegacyLang,
kCmdLineInstallSource);
CreateScenario(cmd_line,
&GoopdateCommandLineValidator::OnInstallHandoffWorkerLegacy);
// gu.exe /install <extraargs> /installsource source /lang en.
cmd_line.Format(_T("/%s extraargs /%s source /%s en"),
kCmdLineInstall, kCmdLineInstallSource, kCmdLineLegacyLang);
CreateScenario(cmd_line,
&GoopdateCommandLineValidator::OnInstallWithSourceLegacy);
return S_OK;
}
// TODO(Omaha): Add check that each scenario is unique and does not overlap an
// existing one in DBG builds.
HRESULT GoopdateCommandLineValidator::Validate(const CommandLineParser* parser,
CommandLineArgs* args) {
ASSERT1(parser);
ASSERT1(args);
parser_ = parser;
args_ = args;
CString scenario_name;
HRESULT hr = validator_->Validate(*parser_, &scenario_name);
if (FAILED(hr)) {
CORE_LOG(LE, (_T("[GoopdateCommandLineValidator::Validate Failed][0x%x]"),
hr));
return hr;
}
MapScenarioHandlersIter iter = scenario_handlers_.find(scenario_name);
if (iter == scenario_handlers_.end()) {
ASSERT1(false);
return GOOGLEUPDATE_COMMANDLINE_E_NO_SCENARIO_HANDLER;
}
ScenarioHandler handler = (*iter).second;
return (this->*handler)();
}
void GoopdateCommandLineValidator::CreateScenario(const TCHAR* cmd_line,
ScenarioHandler handler) {
// Prepend the program name onto the cmd_line.
CString scenario_cmd_line;
scenario_cmd_line.Format(_T("prog.exe %s"), cmd_line);
CString scenario_name;
validator_->CreateScenarioFromCmdLine(scenario_cmd_line, &scenario_name);
// TODO(omaha): Make sure it doesn't already exist.
scenario_handlers_[scenario_name] = handler;
}
HRESULT GoopdateCommandLineValidator::GetExtraAndAppArgs(const CString& name) {
HRESULT hr = parser_->GetSwitchArgumentValue(name,
0,
&args_->extra_args_str);
if (FAILED(hr)) {
return hr;
}
hr = parser_->GetSwitchArgumentValue(kCmdLineAppArgs,
0,
&args_->app_args_str);
if (FAILED(hr)) {
args_->app_args_str.Empty();
}
ExtraArgsParser extra_args_parser;
return extra_args_parser.Parse(args_->extra_args_str,
args_->app_args_str,
&(args_->extra));
}
HRESULT GoopdateCommandLineValidator::OnNoArgs() {
args_->mode = COMMANDLINE_MODE_NOARGS;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnCore() {
args_->mode = COMMANDLINE_MODE_CORE;
args_->is_crash_handler_disabled = parser_->HasSwitch(kCmdLineNoCrashHandler);
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnCrashHandler() {
args_->mode = COMMANDLINE_MODE_CRASH_HANDLER;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnService() {
args_->mode = COMMANDLINE_MODE_SERVICE;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnServiceRegister() {
args_->mode = COMMANDLINE_MODE_SERVICE_REGISTER;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnServiceUnregister() {
args_->mode = COMMANDLINE_MODE_SERVICE_UNREGISTER;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnRegServer() {
args_->mode = COMMANDLINE_MODE_REGSERVER;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnUnregServer() {
args_->mode = COMMANDLINE_MODE_UNREGSERVER;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnNetDiags() {
args_->mode = COMMANDLINE_MODE_NETDIAGS;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnCrash() {
args_->mode = COMMANDLINE_MODE_CRASH;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnComServer() {
args_->mode = COMMANDLINE_MODE_COMSERVER;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnInstall() {
args_->mode = COMMANDLINE_MODE_INSTALL;
parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
0,
&(args_->install_source));
args_->is_silent_set = parser_->HasSwitch(kCmdLineSilent);
args_->is_eula_required_set = parser_->HasSwitch(kCmdLineEulaRequired);
args_->is_oem_set = parser_->HasSwitch(kCmdLineOem);
args_->is_install_elevated = parser_->HasSwitch(kCmdLineInstallElevated);
return GetExtraAndAppArgs(kCmdLineInstall);
}
HRESULT GoopdateCommandLineValidator::OnInstallWithSourceLegacy() {
args_->mode = COMMANDLINE_MODE_INSTALL;
parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
0,
&(args_->install_source));
parser_->GetSwitchArgumentValue(kCmdLineLegacyLang,
0,
&(args_->extra.language));
return GetExtraAndAppArgs(kCmdLineInstall);
}
HRESULT GoopdateCommandLineValidator::OnUpdate() {
args_->mode = COMMANDLINE_MODE_UPDATE;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnInstallHandoffWorker() {
args_->mode = COMMANDLINE_MODE_HANDOFF_INSTALL;
parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
0,
&(args_->install_source));
args_->is_silent_set = parser_->HasSwitch(kCmdLineSilent);
args_->is_eula_required_set = parser_->HasSwitch(kCmdLineEulaRequired);
args_->is_offline_set = parser_->HasSwitch(kCmdLineOfflineInstall);
return GetExtraAndAppArgs(kCmdLineAppHandoffInstall);
}
HRESULT GoopdateCommandLineValidator::OnInstallHandoffWorkerLegacy() {
args_->mode = COMMANDLINE_MODE_HANDOFF_INSTALL;
HRESULT hr = GetExtraAndAppArgs(kCmdLineAppHandoffInstall);
if (FAILED(hr)) {
return hr;
}
parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
0,
&(args_->install_source));
return parser_->GetSwitchArgumentValue(kCmdLineLegacyLang,
0,
&(args_->extra.language));
}
HRESULT GoopdateCommandLineValidator::OnUpdateApps() {
args_->mode = COMMANDLINE_MODE_UA;
args_->is_uninstall_set = parser_->HasSwitch(kCmdLineUninstall);
parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
0,
&(args_->install_source));
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnFinishInstallGoopdate() {
args_->mode = COMMANDLINE_MODE_IG;
parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
0,
&(args_->install_source));
args_->is_silent_set = parser_->HasSwitch(kCmdLineSilent);
args_->is_eula_required_set = parser_->HasSwitch(kCmdLineEulaRequired);
args_->is_offline_set = parser_->HasSwitch(kCmdLineOfflineInstall);
return GetExtraAndAppArgs(kCmdLineFinishGoogleUpdateInstall);
}
HRESULT GoopdateCommandLineValidator::OnFinishUpdateGoopdate() {
args_->mode = COMMANDLINE_MODE_UG;
args_->is_machine_set = parser_->HasSwitch(kCmdLineMachine);
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnReportCrash() {
args_->mode = COMMANDLINE_MODE_REPORTCRASH;
args_->is_machine_set = parser_->HasSwitch(kCmdLineMachine);
parser_->GetSwitchArgumentValue(kCmdLineCustomInfoFileName,
0,
&(args_->custom_info_filename));
return parser_->GetSwitchArgumentValue(kCmdLineReport,
0,
&(args_->crash_filename));
}
HRESULT GoopdateCommandLineValidator::OnReportCrashInteractive() {
args_->mode = COMMANDLINE_MODE_REPORTCRASH;
args_->is_interactive_set = true;
args_->is_machine_set = parser_->HasSwitch(kCmdLineMachine);
return parser_->GetSwitchArgumentValue(kCmdLineInteractive,
0,
&(args_->crash_filename));
}
HRESULT GoopdateCommandLineValidator::OnUiManifest() {
args_->mode = COMMANDLINE_MODE_LEGACYUI;
return parser_->GetSwitchArgumentValue(kCmdLineLegacyUi,
0,
&(args_->legacy_manifest_path));
}
HRESULT GoopdateCommandLineValidator::OnUiLangManifest() {
args_->mode = COMMANDLINE_MODE_LEGACYUI;
HRESULT hr = parser_->GetSwitchArgumentValue(kCmdLineLegacyLang,
0,
&(args_->extra.language));
if (FAILED(hr)) {
return hr;
}
return parser_->GetSwitchArgumentValue(kCmdLineLegacyLang,
1,
&(args_->legacy_manifest_path));
}
HRESULT GoopdateCommandLineValidator::OnUiUserManifest() {
args_->mode = COMMANDLINE_MODE_LEGACY_MANIFEST_HANDOFF;
return parser_->GetSwitchArgumentValue(kCmdLineLegacyUserManifest,
0,
&(args_->legacy_manifest_path));
}
HRESULT GoopdateCommandLineValidator::OnWebPlugin() {
HRESULT hr = parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
0,
&(args_->install_source));
if (FAILED(hr)) {
return hr;
}
// Validate install_source value.
args_->install_source.MakeLower();
if (args_->install_source.Compare(kCmdLineInstallSource_OneClick) != 0) {
args_->install_source.Empty();
return E_INVALIDARG;
}
args_->mode = COMMANDLINE_MODE_WEBPLUGIN;
CString urldomain;
hr = parser_->GetSwitchArgumentValue(kCmdLineWebPlugin,
0,
&urldomain);
if (FAILED(hr)) {
return hr;
}
hr = StringUnescape(urldomain, &(args_->webplugin_urldomain));
if (FAILED(hr)) {
return hr;
}
CString webplugin_args;
hr = parser_->GetSwitchArgumentValue(kCmdLineWebPlugin,
1,
&webplugin_args);
if (FAILED(hr)) {
return hr;
}
return StringUnescape(webplugin_args, &(args_->webplugin_args));
}
HRESULT GoopdateCommandLineValidator::OnCodeRed() {
args_->mode = COMMANDLINE_MODE_CODE_RED_CHECK;
return S_OK;
}
HRESULT GoopdateCommandLineValidator::OnRecover() {
args_->mode = COMMANDLINE_MODE_RECOVER;
return parser_->GetSwitchArgumentValue(
kCmdLineRecover,
0,
&(args_->code_red_metainstaller_path));
}
HRESULT GoopdateCommandLineValidator::OnRecoverMachine() {
args_->mode = COMMANDLINE_MODE_RECOVER;
args_->is_machine_set = true;
return parser_->GetSwitchArgumentValue(
kCmdLineMachine,
0,
&(args_->code_red_metainstaller_path));
}
HRESULT GoopdateCommandLineValidator::OnRegisterProduct() {
args_->mode = COMMANDLINE_MODE_REGISTER_PRODUCT;
parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
0,
&(args_->install_source));
return GetExtraAndAppArgs(kCmdLineRegisterProduct);
}
HRESULT GoopdateCommandLineValidator::OnUnregisterProduct() {
args_->mode = COMMANDLINE_MODE_UNREGISTER_PRODUCT;
return GetExtraAndAppArgs(kCmdLineUnregisterProduct);
}
} // namespace omaha