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 OOo 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