1
/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
29
* Search the registry for a service whose ImagePath starts
30
* with our install directory. Stop and remove it if requested.
32
static TCHAR last_service_name[128];
33
int remove_service(TCHAR *installdir, int check_only) {
37
if(wcslen(installdir) < 3) {
38
WcaLog(LOGMSG_STANDARD, "INSTALLDIR is suspiciously short, better not do anything.");
43
WcaLog(LOGMSG_STANDARD, "Determining number of matching services...");
44
int servicecount = remove_service(installdir, 1);
45
if(servicecount <= 0) {
46
WcaLog(LOGMSG_STANDARD, "No services found, not removing anything.");
48
} else if(servicecount == 1) {
50
swprintf_s(buf, sizeof(buf), TEXT("There is a service called '%ls' set up to run from this installation. Do you wish me to stop and remove that service?"), last_service_name);
51
int rc = MessageBox(NULL, buf, TEXT("Removing MySQL Server"), MB_ICONQUESTION|MB_YESNOCANCEL|MB_SYSTEMMODAL);
52
if(rc == IDCANCEL) return -1;
53
if(rc != IDYES) return 0;
54
} else if(servicecount > 0) {
56
swprintf_s(buf, sizeof(buf), TEXT("There appear to be %d services set up to run from this installation. Do you wish me to stop and remove those services?"), servicecount);
57
int rc = MessageBox(NULL, buf, TEXT("Removing MySQL Server"), MB_ICONQUESTION|MB_YESNOCANCEL|MB_SYSTEMMODAL);
58
if(rc == IDCANCEL) return -1;
59
if(rc != IDYES) return 0;
63
if(check_only == -1) check_only = 0;
65
WcaLog(LOGMSG_STANDARD, "Looking for service...");
66
WcaLog(LOGMSG_STANDARD, "INSTALLDIR = %ls", installdir);
67
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\services"), 0, KEY_READ, &hKey)==ERROR_SUCCESS) {
70
DWORD keylen = sizeof(keyname);
72
/* Go through all services in the registry */
73
while(RegEnumKeyExW(hKey, index, keyname, &keylen, NULL, NULL, NULL, &t) == ERROR_SUCCESS) {
76
DWORD pathlen = sizeof(path)-1;
77
if (RegOpenKeyExW(hKey, keyname, NULL, KEY_READ, &hServiceKey) == ERROR_SUCCESS) {
78
/* Look at the ImagePath value of each service */
79
if (RegQueryValueExW(hServiceKey, TEXT("ImagePath"), NULL, NULL, (LPBYTE)path, &pathlen) == ERROR_SUCCESS) {
82
if(p[0] == '"') p += 1;
83
/* See if it is similar to our install directory */
84
if(wcsncmp(p, installdir, wcslen(installdir)) == 0) {
85
WcaLog(LOGMSG_STANDARD, "Found service '%ls' with ImagePath '%ls'.", keyname, path);
86
swprintf_s(last_service_name, sizeof(last_service_name), TEXT("%ls"), keyname);
87
/* If we are supposed to stop and remove the service... */
89
WcaLog(LOGMSG_STANDARD, "Trying to stop the service.");
90
SC_HANDLE hSCM = NULL;
91
hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
93
SC_HANDLE hService = NULL;
94
hService = OpenService(hSCM, keyname, SERVICE_STOP|SERVICE_QUERY_STATUS|DELETE);
95
if(hService != NULL) {
96
WcaLog(LOGMSG_STANDARD, "Waiting for the service to stop...");
97
SERVICE_STATUS status;
98
/* Attempt to stop the service */
99
if(ControlService(hService, SERVICE_CONTROL_STOP, &status)) {
100
/* Now wait until it's stopped */
101
while("it's one big, mean and cruel world out there") {
102
if(!QueryServiceStatus(hService, &status)) break;
103
if(status.dwCurrentState == SERVICE_STOPPED) break;
106
WcaLog(LOGMSG_STANDARD, "Stopped the service.");
108
/* Mark the service for deletion */
109
DeleteService(hService);
110
CloseServiceHandle(hService);
112
CloseServiceHandle(hSCM);
118
RegCloseKey(hServiceKey);
121
keylen = sizeof(keyname)-1;
125
WcaLog(LOGMSG_STANDARD, "Can't seem to go through the list of installed services in the registry.");
130
UINT wrap(MSIHANDLE hInstall, char *name, int check_only) {
132
UINT er = ERROR_SUCCESS;
134
hr = WcaInitialize(hInstall, name);
135
ExitOnFailure(hr, "Failed to initialize");
137
WcaLog(LOGMSG_STANDARD, "Initialized.");
139
TCHAR INSTALLDIR[1024];
140
DWORD INSTALLDIR_size = sizeof(INSTALLDIR);
141
if(MsiGetPropertyW(hInstall, TEXT("CustomActionData"), INSTALLDIR, &INSTALLDIR_size) == ERROR_SUCCESS) {
142
int rc = remove_service(INSTALLDIR, check_only);
144
er = ERROR_CANCELLED;
147
er = ERROR_CANT_ACCESS_FILE;
151
return WcaFinalize(er);
154
UINT __stdcall RemoveServiceNoninteractive(MSIHANDLE hInstall)
156
return wrap(hInstall, "RemoveServiceNoninteractive", -1);
159
UINT __stdcall RemoveService(MSIHANDLE hInstall)
161
return wrap(hInstall, "RemoveService", 0);
164
UINT __stdcall TestService(MSIHANDLE hInstall)
166
return wrap(hInstall, "TestService", 1);
169
/* DllMain - Initialize and cleanup WiX custom action utils */
170
extern "C" BOOL WINAPI DllMain(
171
__in HINSTANCE hInst,
178
case DLL_PROCESS_ATTACH:
179
WcaGlobalInitialize(hInst);
182
case DLL_PROCESS_DETACH: