1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 /*
25 After installation of the AOO filter for the indexing service
26 it is necessary to restart the indexing service in order to
27 activate the filter. This is the most reliable way to get the
28 indexing service working. We only restart the service if it is
29 already running. If we have insufficient privileges to restart
30 the service we do nothing.
31 */
32
33 #ifdef _MSC_VER
34 #pragma warning(push, 1) /* disable warnings within system headers */
35 #endif
36 #define WIN32_LEAN_AND_MEAN
37 #include <windows.h>
38 #include <msiquery.h>
39 #ifdef _MSC_VER
40 #pragma warning(pop)
41 #endif
42
43 /*
44 Advapi.dll needs to be loaded dynamically because the service
45 control functions are not available under Windows 9x.
46 */
47 typedef BOOL (__stdcall * CloseServiceHandle_t)(SC_HANDLE);
48 typedef BOOL (__stdcall * ControlService_t)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
49 typedef SC_HANDLE (__stdcall * OpenSCManager_t)(LPCSTR, LPCSTR, DWORD);
50 typedef SC_HANDLE (__stdcall * OpenService_t)(SC_HANDLE, LPCSTR, DWORD);
51 typedef BOOL (__stdcall * QueryServiceStatus_t)(SC_HANDLE, LPSERVICE_STATUS);
52 typedef BOOL (__stdcall * StartService_t)(SC_HANDLE, DWORD, LPCSTR*);
53
54 CloseServiceHandle_t CloseServiceHandle_ = NULL;
55 ControlService_t ControlService_ = NULL;
56 OpenSCManager_t OpenSCManager_ = NULL;
57 OpenService_t OpenService_ = NULL;
58 QueryServiceStatus_t QueryServiceStatus_ = NULL;
59 StartService_t StartService_ = NULL;
60
61 const LPTSTR INDEXING_SERVICE_NAME = TEXT("cisvc");
62
StopIndexingService(SC_HANDLE hService)63 bool StopIndexingService(SC_HANDLE hService)
64 {
65 SERVICE_STATUS status;
66
67 if (ControlService_(hService, SERVICE_CONTROL_STOP, &status))
68 {
69 // Check the status until the service is no longer stop pending.
70 if (QueryServiceStatus_(hService, &status))
71 {
72 DWORD startTime = GetTickCount();
73 DWORD oldCheckPoint = status.dwCheckPoint;
74
75 while (status.dwCurrentState == SERVICE_STOP_PENDING)
76 {
77 // Do not wait longer than the wait hint. A good interval is
78 // one tenth the wait hint, but no less than 1 second and no
79 // more than 10 seconds.
80 DWORD waitTime = status.dwWaitHint / 10;
81
82 if (waitTime < 1000)
83 waitTime = 1000;
84 else if (waitTime > 10000)
85 waitTime = 10000;
86
87 Sleep(waitTime);
88
89 // Check the status again.
90 if (!QueryServiceStatus_(hService, &status) ||
91 (status.dwCurrentState == SERVICE_STOPPED))
92 break;
93
94 if (status.dwCheckPoint > oldCheckPoint)
95 {
96 startTime = GetTickCount();
97 oldCheckPoint = status.dwCheckPoint;
98 }
99 else if ((GetTickCount() - startTime) > status.dwWaitHint)
100 {
101 break; // service doesn't react anymore
102 }
103 }
104 }
105 }
106 return (status.dwCurrentState == SERVICE_STOPPED);
107 }
108
StartIndexingService(SC_HANDLE hService)109 void StartIndexingService(SC_HANDLE hService)
110 {
111 if (StartService_(hService, 0, NULL))
112 {
113 SERVICE_STATUS status;
114
115 // Check the status until the service is no longer stop pending.
116 if (QueryServiceStatus_(hService, &status))
117 {
118 DWORD startTime = GetTickCount();
119 DWORD oldCheckPoint = status.dwCheckPoint;
120
121 while (status.dwCurrentState == SERVICE_START_PENDING)
122 {
123 // Do not wait longer than the wait hint. A good interval is
124 // one tenth the wait hint, but no less than 1 second and no
125 // more than 10 seconds.
126 DWORD waitTime = status.dwWaitHint / 10;
127
128 if (waitTime < 1000)
129 waitTime = 1000;
130 else if (waitTime > 10000)
131 waitTime = 10000;
132
133 Sleep(waitTime);
134
135 // Check the status again.
136 if (!QueryServiceStatus_(hService, &status) ||
137 (status.dwCurrentState == SERVICE_STOPPED))
138 break;
139
140 if (status.dwCheckPoint > oldCheckPoint)
141 {
142 startTime = GetTickCount();
143 oldCheckPoint = status.dwCheckPoint;
144 }
145 else if ((GetTickCount() - startTime) > status.dwWaitHint)
146 {
147 // service doesn't react anymore
148 break;
149 }
150 }
151 }
152 }
153 }
154
RestartIndexingService(MSIHANDLE)155 extern "C" UINT __stdcall RestartIndexingService(MSIHANDLE)
156 {
157 //MessageBox(NULL, TEXT("Restarting Indexing Service"), TEXT("Message"), MB_OK | MB_ICONINFORMATION);
158
159 HMODULE hAdvapi32 = LoadLibrary("advapi32.dll");
160
161 if (hAdvapi32)
162 {
163 CloseServiceHandle_ = reinterpret_cast<CloseServiceHandle_t>(GetProcAddress(hAdvapi32, "CloseServiceHandle"));
164 ControlService_ = reinterpret_cast<ControlService_t>(GetProcAddress(hAdvapi32, "ControlService"));
165 OpenSCManager_ = reinterpret_cast<OpenSCManager_t>(GetProcAddress(hAdvapi32, "OpenSCManagerA"));
166 OpenService_ = reinterpret_cast<OpenService_t>(GetProcAddress(hAdvapi32, "OpenServiceA"));
167 QueryServiceStatus_ = reinterpret_cast<QueryServiceStatus_t>(GetProcAddress(hAdvapi32, "QueryServiceStatus"));
168 StartService_ = reinterpret_cast<StartService_t>(GetProcAddress(hAdvapi32, "StartServiceA"));
169 }
170
171 /* On systems other than Windows 2000/XP the service API
172 functions might not be available */
173 if (!hAdvapi32 ||
174 !(CloseServiceHandle_ && ControlService_ && OpenSCManager_ && OpenService_ && QueryServiceStatus_ && StartService_))
175 return ERROR_SUCCESS;
176
177 SC_HANDLE hSCManager = OpenSCManager_(
178 NULL, // local machine
179 NULL, // ServicesActive database
180 SC_MANAGER_ALL_ACCESS);
181
182 if (hSCManager != NULL)
183 {
184 SC_HANDLE hIndexingService = OpenService_(
185 hSCManager, INDEXING_SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP);
186
187 if (hIndexingService)
188 {
189 SERVICE_STATUS status;
190 ZeroMemory(&status, sizeof(status));
191
192 if (QueryServiceStatus_(hIndexingService, &status) &&
193 (status.dwCurrentState == SERVICE_RUNNING))
194 {
195 if (StopIndexingService(hIndexingService))
196 StartIndexingService(hIndexingService);
197 }
198 CloseServiceHandle_(hIndexingService);
199 }
200 CloseServiceHandle_(hSCManager);
201 }
202 return ERROR_SUCCESS;
203 }
204
205