source: nscp/helpers/installer_dll/main_dll.cpp @ 1fc246c

0.4.00.4.10.4.2stable
Last change on this file since 1fc246c was 1fc246c, checked in by Michael Medin <michael@…>, 4 years ago

SOme minor fixes to the installer and added archive project

  • Property mode set to 100644
File size: 25.3 KB
Line 
1#include <windows.h>
2#include <msi.h>
3#include <msiquery.h>
4#include <error.hpp>
5#include <Settings.h>
6#include <config.h>
7#include <ServiceCmd.h>
8#include <char_buffer.hpp>
9#include <file_helpers.hpp>
10#include "installer_helper.hpp"
11
12const UINT COST_SERVICE_INSTALL = 2000;
13
14LPCWSTR vcsServiceQuery =
15L"SELECT `ShortName`, `LongName`, `Description`, `Program`, `Attributes`, `Component_` FROM `Services`";
16enum eServiceQuery { feqShortName = 1, feqLongName, feqDesc, feqProgram, feqAttributes, feqComponent };
17enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 };
18
19bool install(msi_helper &h, std::wstring exe, std::wstring service_short_name, std::wstring service_long_name, std::wstring service_description);
20bool uninstall(msi_helper &h, std::wstring service_name);
21UINT SchedServiceMgmt(__in MSIHANDLE hInstall, msi_helper::WCA_TODO todoSched);
22
23extern "C" UINT __stdcall ScheduleInstallService(MSIHANDLE hInstall) {
24        return SchedServiceMgmt(hInstall, msi_helper::WCA_TODO_INSTALL);
25}
26extern "C" UINT __stdcall ScheduleUnInstallService(MSIHANDLE hInstall) {
27        return SchedServiceMgmt(hInstall, msi_helper::WCA_TODO_UNINSTALL);
28}
29extern "C" UINT __stdcall ExecServiceInstall(__in MSIHANDLE hInstall) {
30        HRESULT hr = S_OK;
31        // initialize
32        msi_helper h(hInstall, _T("ExecServiceInstall"));
33        try {
34                msi_helper::custom_action_data_r data(h.getPropery(L"CustomActionData"));
35
36                // loop through all the passed in data
37                while (data.has_more()) {
38                        // extract the custom action data and if rolling back, swap INSTALL and UNINSTALL
39                        int iTodo = data.get_next_int();
40                        if (::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK))
41                        {
42                                if (msi_helper::WCA_TODO_INSTALL == iTodo)
43                                {
44                                        iTodo = msi_helper::WCA_TODO_UNINSTALL;
45                                }
46                                else if (msi_helper::WCA_TODO_UNINSTALL == iTodo)
47                                {
48                                        iTodo = msi_helper::WCA_TODO_INSTALL;
49                                }
50                        }
51
52                        std::wstring shortname = data.get_next_string();
53                        std::wstring longname = data.get_next_string();
54                        std::wstring desc = data.get_next_string();
55                        int attr = data.get_next_int();
56                        BOOL fIgnoreFailures = feaIgnoreFailures == (attr & feaIgnoreFailures);
57                        std::wstring file = data.get_next_string();
58                        switch (iTodo) {
59                        case msi_helper::WCA_TODO_INSTALL:
60                        case msi_helper::WCA_TODO_REINSTALL:
61                                h.logMessage(_T("Installing service install: ") + shortname + _T(", ") + file);
62                                install(h, file, shortname, longname, desc);
63                                break;
64
65                        case msi_helper::WCA_TODO_UNINSTALL:
66                                h.logMessage(_T("Installing service install: ") + shortname + _T(", ") + file);
67                                uninstall(h, shortname);
68                                break;
69                        default:
70                                h.logMessage(_T("IGNORING service install: ") + shortname + _T(", ") + file);
71                        }
72                }
73        } catch (installer_exception e) {
74                h.errorMessage(_T("Failed to install service: ") + e.what());
75                return ERROR_SUCCESS;
76        } catch (...) {
77                h.errorMessage(_T("Failed to install service: <UNKNOWN EXCEPTION>"));
78                return ERROR_INSTALL_FAILURE;
79        }
80        return ERROR_SUCCESS;
81
82}
83
84
85UINT SchedServiceMgmt(__in MSIHANDLE hInstall, msi_helper::WCA_TODO todoSched)
86{
87        msi_helper h(hInstall, _T("SchedServiceInstall"));
88        try {
89                int cFirewallExceptions = 0;
90                h.logMessage(_T("SchedServiceInstall: ") + strEx::itos(todoSched));
91                // anything to do?
92                if (!h.table_exists(L"Services")) {
93                        h.logMessage(_T("Services table doesn't exist, so there are no services to configure."));
94                        return ERROR_SUCCESS;
95                }
96
97                // query and loop through all the firewall exceptions
98                PMSIHANDLE hView = h.open_execute_view(vcsServiceQuery);
99                if (h.isNull(hView)) {
100                        h.logMessage(_T("Failed to query service view!"));
101                        return ERROR_INSTALL_FAILURE;
102                }
103
104                msi_helper::custom_action_data_w custom_data;
105                PMSIHANDLE hRec = h.fetch_record(hView);
106                while (hRec != NULL)
107                {
108                        std::wstring shortname = h.get_record_formatted_string(hRec, feqShortName);
109                        std::wstring longname = h.get_record_formatted_string(hRec, feqLongName);
110                        std::wstring desc = h.get_record_formatted_string(hRec, feqDesc);
111                        std::wstring program = h.get_record_formatted_string(hRec, feqProgram);
112                        int attributes = h.get_record_integer(hRec, feqAttributes);
113                        std::wstring component = h.get_record_string(hRec, feqComponent);
114
115                        // figure out what we're doing for this exception, treating reinstall the same as install
116                        msi_helper::WCA_TODO todoComponent = h.get_component_todo(component);
117                        if ((msi_helper::WCA_TODO_REINSTALL == todoComponent ? msi_helper::WCA_TODO_INSTALL : todoComponent) != todoSched) {
118                                h.logMessage(_T("Component '") + component + _T("' action state (") + strEx::itos(todoComponent) + _T(") doesn't match request (") + strEx::itos(todoSched) + _T(")"));
119                                hRec = h.fetch_record(hView);
120                                continue;
121                        }
122                        h.logMessage(_T("Adding data to CA chunk... "));
123                        // action :: name :: remoteaddresses :: attributes :: target :: {port::protocol | path}
124                        ++cFirewallExceptions;
125                        custom_data.write_int(todoComponent);
126                        custom_data.write_string(shortname);
127                        custom_data.write_string(longname);
128                        custom_data.write_string(desc);
129                        custom_data.write_int(attributes);
130                        //custom_data.write_int(fetApplication);
131                        custom_data.write_string(program);
132                        h.logMessage(_T("Adding data to CA chunk... DONE"));
133                        h.logMessage(_T("CA chunk: ") + custom_data.to_string());
134                        hRec = h.fetch_record(hView);
135                }
136                // schedule ExecFirewallExceptions if there's anything to do
137                if (custom_data.has_data()) {
138                        h.logMessage(_T("Scheduling (WixExecServiceInstall) firewall exception: ") + custom_data.to_string());
139                        if (msi_helper::WCA_TODO_INSTALL == todoSched) {
140                                HRESULT hr = h.do_deferred_action(L"WixRollbackServiceInstall", custom_data, cFirewallExceptions * COST_SERVICE_INSTALL);
141                                if (FAILED(hr)) {
142                                        h.errorMessage(_T("failed to schedule service install exceptions rollback"));
143                                        return hr;
144                                }
145                                hr = h.do_deferred_action(L"WixExecServiceInstall", custom_data, cFirewallExceptions * COST_SERVICE_INSTALL);
146                                if (FAILED(hr)) {
147                                        h.errorMessage(_T("failed to schedule service install exceptions execution"));
148                                        return hr;
149                                }
150                        }
151                        else
152                        {
153                                h.logMessage(_T("Scheduling (WixExecServiceUninstall) firewall exception: ") + custom_data.to_string());
154                                HRESULT hr = h.do_deferred_action(L"WixRollbackServiceUninstall", custom_data, cFirewallExceptions * COST_SERVICE_INSTALL);
155                                if (FAILED(hr)) {
156                                        h.errorMessage(_T("failed to schedule service install exceptions rollback"));
157                                        return hr;
158                                }
159                                hr = h.do_deferred_action(L"WixExecServiceUninstall", custom_data, cFirewallExceptions * COST_SERVICE_INSTALL);
160                                if (FAILED(hr)) {
161                                        h.errorMessage(_T("failed to schedule service install exceptions execution"));
162                                        return hr;
163                                }
164                        }
165                } else
166                        h.logMessage(_T("No services scheduled"));
167        } catch (installer_exception e) {
168                h.errorMessage(_T("Failed to install service: ") + e.what());
169                return ERROR_INSTALL_FAILURE;
170        } catch (...) {
171                h.errorMessage(_T("Failed to install service: <UNKNOWN EXCEPTION>"));
172                return ERROR_INSTALL_FAILURE;
173        }
174        return ERROR_SUCCESS;
175
176}
177/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
178
179//#pragma comment(linker, "/EXPORT:ImportConfig=_ImportConfig@4")
180extern "C" UINT __stdcall ImportConfig (MSIHANDLE hInstall) {
181        msi_helper h(hInstall, _T("ImportConfig"));
182        try {
183                std::wstring target = h.getTargetPath(_T("INSTALLLOCATION"));
184                std::wstring main = h.getPropery(_T("MAIN_CONFIGURATION_FILE"));
185                std::wstring custom = h.getPropery(_T("CUSTOM_CONFIGURATION_FILE"));
186
187                h.setupMyProperty(_T("ALLOWED_HOSTS"), MAIN_ALLOWED_HOSTS_DEFAULT);
188                h.setupMyProperty(_T("NSCLIENT_PWD"), MAIN_SETTINGS_PWD_DEFAULT);
189                h.setupMyProperty(_T("CONF_NRPE"), _T(""));
190                h.setupMyProperty(_T("CONF_NSCLIENT"), _T(""));
191                h.setupMyProperty(_T("CONF_NSCA"), _T(""));
192                h.setupMyProperty(_T("CONF_CHECKS"), _T(""));
193                h.setupMyProperty(_T("CONF_WMI"), _T(""));
194
195                std::wstring filename = target + _T("\\") + main;
196                if (!file_helpers::checks::exists(filename)) {
197                        h.setProperty(_T("CONF_CHECKS_GRAY"), _T(""));
198                        h.setProperty(_T("CONF_CAN_WRITE"), _T("1"));
199                        h.setProperty(_T("CONF_OLD_NOT_FOUND"), _T("1"));
200                        return ERROR_SUCCESS;
201                }
202
203                Settings::getInstance()->setFile(target, main);
204                if (Settings::getInstance()->getActiveType() == _T("INI-file")) {
205                        h.setProperty(_T("CONF_CAN_WRITE"), _T("1"));
206                        CopyFile(filename.c_str(), (h.getTempPath() + _T("\\old_nsc.ini")).c_str(), FALSE);
207                } else
208                        h.setProperty(_T("CONF_CAN_WRITE"), _T("0"));
209
210
211
212
213                std::wstring allowed_hosts = Settings::getInstance()->getString(MAIN_SECTION_TITLE, MAIN_ALLOWED_HOSTS, MAIN_ALLOWED_HOSTS_DEFAULT);
214                h.setMyProperty(_T("ALLOWED_HOSTS"), allowed_hosts);
215
216                std::wstring password = Settings::getInstance()->getString(MAIN_SECTION_TITLE, MAIN_SETTINGS_PWD, MAIN_SETTINGS_PWD_DEFAULT);
217                h.setMyProperty(_T("NSCLIENT_PWD"), password);
218
219                int found_common_checks = 0;
220                settings_base::sectionList list = Settings::getInstance()->getSection(_T("modules"));
221                for (settings_base::sectionList::const_iterator cit=list.begin(); cit!=list.end();++cit) {
222                        if (*cit == _T("NRPEListener.dll")) {
223                                h.setMyProperty(_T("CONF_NRPE"), _T("1"));
224                        }
225                        if (*cit == _T("NSClientListener.dll")) {
226                                h.setMyProperty(_T("CONF_NSCLIENT"), _T("1"));
227                        }
228                        if (*cit == _T("NSCAAgent.dll")) {
229                                h.setMyProperty(_T("CONF_NSCA"), _T("1"));
230                        }
231                        if (*cit == _T("CheckWMI.dll")) {
232                                h.setMyProperty(_T("CONF_WMI"), _T("1"));
233                        }
234                        if (
235                                (*cit == _T("FileLogger.dll")) ||
236                                (*cit == _T("CheckSystem.dll")) ||
237                                (*cit == _T("CheckDisk.dll")) ||
238                                (*cit == _T("CheckEventLog.dll")) ||
239                                (*cit == _T("CheckHelpers.dll"))
240                                ) {
241                                found_common_checks++;
242                        }
243                }
244                if (found_common_checks == 5) {
245                        h.setMyProperty(_T("CONF_CHECKS"), _T("1"));
246                        h.setProperty(_T("CONF_CHECKS_GRAY"), _T(""));
247                } else if (found_common_checks == 0) {
248                        h.setMyProperty(_T("CONF_CHECKS"), _T(""));
249                        h.setProperty(_T("CONF_CHECKS_GRAY"), _T(""));
250                } else {
251                        h.setMyProperty(_T("CONF_CHECKS"), _T("1"));
252                        h.setProperty(_T("CONF_CHECKS_GRAY"), _T("1"));
253                }
254                Settings::destroyInstance();
255                h.setProperty(_T("CONF_OLD_NOT_FOUND"), _T("0"));
256        } catch (installer_exception e) {
257                h.errorMessage(_T("Failed to read old configuration file: ") + e.what());
258                h.setProperty(_T("INSCON_CONFIGURE"),_T("0"));
259                h.setProperty(_T("CONF_CAN_WRITE"), _T("0"));
260                return ERROR_INSTALL_FAILURE;
261        } catch (SettingsException e) {
262                h.errorMessage(_T("Failed to read old configuration file: ") + e.getMessage());
263                h.setProperty(_T("INSCON_CONFIGURE"),_T("0"));
264                h.setProperty(_T("CONF_CAN_WRITE"), _T("0"));
265                return ERROR_SUCCESS;
266        } catch (...) {
267                h.errorMessage(_T("Failed to read old configuration file: <UNKNOWN EXCEPTION>"));
268                h.setProperty(_T("INSCON_CONFIGURE"),_T("0"));
269                h.setProperty(_T("CONF_CAN_WRITE"), _T("0"));
270                return ERROR_INSTALL_FAILURE;
271        }
272        return ERROR_SUCCESS;
273}
274
275
276bool install(msi_helper &h, std::wstring exe, std::wstring service_short_name, std::wstring service_long_name, std::wstring service_description) {
277        h.updateProgress(_T("Preparing to install service"), service_short_name);
278        try {
279                if (serviceControll::isStarted(service_short_name)) {
280                        h.updateProgress(_T("Stopping service"), service_short_name);
281                        serviceControll::Stop(service_short_name);
282                }
283                if (serviceControll::isInstalled(service_short_name)) {
284                        h.updateProgress(_T("Uninstalling service"), service_short_name);
285                        serviceControll::Uninstall(service_short_name);
286                }
287                h.updateProgress(_T("Installing service"), service_short_name);
288                serviceControll::Install(service_short_name, service_long_name, SZDEPENDENCIES, SERVICE_WIN32_OWN_PROCESS, exe);
289        } catch (const serviceControll::SCException& e) {
290                h.errorMessage(_T("Failed to install service: ") + e.error_);
291                return false;
292        }
293        try {
294                serviceControll::SetDescription(service_short_name, service_description);
295        } catch (const serviceControll::SCException& e) {
296                h.errorMessage(_T("Failed to set description of service: ") + e.error_);
297        }
298        return true;
299}
300
301bool uninstall(msi_helper &h, std::wstring service_name) {
302        h.updateProgress(_T("Preparing to uninstall service"), service_name);
303        try {
304                if (!serviceControll::isInstalled(service_name))
305                        return true;
306                if (serviceControll::isStarted(service_name)) {
307                        h.updateProgress(_T("Stopping service"), service_name);
308                        serviceControll::Stop(service_name);
309                }
310                h.updateProgress(_T("Uninstalling service"), service_name);
311                serviceControll::Uninstall(service_name);
312        } catch (const serviceControll::SCException& e) {
313                h.errorMessage(_T("Failed to uninstall service: ") + e.error_);
314                return false;
315        }
316        return true;
317}
318
319/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
320bool write_config(msi_helper &h, std::wstring path, std::wstring file);
321
322extern "C" UINT __stdcall ScheduleWriteConfig (MSIHANDLE hInstall) {
323        msi_helper h(hInstall, _T("ScheduleWriteConfig"));
324        try {
325                std::wstring target = h.getTargetPath(_T("INSTALLLOCATION"));
326                std::wstring main_conf = h.getPropery(_T("MAIN_CONFIGURATION_FILE"));
327                std::wstring custom_conf = h.getPropery(_T("CUSTOM_CONFIGURATION_FILE"));
328
329                std::wstring write = target + _T("\\") + custom_conf;
330                h.logMessage(_T("config file (update): ") + write);
331
332                if (h.getPropery(_T("CONF_CAN_WRITE")) == _T("1")) {
333                        if (h.getPropery(_T("KEEP_WHICH_CONFIG")) == _T("OLD")) {
334                                CopyFile((target + _T("\\nsc.ini")).c_str(), (target + _T("\\nsc.new")).c_str(), FALSE);
335                                CopyFile((h.getTempPath() + _T("\\old_nsc.ini")).c_str(), (target + _T("\\nsc.ini")).c_str(), FALSE);
336                        } else {
337                                CopyFile((h.getTempPath() + _T("\\old_nsc.ini")).c_str(), (target + _T("\\nsc.old")).c_str(), FALSE);
338                        }
339                }
340                if (h.getPropery(_T("KEEP_WHICH_CONFIG")) == _T("NEW")) {
341                        if (!write_config(h, target, custom_conf)) {
342                                h.logMessage(_T("Failed to write configuration"));
343                                return ERROR_INSTALL_FAILURE;
344                        }
345                }
346        } catch (installer_exception e) {
347                h.errorMessage(_T("Failed to install service: ") + e.what());
348                return ERROR_INSTALL_FAILURE;
349        } catch (...) {
350                h.errorMessage(_T("Failed to install service: <UNKNOWN EXCEPTION>"));
351                return ERROR_INSTALL_FAILURE;
352        }
353        return ERROR_SUCCESS;
354}
355extern "C" UINT __stdcall ExecWriteConfig (MSIHANDLE hInstall) {
356        msi_helper h(hInstall, _T("ExecWriteConfig"));
357        try {
358                h.logMessage(_T("RAW: ") + h.getPropery(L"CustomActionData"));
359                msi_helper::custom_action_data_r data(h.getPropery(L"CustomActionData"));
360                h.logMessage(_T("Got CA data: ") + data.to_string());
361                std::wstring path = data.get_next_string();
362                std::wstring file = data.get_next_string();
363                Settings::getInstance()->setFile(path, file, true);
364
365                while (data.has_more()) {
366                        unsigned int mode = data.get_next_int();
367                        if (mode == 1) {
368                        // loop through all the passed in data
369                                std::wstring path = data.get_next_string();
370                                std::wstring key = data.get_next_string();
371                                std::wstring prop = data.get_next_string();
372                                h.logMessage(_T("Writing to config file: ") + path + _T("/") + key + _T(" = ") + prop);
373                                Settings::getInstance()->setString(path, key, prop);
374                                //TODO write config
375                        } else if (mode == 2) {
376                                std::list<std::wstring> list = data.get_next_list();
377                                h.logMessage(_T("Writing modules section: ") + strEx::itos(list.size()));
378                                Settings::getInstance()->writeSection(_T("modules"), list);
379                        } else {
380                                h.errorMessage(_T("Unknown mode in CA data: ") + strEx::itos(mode) + _T(": ") + data.to_string());
381                                return ERROR_INSTALL_FAILURE;
382                        }
383                }
384                Settings::getInstance()->write();
385        } catch (SettingsException e) {
386                h.errorMessage(_T("Failed to write configuration file: ") + e.getMessage());
387                return ERROR_SUCCESS;
388        } catch (installer_exception e) {
389                h.errorMessage(_T("Failed to install service: ") + e.what());
390                return ERROR_INSTALL_FAILURE;
391        } catch (...) {
392                h.errorMessage(_T("Failed to install service: <UNKNOWN EXCEPTION>"));
393                return ERROR_INSTALL_FAILURE;
394        }
395        return ERROR_SUCCESS;
396}
397
398inline void write_string_item_if_changed(msi_helper &h, msi_helper::custom_action_data_w &data, std::wstring property, std::wstring path, std::wstring key) {
399        if (h.isChangedProperyAndOld(property)) {
400                data.write_int(1);
401                data.write_string(path);
402                data.write_string(key);
403                data.write_string(h.getPropery(property));
404        } else
405                h.logMessage(property + _T(" was not changed..."));
406}
407bool write_config(msi_helper &h, std::wstring path, std::wstring file) {
408        std::wstring t;
409        msi_helper::custom_action_data_w data;
410
411        data.write_string(path);
412        data.write_string(file);
413
414        //cd_prop.write_int(1);
415        if (h.getPropery(_T("CONF_CAN_WRITE")) != _T("1")) {
416                h.updateProgress(_T("File is not writable (writing to registry not supported)"), file);
417                return true;
418        }
419
420        //Settings::getInstance()->setFile(path, file, true);
421        write_string_item_if_changed(h, data, _T("ALLOWED_HOSTS"), MAIN_SECTION_TITLE, MAIN_ALLOWED_HOSTS);
422        write_string_item_if_changed(h, data, _T("NSCLIENT_PWD"), MAIN_SECTION_TITLE, MAIN_SETTINGS_PWD);
423
424        settings_base::sectionList list;
425        if (h.isChangedProperyAndOld(_T("CONF_NRPE")))
426                list.push_back(_T("NRPEListener.dll"));
427        if (h.isChangedProperyAndOld(_T("CONF_NSCLIENT")))
428                list.push_back(_T("NSClientListener.dll"));
429        if (h.isChangedProperyAndOld(_T("CONF_NSCA")))
430                list.push_back(_T("NSCAAgent.dll"));
431        if (h.isChangedProperyAndOld(_T("CONF_WMI")))
432                list.push_back(_T("CheckWMI.dll"));
433        if (h.isChangedProperyAndOld(_T("CONF_CHECKS"))) {
434                list.push_back(_T("FileLogger.dll"));
435                list.push_back(_T("CheckSystem.dll"));
436                list.push_back(_T("CheckDisk.dll"));
437                list.push_back(_T("CheckEventLog.dll"));
438                list.push_back(_T("CheckHelpers.dll"));
439        }
440        if (list.size() > 0) {
441                data.write_int(2);
442                data.write_list(list);
443        }
444        if (data.has_data()) {
445                h.logMessage(_T("Scheduling (ExecWriteConfig): ") + data.to_string());
446                HRESULT hr = h.do_deferred_action(L"ExecWriteConfig", data, 1000);
447                if (FAILED(hr)) {
448                        h.errorMessage(_T("failed to schedule config update"));
449                        return hr;
450                }
451        }
452}
453
454
455bool start(msi_helper &h, std::wstring service_name = _T("")) {
456        if (service_name.empty())
457                service_name = SZSERVICENAME;
458        if (!serviceControll::isInstalled(service_name)) {
459                h.logMessage(_T("Service was not installed (so we cannot start it): ")+ service_name);
460                return false;
461        }
462
463        h.updateProgress(_T("Preparing to start service"), service_name);
464        try {
465                if (!serviceControll::isStarted(service_name)) {
466                        h.updateProgress(_T("Starting service"), service_name);
467                        serviceControll::Start(service_name);
468                }
469        } catch (const serviceControll::SCException& e) {
470                h.errorMessage(_T("Failed to start service: ") + e.error_);
471                return false;
472        }
473        return true;
474}
475
476bool stop(msi_helper &h, std::wstring service_name = _T("")) {
477        if (service_name.empty())
478                service_name = SZSERVICENAME;
479        h.updateProgress(_T("Preparing to stopp service"), service_name);
480        try {
481                if (serviceControll::isStarted(service_name)) {
482                        h.updateProgress(_T("Stopping service"), service_name);
483                        serviceControll::Stop(service_name);
484                }
485        } catch (const serviceControll::SCException& e) {
486                h.errorMessage(_T("Failed to stop service: ") + e.error_);
487                return false;
488        }
489        return true;
490}
491
492
493//#pragma comment(linker, "/EXPORT:UpdateConfig=_UpdateConfig@4")
494
495extern "C" UINT __stdcall StartAllServices (MSIHANDLE hInstall) {
496        msi_helper h(hInstall, _T("StartService"));
497        try {
498                std::wstring val = h.getPropery(_T("START_SERVICE_ON_EXIT"));
499                if (val == _T("1")) {
500                        // anything to do?
501                        if (h.table_exists(L"Services")) {
502                                PMSIHANDLE hView = h.open_execute_view(vcsServiceQuery);
503                                if (h.isNull(hView)) {
504                                        h.logMessage(_T("Failed to query service view!"));
505                                        return ERROR_INSTALL_FAILURE;
506                                }
507
508                                msi_helper::custom_action_data_w custom_data;
509                                PMSIHANDLE hRec = h.fetch_record(hView);
510                                while (hRec != NULL)
511                                {
512                                        std::wstring shortname = h.get_record_formatted_string(hRec, feqShortName);
513                                        std::wstring component = h.get_record_string(hRec, feqComponent);
514
515                                        // figure out what we're doing for this exception, treating reinstall the same as install
516                                        msi_helper::WCA_TODO todoComponent = h.get_component_todo(component);
517                                        if ((msi_helper::WCA_TODO_REINSTALL == todoComponent ? msi_helper::WCA_TODO_INSTALL : todoComponent) != msi_helper::WCA_TODO_INSTALL) {
518                                                h.logMessage(_T("Component '") + component + _T("' action state (") + strEx::itos(todoComponent) + _T(") doesn't match request (") + strEx::itos(msi_helper::WCA_TODO_INSTALL) + _T(")"));
519                                                hRec = h.fetch_record(hView);
520                                                continue;
521                                        }
522                                        try {
523                                                if (!serviceControll::isStarted(shortname)) {
524                                                        h.updateProgress(_T("Starting service"), shortname);
525                                                        serviceControll::Start(shortname);
526                                                }
527                                        } catch (const serviceControll::SCException& e) {
528                                                h.logMessage(_T("Failed to start service: ") + shortname + _T(": ") + e.error_);
529                                        }
530                                        hRec = h.fetch_record(hView);
531                                }
532                        }
533                }
534                val = h.getPropery(_T("DONATE_ON_EXIT"));
535                if (val == _T("1")) {
536                        long r = (long)ShellExecute(NULL, _T("open"), _T("https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=michael@medin.name&item_name=Fans+of+NSClient%2B%2B&item_number=Installer+Campaign&amount=10%2e00&currency_code=EUR&return=http%3A//nsclient.org"), NULL, NULL, SW_SHOWNORMAL);
537                        if (r > 32)
538                                return ERROR_SUCCESS;
539                        h.errorMessage(_T("Failed to start web browser for donations..."));
540                        return ERROR_INSTALL_FAILURE;
541                }
542        } catch (installer_exception e) {
543                h.errorMessage(_T("Failed to process finalizing stuff: ") + e.what());
544                return ERROR_INSTALL_FAILURE;
545        } catch (...) {
546                h.errorMessage(_T("Failed to process finalizing stuff: <UNKNOWN EXCEPTION>"));
547                return ERROR_INSTALL_FAILURE;
548        }
549        return ERROR_SUCCESS;
550}
551
552
553extern "C" UINT __stdcall StopAllServices (MSIHANDLE hInstall) {
554        msi_helper h(hInstall, _T("StopAllServices"));
555        try {
556
557                // anything to do?
558                if (!h.table_exists(L"Services")) {
559                        h.logMessage(_T("Services table doesn't exist, so there are no services to configure."));
560                        return ERROR_SUCCESS;
561                }
562
563                // query and loop through all the firewall exceptions
564                PMSIHANDLE hView = h.open_execute_view(vcsServiceQuery);
565                if (h.isNull(hView)) {
566                        h.logMessage(_T("Failed to query service view!"));
567                        return ERROR_INSTALL_FAILURE;
568                }
569
570                msi_helper::custom_action_data_w custom_data;
571                PMSIHANDLE hRec = h.fetch_record(hView);
572                while (hRec != NULL)
573                {
574                        std::wstring shortname = h.get_record_formatted_string(hRec, feqShortName);
575                        std::wstring component = h.get_record_string(hRec, feqComponent);
576
577                        // figure out what we're doing for this exception, treating reinstall the same as install
578                        msi_helper::WCA_TODO todoComponent = h.get_component_todo(component);
579                        if (todoComponent == msi_helper::WCA_TODO_REINSTALL)
580                                todoComponent = msi_helper::WCA_TODO_INSTALL;
581                        h.logMessage(_T("Component '") + component + _T("' action state (") + strEx::itos(todoComponent));
582                        if (todoComponent != msi_helper::WCA_TODO_INSTALL && todoComponent != msi_helper::WCA_TODO_UNINSTALL) {
583                                h.logMessage(_T("Component '") + component + _T("' action state (") + strEx::itos(todoComponent) + _T(") doesn't match request (IN/UN/RE)"));
584                                hRec = h.fetch_record(hView);
585                                continue;
586                        }
587                        try {
588                                if (serviceControll::isStarted(shortname)) {
589                                        h.updateProgress(_T("Stopping service"), shortname);
590                                        serviceControll::Stop(shortname);
591                                }
592                        } catch (const serviceControll::SCException& e) {
593                                h.logMessage(_T("Failed to stop service: ") + shortname + _T(": ") + e.error_);
594                        }
595                        hRec = h.fetch_record(hView);
596                }
597        } catch (installer_exception e) {
598                h.errorMessage(_T("Failed to stop service: ") + e.what());
599                return ERROR_INSTALL_FAILURE;
600        } catch (...) {
601                h.errorMessage(_T("Failed to stop service: <UNKNOWN EXCEPTION>"));
602                return ERROR_INSTALL_FAILURE;
603        }
604        return ERROR_SUCCESS;
605}
606
607extern "C" UINT __stdcall NeedUninstall (MSIHANDLE hInstall) {
608        msi_helper h(hInstall, _T("NeedUninstall"));
609        try {
610                std::list<std::wstring> list = h.enumProducts();
611                for (std::list<std::wstring>::const_iterator cit = list.begin(); cit != list.end(); ++cit) {
612                        if ((*cit) == _T("{E7CF81FE-8505-4D4A-8ED3-48949C8E4D5B}")) {
613                                h.errorMessage(_T("Found old NSClient++/OP5 client installed, will uninstall it now!"));
614                                std::wstring command = _T("msiexec /uninstall ") + (*cit);
615                                TCHAR *cmd = new TCHAR[command.length()+1];
616                                wcsncpy_s(cmd, command.length()+1, command.c_str(), command.length());
617                                cmd[command.length()] = 0;
618                                PROCESS_INFORMATION pi;
619                                STARTUPINFO si;
620                                ZeroMemory(&si, sizeof(STARTUPINFO));
621                                si.cb = sizeof(STARTUPINFO);
622
623                                BOOL processOK = CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
624                                delete [] cmd;
625                                if (processOK) {
626                                        DWORD dwstate = WaitForSingleObject(pi.hProcess, 1000*60);
627                                        if (dwstate == WAIT_TIMEOUT)
628                                                h.errorMessage(_T("Failed to wait for process (probably not such a big deal, the uninstall usualy takes alonger)!"));
629                                } else {
630                                        h.errorMessage(_T("Failed to start process: ") + error::lookup::last_error());
631                                }
632                        }
633                }
634       
635        } catch (installer_exception e) {
636                h.errorMessage(_T("Failed to start service: ") + e.what());
637                return ERROR_INSTALL_FAILURE;
638        } catch (...) {
639                h.errorMessage(_T("Failed to start service: <UNKNOWN EXCEPTION>"));
640                return ERROR_INSTALL_FAILURE;
641        }
642        return ERROR_SUCCESS;
643};
Note: See TracBrowser for help on using the repository browser.