1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: registerextensions.cxx,v $
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 ************************************************************************/
34 #define _WIN32_WINDOWS 0x0410
37 #pragma warning(push, 1) /* disable warnings within system headers */
38 #define WIN32_LEAN_AND_MEAN
53 #define _tstring wstring
55 #define _tstring string
60 /** creates a temporary folder with a unique name.
62 The returned string is a file URL.
64 static std::_tstring
createTempFolder()
67 TCHAR szTempName
[MAX_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());
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
86 //fprintf (stderr, "GetTempFileName failed with error %d.\n", GetLastError());
90 BOOL bDel
= DeleteFile(szTempName
);
93 //fprintf(stderr, "Could not delete temp file. Error %d.\n", GetLastError());
96 // Create the directory
97 BOOL bDir
= CreateDirectory(szTempName
, NULL
);
100 DWORD error
=GetLastError();
101 if (ERROR_ALREADY_EXISTS
== error
)
107 //fprintf(stderr, "CreateDirectory failed with error %d.\n", error);
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
++)
119 ret
.append(TEXT("/"));
123 // MessageBox(NULL, ret.c_str(), "createTempFolder", MB_OK);
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)
134 //convert the file URL to a path
135 const std::_tstring
path(sTempFolder
.substr(8));
137 // MessageBox(NULL, path.c_str(), "del1", MB_OK);
138 for (std::_tstring::const_iterator i
= path
.begin(); i
!= path
.end(); i
++)
141 path2
.append(TEXT("\\"));
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
=
161 FOF_SILENT
| FOF_NOCONFIRMATION
| FOF_NOERRORUI
| FOF_NOCONFIRMMKDIR
,
167 SHFileOperation( &operation
);
173 static std::_tstring
GetMsiProperty( MSIHANDLE handle
, const std::_tstring
& sProperty
)
175 std::_tstring result
;
176 TCHAR szDummy
[1] = TEXT("");
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
);
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
;
201 PROCESS_INFORMATION pi
;
203 ZeroMemory( &si
, sizeof(si
) );
206 fSuccess
= CreateProcess(
221 WaitForSingleObject( pi
.hProcess
, INFINITE
);
223 if (!GetExitCodeProcess( pi
.hProcess
, out_exitCode
))
226 CloseHandle( pi
.hProcess
);
227 CloseHandle( pi
.hThread
);
233 static BOOL
RemoveCompleteDirectory( std::_tstring sPath
)
235 bool bDirectoryRemoved
= true;
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
);
268 mystr
= "Successfully removed content of dir " + sCompleteFileName
;
269 // MessageBox(NULL, mystr.c_str(), "Removed Directory", MB_OK);
273 mystr
= "An error occured during removing content of " + sCompleteFileName
;
274 // MessageBox(NULL, mystr.c_str(), "Error removing directory", MB_OK);
279 bool fSuccess
= DeleteFile( sCompleteFileName
.c_str() );
282 mystr
= "Successfully removed file " + sCompleteFileName
;
283 // MessageBox(NULL, mystr.c_str(), "Removed File", MB_OK);
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);
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");
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);
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);
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
);
379 // mystr = "Executed successfully!";
380 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
384 // mystr = "An error occured during execution!";
385 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
388 fNextFile
= FindNextFile( hFindOxt
, &aFindFileData
);
390 } while ( fNextFile
);
392 FindClose( hFindOxt
);
397 // mystr = "Error: Did not find " + sUnoPkgFile;
398 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
401 return ERROR_SUCCESS
;
404 extern "C" UINT __stdcall
DeregisterExtensions(MSIHANDLE handle
)
408 // Finding the product with the help of the propery FINDPRODUCT,
409 // that contains a Windows Registry key, that points to the install location.
412 DWORD nValueSize
= sizeof(szValue
);
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
) )
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
) )
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
;
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 " + "\""
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);
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
);
497 mystr
= "Executed successfully!";
498 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
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
);
515 // mystr = "Not found: " + sUnoPkgFile;
516 // MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
519 return ERROR_SUCCESS
;
522 extern "C" UINT __stdcall
RemoveExtensions(MSIHANDLE handle
)
526 // Finding the product with the help of the propery FINDPRODUCT,
527 // that contains a Windows Registry key, that points to the install location.
530 DWORD nValueSize
= sizeof(szValue
);
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
) )
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
) )
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
);
566 mystr
= "Executed successfully!";
567 // MessageBox(NULL, mystr.c_str(), "Main methode", MB_OK);
571 mystr
= "An error occured during execution!";
572 // MessageBox(NULL, mystr.c_str(), "Main methode", MB_OK);
575 return ERROR_SUCCESS
;