Update ooo320-m1
[ooovba.git] / setup_native / source / win32 / customactions / shellextensions / registerextensions.cxx
blobd13f56e8cdc25bb2da83e98c9c7da1307e04d61d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: registerextensions.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #undef UNICODE
32 #undef _UNICODE
34 #define _WIN32_WINDOWS 0x0410
36 #ifdef _MSC_VER
37 #pragma warning(push, 1) /* disable warnings within system headers */
38 #define WIN32_LEAN_AND_MEAN
39 #endif
40 #include <windows.h>
41 #include <msiquery.h>
42 #include <shellapi.h>
43 #ifdef _MSC_VER
44 #pragma warning(pop)
45 #endif
47 #include <malloc.h>
48 #include <assert.h>
49 #include <string.h>
51 #ifdef UNICODE
52 #define _UNICODE
53 #define _tstring wstring
54 #else
55 #define _tstring string
56 #endif
57 #include <tchar.h>
58 #include <string>
60 /** creates a temporary folder with a unique name.
62 The returned string is a file URL.
64 static std::_tstring createTempFolder()
66 BOOL bExist = FALSE;
67 TCHAR szTempName[MAX_PATH];
70 bExist = FALSE;
71 // Get the temp path.
72 TCHAR lpPathBuffer[MAX_PATH];
73 DWORD dwRetVal = GetTempPath(MAX_PATH, lpPathBuffer);
74 if (dwRetVal > MAX_PATH || (dwRetVal == 0))
76 //fprintf (stderr, "GetTempPath failed with error %d.\n", GetLastError());
77 return TEXT("");
79 // Create a temporary file.
80 UINT uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files
81 "upg", // temp file name prefix
82 0, // create unique name
83 szTempName); // buffer for name
84 if (uRetVal == 0)
86 //fprintf (stderr, "GetTempFileName failed with error %d.\n", GetLastError());
87 return TEXT("");
89 //Delete the file
90 BOOL bDel = DeleteFile(szTempName);
91 if (FALSE == bDel)
93 //fprintf(stderr, "Could not delete temp file. Error %d.\n", GetLastError());
94 return TEXT("");
96 // Create the directory
97 BOOL bDir = CreateDirectory(szTempName, NULL);
98 if (FALSE == bDir)
100 DWORD error =GetLastError();
101 if (ERROR_ALREADY_EXISTS == error)
103 bExist = TRUE;
105 else
107 //fprintf(stderr, "CreateDirectory failed with error %d.\n", error);
108 return TEXT("");
111 } while(bExist);
113 std::_tstring cur(szTempName);
114 //make a file URL from the path
115 std::_tstring ret(TEXT("file:///"));
116 for (std::_tstring::iterator i = cur.begin(); i != cur.end(); i++)
118 if (*i == '\\')
119 ret.append(TEXT("/"));
120 else
121 ret.push_back(*i);
123 // MessageBox(NULL, ret.c_str(), "createTempFolder", MB_OK);
124 return ret.c_str();
127 /** deletes the temporary folder.
128 The argument must be a file URL.
130 static void deleteTempFolder(const std::_tstring& sTempFolder)
132 if (sTempFolder.size() == 0)
133 return;
134 //convert the file URL to a path
135 const std::_tstring path(sTempFolder.substr(8));
136 std::_tstring path2;
137 // MessageBox(NULL, path.c_str(), "del1", MB_OK);
138 for (std::_tstring::const_iterator i = path.begin(); i != path.end(); i++)
140 if (*i == '/')
141 path2.append(TEXT("\\"));
142 else
143 path2.push_back(*i);
146 //We need a null terminated string with two nulls in the end
147 //for the SHFILEOPSTRUCT
148 const TCHAR * szTemp = path2.c_str();
149 size_t size = path2.size();
150 TCHAR * szTemp2 = new TCHAR[size + 2];
151 ZeroMemory(szTemp2, (size + 2) * sizeof(TCHAR));
152 memcpy(szTemp2, szTemp, size * sizeof(TCHAR));
154 // MessageBox(NULL, szTemp2, "del3", MB_OK);
155 SHFILEOPSTRUCT operation =
157 NULL,
158 FO_DELETE,
159 szTemp2,
160 NULL,
161 FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR,
162 FALSE,
163 NULL,
164 NULL
167 SHFileOperation( &operation);
168 delete [] szTemp2;
173 static std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty )
175 std::_tstring result;
176 TCHAR szDummy[1] = TEXT("");
177 DWORD nChars = 0;
179 if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA )
181 DWORD nBytes = ++nChars * sizeof(TCHAR);
182 LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
183 ZeroMemory( buffer, nBytes );
184 MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
185 result = buffer;
188 return result;
191 /* creates a child process which is specified in lpCommand.
193 out_exitCode is the exit code of the child process
197 static BOOL ExecuteCommand( LPCTSTR lpCommand, DWORD * out_exitCode)
199 BOOL fSuccess = FALSE;
200 STARTUPINFO si;
201 PROCESS_INFORMATION pi;
203 ZeroMemory( &si, sizeof(si) );
204 si.cb = sizeof(si);
206 fSuccess = CreateProcess(
207 NULL,
208 (LPTSTR)lpCommand,
209 NULL,
210 NULL,
211 FALSE,
213 NULL,
214 NULL,
215 &si,
219 if ( fSuccess )
221 WaitForSingleObject( pi.hProcess, INFINITE );
223 if (!GetExitCodeProcess( pi.hProcess, out_exitCode))
224 fSuccess = FALSE;
226 CloseHandle( pi.hProcess );
227 CloseHandle( pi.hThread );
230 return fSuccess;
233 static BOOL RemoveCompleteDirectory( std::_tstring sPath )
235 bool bDirectoryRemoved = true;
237 std::_tstring mystr;
238 std::_tstring sPattern = sPath + TEXT("\\") + TEXT("*.*");
239 WIN32_FIND_DATA aFindData;
241 // Finding all content in sPath
243 HANDLE hFindContent = FindFirstFile( sPattern.c_str(), &aFindData );
245 if ( hFindContent != INVALID_HANDLE_VALUE )
247 bool fNextFile = false;
251 std::_tstring sFileName = aFindData.cFileName;
252 std::_tstring sCurrentDir = TEXT(".");
253 std::_tstring sParentDir = TEXT("..");
255 mystr = "Current short file: " + sFileName;
256 // MessageBox(NULL, mystr.c_str(), "Current Content", MB_OK);
258 if (( strcmp(sFileName.c_str(),sCurrentDir.c_str()) != 0 ) &&
259 ( strcmp(sFileName.c_str(),sParentDir.c_str()) != 0 ))
261 std::_tstring sCompleteFileName = sPath + TEXT("\\") + sFileName;
263 if ( aFindData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY )
265 bool fSuccess = RemoveCompleteDirectory(sCompleteFileName);
266 if ( fSuccess )
268 mystr = "Successfully removed content of dir " + sCompleteFileName;
269 // MessageBox(NULL, mystr.c_str(), "Removed Directory", MB_OK);
271 else
273 mystr = "An error occured during removing content of " + sCompleteFileName;
274 // MessageBox(NULL, mystr.c_str(), "Error removing directory", MB_OK);
277 else
279 bool fSuccess = DeleteFile( sCompleteFileName.c_str() );
280 if ( fSuccess )
282 mystr = "Successfully removed file " + sCompleteFileName;
283 // MessageBox(NULL, mystr.c_str(), "Removed File", MB_OK);
285 else
287 mystr = "An error occured during removal of file " + sCompleteFileName;
288 // MessageBox(NULL, mystr.c_str(), "Error removing file", MB_OK);
293 fNextFile = FindNextFile( hFindContent, &aFindData );
295 } while ( fNextFile );
297 FindClose( hFindContent );
299 // empty directory can be removed now
300 // RemoveDirectory is only successful, if the last handle to the directory is closed
301 // -> first removing content -> closing handle -> remove empty directory
303 bool fRemoveDirSuccess = RemoveDirectory(sPath.c_str());
305 if ( fRemoveDirSuccess )
307 mystr = "Successfully removed dir " + sPath;
308 // MessageBox(NULL, mystr.c_str(), "Removed Directory", MB_OK);
310 else
312 mystr = "An error occured during removal of empty directory " + sPath;
313 // MessageBox(NULL, mystr.c_str(), "Error removing directory", MB_OK);
314 bDirectoryRemoved = false;
318 return bDirectoryRemoved;
321 extern "C" UINT __stdcall RegisterExtensions(MSIHANDLE handle)
323 std::_tstring sInstDir = GetMsiProperty( handle, TEXT("OFFICEINSTALLLOCATION") );
324 std::_tstring sUnoPkgFile = sInstDir + TEXT("program\\unopkg.exe");
325 std::_tstring sShareInstallDir = sInstDir + TEXT("share\\extension\\install\\");
326 std::_tstring sPattern = sShareInstallDir + TEXT("*.oxt");
327 std::_tstring mystr;
329 WIN32_FIND_DATA aFindFileData;
331 mystr = "unopkg file: " + sUnoPkgFile;
332 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
334 mystr = "oxt file directory: " + sShareInstallDir;
335 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
337 // Find unopkg.exe
339 HANDLE hFindUnopkg = FindFirstFile( sUnoPkgFile.c_str(), &aFindFileData );
341 if ( hFindUnopkg != INVALID_HANDLE_VALUE )
343 // unopkg.exe exists in program directory
345 // Finding all oxt files in sShareInstallDir
347 HANDLE hFindOxt = FindFirstFile( sPattern.c_str(), &aFindFileData );
349 if ( hFindOxt != INVALID_HANDLE_VALUE )
351 bool fNextFile = false;
355 const std::_tstring sTempFolder(createTempFolder());
356 std::_tstring sOxtFile = sShareInstallDir + aFindFileData.cFileName;
357 std::_tstring sCommandPart1 = sUnoPkgFile + " add --shared --bundled " + "\"" + sOxtFile + "\"";
358 std::_tstring sCommand = sCommandPart1
359 + TEXT(" -env:UNO_JAVA_JFW_INSTALL_DATA=$OOO_BASE_DIR/share/config/javasettingsunopkginstall.xml")
360 + TEXT(" -env:UserInstallation=") + sTempFolder;
361 mystr = "Command: " + sCommand;
362 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
364 DWORD exitCode = 0;
365 bool fSuccess = ExecuteCommand( sCommand.c_str(), & exitCode);
366 // unopkg in OOo 2.2.1 and early had a bug that it failed when receiving
367 // a bootstrap parameter (-env:...) then it exited with a value != 0.
368 if (fSuccess && exitCode != 0)
370 std::_tstring sCommand = sCommandPart1;
371 mystr = "Command: " + sCommand;
372 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
373 fSuccess = ExecuteCommand( sCommand.c_str(), & exitCode);
375 deleteTempFolder(sTempFolder);
377 // if ( fSuccess )
378 // {
379 // mystr = "Executed successfully!";
380 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
381 // }
382 // else
383 // {
384 // mystr = "An error occured during execution!";
385 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
386 // }
388 fNextFile = FindNextFile( hFindOxt, &aFindFileData );
390 } while ( fNextFile );
392 FindClose( hFindOxt );
395 // else
396 // {
397 // mystr = "Error: Did not find " + sUnoPkgFile;
398 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
399 // }
401 return ERROR_SUCCESS;
404 extern "C" UINT __stdcall DeregisterExtensions(MSIHANDLE handle)
406 std::_tstring mystr;
408 // Finding the product with the help of the propery FINDPRODUCT,
409 // that contains a Windows Registry key, that points to the install location.
411 TCHAR szValue[8192];
412 DWORD nValueSize = sizeof(szValue);
413 HKEY hKey;
414 std::_tstring sInstDir;
416 std::_tstring sProductKey = GetMsiProperty( handle, TEXT("FINDPRODUCT") );
417 // MessageBox( NULL, sProductKey.c_str(), "Titel", MB_OK );
419 if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, sProductKey.c_str(), &hKey ) )
421 if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("OFFICEINSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
423 sInstDir = szValue;
425 RegCloseKey( hKey );
427 else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sProductKey.c_str(), &hKey ) )
429 if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("OFFICEINSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
431 sInstDir = szValue;
433 RegCloseKey( hKey );
435 else
437 return ERROR_SUCCESS;
440 // MessageBox( NULL, sInstDir.c_str(), "install location", MB_OK );
442 // Searching for the unopkg.exe
444 std::_tstring sUnoPkgFile = sInstDir + TEXT("program\\unopkg.exe");
445 std::_tstring sShareInstallDir = sInstDir + TEXT("share\\extension\\install\\");
446 std::_tstring sPattern = sShareInstallDir + TEXT("*.oxt");
448 WIN32_FIND_DATA aFindFileData;
450 // Find unopkg.exe
452 HANDLE hFindUnopkg = FindFirstFile( sUnoPkgFile.c_str(), &aFindFileData );
454 if ( hFindUnopkg != INVALID_HANDLE_VALUE )
456 // unopkg.exe exists in program directory
458 // Finding all oxt files in sShareInstallDir
460 HANDLE hFindOxt = FindFirstFile( sPattern.c_str(), &aFindFileData );
462 if ( hFindOxt != INVALID_HANDLE_VALUE )
464 bool fNextFile = false;
468 const std::_tstring sTempFolder(createTempFolder());
469 // When removing extensions, only the oxt file name is required, without path
470 // Therefore no quoting is required
471 // std::_tstring sOxtFile = sShareInstallDir + aFindFileData.cFileName;
472 std::_tstring sOxtFile = aFindFileData.cFileName;
473 std::_tstring sCommandPart1 = sUnoPkgFile + " remove --shared --bundled " + "\""
474 + sOxtFile + "\"";
475 std::_tstring sCommand = sCommandPart1
476 + TEXT(" -env:UNO_JAVA_JFW_INSTALL_DATA=$OOO_BASE_DIR/share/config/javasettingsunopkginstall.xml")
477 + TEXT(" -env:UserInstallation=") + sTempFolder;
479 mystr = "Command: " + sCommand;
480 //MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
481 DWORD exitCode = 0;
482 bool fSuccess = ExecuteCommand( sCommand.c_str(), & exitCode);
483 // unopkg in OOo 2.2.1 and early had a bug that it failed when receiving
484 // a bootstrap parameter (-env:...) then it exited with a value != 0.
485 if (fSuccess && exitCode != 0)
487 std::_tstring sCommand = sCommandPart1;
488 mystr = "Command: " + sCommand;
489 //MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
490 fSuccess = ExecuteCommand( sCommand.c_str(), & exitCode);
493 deleteTempFolder(sTempFolder);
495 if ( fSuccess )
497 mystr = "Executed successfully!";
498 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
500 else
502 mystr = "An error occured during execution!";
503 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
506 fNextFile = FindNextFile( hFindOxt, &aFindFileData );
508 } while ( fNextFile );
510 FindClose( hFindOxt );
513 // else
514 // {
515 // mystr = "Not found: " + sUnoPkgFile;
516 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
517 // }
519 return ERROR_SUCCESS;
522 extern "C" UINT __stdcall RemoveExtensions(MSIHANDLE handle)
524 std::_tstring mystr;
526 // Finding the product with the help of the propery FINDPRODUCT,
527 // that contains a Windows Registry key, that points to the install location.
529 TCHAR szValue[8192];
530 DWORD nValueSize = sizeof(szValue);
531 HKEY hKey;
532 std::_tstring sInstDir;
534 std::_tstring sProductKey = GetMsiProperty( handle, TEXT("FINDPRODUCT") );
535 // MessageBox( NULL, sProductKey.c_str(), "Titel", MB_OK );
537 if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, sProductKey.c_str(), &hKey ) )
539 if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("OFFICEINSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
541 sInstDir = szValue;
543 RegCloseKey( hKey );
545 else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sProductKey.c_str(), &hKey ) )
547 if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("OFFICEINSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
549 sInstDir = szValue;
551 RegCloseKey( hKey );
553 else
555 return ERROR_SUCCESS;
558 // Removing complete directory "share\uno_packages\cache"
560 std::_tstring sCacheDir = sInstDir + TEXT("share\\uno_packages\\cache");
562 bool fSuccess = RemoveCompleteDirectory( sCacheDir );
564 if ( fSuccess )
566 mystr = "Executed successfully!";
567 // MessageBox(NULL, mystr.c_str(), "Main methode", MB_OK);
569 else
571 mystr = "An error occured during execution!";
572 // MessageBox(NULL, mystr.c_str(), "Main methode", MB_OK);
575 return ERROR_SUCCESS;