xref: /AOO41X/main/setup_native/source/win32/customactions/shellextensions/registerextensions.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #undef UNICODE
29 #undef _UNICODE
30 
31 #define _WIN32_WINDOWS 0x0410
32 
33 #ifdef _MSC_VER
34 #pragma warning(push, 1) /* disable warnings within system headers */
35 #define WIN32_LEAN_AND_MEAN
36 #endif
37 #include <windows.h>
38 #include <msiquery.h>
39 #include <shellapi.h>
40 #ifdef _MSC_VER
41 #pragma warning(pop)
42 #endif
43 
44 #include <malloc.h>
45 #include <assert.h>
46 #include <string.h>
47 
48 #ifdef UNICODE
49 #define _UNICODE
50 #define _tstring    wstring
51 #else
52 #define _tstring    string
53 #endif
54 #include <tchar.h>
55 #include <string>
56 
57 /** creates a temporary folder with a unique name.
58 
59     The returned string is a file URL.
60 */
61 // static std::_tstring createTempFolder()
62 // {
63 //     BOOL bExist = FALSE;
64 //     TCHAR szTempName[MAX_PATH];
65 //     do
66 //     {
67 //         bExist = FALSE;
68 //         // Get the temp path.
69 //         TCHAR lpPathBuffer[MAX_PATH];
70 //         DWORD dwRetVal = GetTempPath(MAX_PATH, lpPathBuffer);
71 //         if (dwRetVal > MAX_PATH || (dwRetVal == 0))
72 //         {
73 //             //fprintf (stderr, "GetTempPath failed with error %d.\n", GetLastError());
74 //             return TEXT("");
75 //         }
76 //         // Create a temporary file.
77 //         UINT uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files
78 //                                        "upg",        // temp file name prefix
79 //                                        0,            // create unique name
80 //                                        szTempName);  // buffer for name
81 //         if (uRetVal == 0)
82 //         {
83 //             //fprintf (stderr, "GetTempFileName failed with error %d.\n", GetLastError());
84 //             return TEXT("");
85 //         }
86 //         //Delete the file
87 //         BOOL bDel = DeleteFile(szTempName);
88 //         if (FALSE == bDel)
89 //         {
90 //             //fprintf(stderr, "Could not delete temp file. Error %d.\n", GetLastError());
91 //             return TEXT("");
92 //         }
93 //         // Create the directory
94 //         BOOL bDir = CreateDirectory(szTempName, NULL);
95 //         if (FALSE == bDir)
96 //         {
97 //             DWORD error =GetLastError();
98 //             if (ERROR_ALREADY_EXISTS == error)
99 //             {
100 //                 bExist = TRUE;
101 //             }
102 //             else
103 //             {
104 //                 //fprintf(stderr, "CreateDirectory failed with error %d.\n", error);
105 //                 return TEXT("");
106 //             }
107 //         }
108 //     } while(bExist);
109 
110 //     std::_tstring cur(szTempName);
111 //     //make a file URL from the path
112 //     std::_tstring ret(TEXT("file:///"));
113 //     for (std::_tstring::iterator i = cur.begin(); i != cur.end(); i++)
114 //     {
115 //         if (*i == '\\')
116 //             ret.append(TEXT("/"));
117 //         else
118 //             ret.push_back(*i);
119 //     }
120 // //    MessageBox(NULL, ret.c_str(), "createTempFolder", MB_OK);
121 //     return ret.c_str();
122 // }
123 
124 /** deletes the temporary folder.
125     The argument must be a file URL.
126 */
127 // static void deleteTempFolder(const std::_tstring& sTempFolder)
128 // {
129 //     if (sTempFolder.size() == 0)
130 //         return;
131 //     //convert the file URL to a path
132 //     const std::_tstring path(sTempFolder.substr(8));
133 //     std::_tstring path2;
134 // //    MessageBox(NULL, path.c_str(), "del1", MB_OK);
135 //     for (std::_tstring::const_iterator i = path.begin(); i != path.end(); i++)
136 //     {
137 //         if (*i == '/')
138 //             path2.append(TEXT("\\"));
139 //         else
140 //             path2.push_back(*i);
141 //     }
142 
143 //     //We need a null terminated string with two nulls in the end
144 //     //for the SHFILEOPSTRUCT
145 //     const TCHAR * szTemp = path2.c_str();
146 //     size_t size = path2.size();
147 //     TCHAR * szTemp2 = new TCHAR[size + 2];
148 //     ZeroMemory(szTemp2, (size + 2) * sizeof(TCHAR));
149 //     memcpy(szTemp2, szTemp, size * sizeof(TCHAR));
150 
151 // //    MessageBox(NULL, szTemp2, "del3", MB_OK);
152 //     SHFILEOPSTRUCT operation =
153 //         {
154 //             NULL,
155 //             FO_DELETE,
156 //             szTemp2,
157 //             NULL,
158 //             FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR,
159 //             FALSE,
160 //             NULL,
161 //             NULL
162 //         };
163 
164 //     SHFileOperation( &operation);
165 //     delete [] szTemp2;
166 // }
167 
168 
169 
170 static std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty )
171 {
172     std::_tstring result;
173     TCHAR szDummy[1] = TEXT("");
174     DWORD nChars = 0;
175 
176     if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA )
177     {
178         DWORD nBytes = ++nChars * sizeof(TCHAR);
179         LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
180         ZeroMemory( buffer, nBytes );
181         MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
182         result = buffer;
183     }
184 
185     return result;
186 }
187 
188 /* creates a child process which is specified in lpCommand.
189 
190   out_exitCode is the exit code of the child process
191 
192 
193 **/
194 static BOOL ExecuteCommand( LPCTSTR lpCommand, DWORD * out_exitCode)
195 {
196     BOOL                fSuccess = FALSE;
197     STARTUPINFO         si;
198     PROCESS_INFORMATION pi;
199 
200     ZeroMemory( &si, sizeof(si) );
201     si.cb = sizeof(si);
202 
203     fSuccess = CreateProcess(
204         NULL,
205         (LPTSTR)lpCommand,
206         NULL,
207         NULL,
208         FALSE,
209         0,
210         NULL,
211         NULL,
212         &si,
213         &pi
214         );
215 
216     if ( fSuccess )
217     {
218         WaitForSingleObject( pi.hProcess, INFINITE );
219 
220         if (!GetExitCodeProcess( pi.hProcess, out_exitCode))
221             fSuccess = FALSE;
222 
223         CloseHandle( pi.hProcess );
224         CloseHandle( pi.hThread );
225     }
226 
227     return fSuccess;
228 }
229 
230 static BOOL RemoveCompleteDirectory( std::_tstring sPath )
231 {
232     bool bDirectoryRemoved = true;
233 
234     std::_tstring mystr;
235     std::_tstring sPattern = sPath + TEXT("\\") + TEXT("*.*");
236     WIN32_FIND_DATA aFindData;
237 
238     // Finding all content in sPath
239 
240     HANDLE hFindContent = FindFirstFile( sPattern.c_str(), &aFindData );
241 
242     if ( hFindContent != INVALID_HANDLE_VALUE )
243     {
244         bool fNextFile = false;
245 
246         do
247         {
248             std::_tstring sFileName = aFindData.cFileName;
249             std::_tstring sCurrentDir = TEXT(".");
250             std::_tstring sParentDir = TEXT("..");
251 
252             mystr = "Current short file: " + sFileName;
253             // MessageBox(NULL, mystr.c_str(), "Current Content", MB_OK);
254 
255             if (( strcmp(sFileName.c_str(),sCurrentDir.c_str()) != 0 ) &&
256                 ( strcmp(sFileName.c_str(),sParentDir.c_str()) != 0 ))
257             {
258                 std::_tstring sCompleteFileName = sPath + TEXT("\\") + sFileName;
259 
260                 if ( aFindData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY )
261                 {
262                     bool fSuccess = RemoveCompleteDirectory(sCompleteFileName);
263                     if ( fSuccess )
264                     {
265                         mystr = "Successfully removed content of dir " + sCompleteFileName;
266                         // MessageBox(NULL, mystr.c_str(), "Removed Directory", MB_OK);
267                     }
268                     else
269                     {
270                         mystr = "An error occured during removing content of " + sCompleteFileName;
271                         // MessageBox(NULL, mystr.c_str(), "Error removing directory", MB_OK);
272                     }
273                 }
274                 else
275                 {
276                     bool fSuccess = DeleteFile( sCompleteFileName.c_str() );
277                     if ( fSuccess )
278                     {
279                         mystr = "Successfully removed file " + sCompleteFileName;
280                         // MessageBox(NULL, mystr.c_str(), "Removed File", MB_OK);
281                     }
282                     else
283                     {
284                         mystr = "An error occured during removal of file " + sCompleteFileName;
285                         // MessageBox(NULL, mystr.c_str(), "Error removing file", MB_OK);
286                     }
287                 }
288             }
289 
290             fNextFile = FindNextFile( hFindContent, &aFindData );
291 
292         } while ( fNextFile );
293 
294         FindClose( hFindContent );
295 
296         // empty directory can be removed now
297         // RemoveDirectory is only successful, if the last handle to the directory is closed
298         // -> first removing content -> closing handle -> remove empty directory
299 
300         bool fRemoveDirSuccess = RemoveDirectory(sPath.c_str());
301 
302         if ( fRemoveDirSuccess )
303         {
304             mystr = "Successfully removed dir " + sPath;
305             // MessageBox(NULL, mystr.c_str(), "Removed Directory", MB_OK);
306         }
307         else
308         {
309             mystr = "An error occured during removal of empty directory " + sPath;
310             // MessageBox(NULL, mystr.c_str(), "Error removing directory", MB_OK);
311             bDirectoryRemoved = false;
312         }
313     }
314 
315     return bDirectoryRemoved;
316 }
317 
318 extern "C" UINT __stdcall RegisterExtensions(MSIHANDLE handle)
319 {
320     // std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") );
321     std::_tstring sInstDir = GetMsiProperty( handle, TEXT("CustomActionData") );
322     std::_tstring sUnoPkgFile = sInstDir + TEXT("program\\unopkg.exe");
323     std::_tstring mystr;
324 
325     WIN32_FIND_DATA aFindFileData;
326     bool registrationError = false;
327 
328     // Find unopkg.exe
329     HANDLE hFindUnopkg = FindFirstFile( sUnoPkgFile.c_str(), &aFindFileData );
330 
331     if ( hFindUnopkg != INVALID_HANDLE_VALUE )
332     {
333         // unopkg.exe exists in program directory
334         std::_tstring sCommand = sUnoPkgFile + " sync";
335 
336         DWORD exitCode = 0;
337         bool fSuccess = ExecuteCommand( sCommand.c_str(), & exitCode);
338 
339 //          if ( fSuccess )
340 //          {
341 //              mystr = "Executed successfully!";
342 //              MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
343 //          }
344 //          else
345 //          {
346 //              mystr = "An error occured during execution!";
347 //              MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
348 //          }
349 
350         if ( ! fSuccess )
351         {
352             mystr = "ERROR: An error occured during registration of extensions!";
353             MessageBox(NULL, mystr.c_str(), "ERROR", MB_OK);
354             registrationError = true;
355         }
356 
357         FindClose( hFindUnopkg );
358     }
359     // else
360     // {
361     //     mystr = "Error: Did not find " + sUnoPkgFile;
362     //     MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
363     // }
364 
365     if ( registrationError )
366     {
367         return 1;
368     }
369     else
370     {
371         return ERROR_SUCCESS;
372     }
373 }
374 
375 
376 extern "C" UINT __stdcall RemoveExtensions(MSIHANDLE handle)
377 {
378     std::_tstring mystr;
379 
380     // Finding the product with the help of the propery FINDPRODUCT,
381     // that contains a Windows Registry key, that points to the install location.
382 
383     TCHAR szValue[8192];
384     DWORD nValueSize = sizeof(szValue);
385     HKEY  hKey;
386     std::_tstring sInstDir;
387 
388     std::_tstring sProductKey = GetMsiProperty( handle, TEXT("FINDPRODUCT") );
389     //MessageBox( NULL, sProductKey.c_str(), "Titel", MB_OK );
390 
391     if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER,  sProductKey.c_str(), &hKey ) )
392     {
393         if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
394         {
395             sInstDir = szValue;
396         }
397         RegCloseKey( hKey );
398     }
399     else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE,  sProductKey.c_str(), &hKey ) )
400     {
401         if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
402         {
403             sInstDir = szValue;
404         }
405         RegCloseKey( hKey );
406     }
407     else
408     {
409         return ERROR_SUCCESS;
410     }
411 
412     // Removing complete directory "Basis\presets\bundled"
413 
414     std::_tstring sCacheDir = sInstDir + TEXT("share\\prereg\\bundled");
415 
416     bool fSuccess = RemoveCompleteDirectory( sCacheDir );
417 
418 //     if ( fSuccess )
419 //     {
420 //         mystr = "Executed successfully!";
421 //          MessageBox(NULL, mystr.c_str(), "Main methode", MB_OK);
422 //     }
423 //     else
424 //     {
425 //         mystr = "An error occured during execution!";
426 //         MessageBox(NULL, mystr.c_str(), "Main methode", MB_OK);
427 //     }
428 
429     return ERROR_SUCCESS;
430 }
431