blob: 4fe0daadbbea865ab5881e5de34265efdd36178f [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#undef UNICODE
#undef _UNICODE
#define _WIN32_WINDOWS 0x0410
#ifdef _MSC_VER
#pragma warning(push, 1) /* disable warnings within system headers */
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <msiquery.h>
#include <shellapi.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <malloc.h>
#include <assert.h>
#include <string.h>
#ifdef UNICODE
#define _UNICODE
#define _tstring wstring
#else
#define _tstring string
#endif
#include <tchar.h>
#include <string>
/** creates a temporary folder with a unique name.
The returned string is a file URL.
*/
// static std::_tstring createTempFolder()
// {
// BOOL bExist = FALSE;
// TCHAR szTempName[MAX_PATH];
// do
// {
// bExist = FALSE;
// // Get the temp path.
// TCHAR lpPathBuffer[MAX_PATH];
// DWORD dwRetVal = GetTempPath(MAX_PATH, lpPathBuffer);
// if (dwRetVal > MAX_PATH || (dwRetVal == 0))
// {
// //fprintf (stderr, "GetTempPath failed with error %d.\n", GetLastError());
// return TEXT("");
// }
// // Create a temporary file.
// UINT uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files
// "upg", // temp file name prefix
// 0, // create unique name
// szTempName); // buffer for name
// if (uRetVal == 0)
// {
// //fprintf (stderr, "GetTempFileName failed with error %d.\n", GetLastError());
// return TEXT("");
// }
// //Delete the file
// BOOL bDel = DeleteFile(szTempName);
// if (FALSE == bDel)
// {
// //fprintf(stderr, "Could not delete temp file. Error %d.\n", GetLastError());
// return TEXT("");
// }
// // Create the directory
// BOOL bDir = CreateDirectory(szTempName, NULL);
// if (FALSE == bDir)
// {
// DWORD error =GetLastError();
// if (ERROR_ALREADY_EXISTS == error)
// {
// bExist = TRUE;
// }
// else
// {
// //fprintf(stderr, "CreateDirectory failed with error %d.\n", error);
// return TEXT("");
// }
// }
// } while(bExist);
// std::_tstring cur(szTempName);
// //make a file URL from the path
// std::_tstring ret(TEXT("file:///"));
// for (std::_tstring::iterator i = cur.begin(); i != cur.end(); i++)
// {
// if (*i == '\\')
// ret.append(TEXT("/"));
// else
// ret.push_back(*i);
// }
// // MessageBox(NULL, ret.c_str(), "createTempFolder", MB_OK);
// return ret.c_str();
// }
/** deletes the temporary folder.
The argument must be a file URL.
*/
// static void deleteTempFolder(const std::_tstring& sTempFolder)
// {
// if (sTempFolder.size() == 0)
// return;
// //convert the file URL to a path
// const std::_tstring path(sTempFolder.substr(8));
// std::_tstring path2;
// // MessageBox(NULL, path.c_str(), "del1", MB_OK);
// for (std::_tstring::const_iterator i = path.begin(); i != path.end(); i++)
// {
// if (*i == '/')
// path2.append(TEXT("\\"));
// else
// path2.push_back(*i);
// }
// //We need a null terminated string with two nulls in the end
// //for the SHFILEOPSTRUCT
// const TCHAR * szTemp = path2.c_str();
// size_t size = path2.size();
// TCHAR * szTemp2 = new TCHAR[size + 2];
// ZeroMemory(szTemp2, (size + 2) * sizeof(TCHAR));
// memcpy(szTemp2, szTemp, size * sizeof(TCHAR));
// // MessageBox(NULL, szTemp2, "del3", MB_OK);
// SHFILEOPSTRUCT operation =
// {
// NULL,
// FO_DELETE,
// szTemp2,
// NULL,
// FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR,
// FALSE,
// NULL,
// NULL
// };
// SHFileOperation( &operation);
// delete [] szTemp2;
// }
static std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty )
{
std::_tstring result;
TCHAR szDummy[1] = TEXT("");
DWORD nChars = 0;
if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA )
{
DWORD nBytes = ++nChars * sizeof(TCHAR);
LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
ZeroMemory( buffer, nBytes );
MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
result = buffer;
}
return result;
}
/* creates a child process which is specified in lpCommand.
out_exitCode is the exit code of the child process
**/
static BOOL ExecuteCommand( LPCTSTR lpCommand, DWORD * out_exitCode)
{
BOOL fSuccess = FALSE;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
fSuccess = CreateProcess(
NULL,
(LPTSTR)lpCommand,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi
);
if ( fSuccess )
{
WaitForSingleObject( pi.hProcess, INFINITE );
if (!GetExitCodeProcess( pi.hProcess, out_exitCode))
fSuccess = FALSE;
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
return fSuccess;
}
static BOOL RemoveCompleteDirectory( std::_tstring sPath )
{
bool bDirectoryRemoved = true;
std::_tstring mystr;
std::_tstring sPattern = sPath + TEXT("\\") + TEXT("*.*");
WIN32_FIND_DATA aFindData;
// Finding all content in sPath
HANDLE hFindContent = FindFirstFile( sPattern.c_str(), &aFindData );
if ( hFindContent != INVALID_HANDLE_VALUE )
{
bool fNextFile = false;
do
{
std::_tstring sFileName = aFindData.cFileName;
std::_tstring sCurrentDir = TEXT(".");
std::_tstring sParentDir = TEXT("..");
mystr = "Current short file: " + sFileName;
// MessageBox(NULL, mystr.c_str(), "Current Content", MB_OK);
if (( strcmp(sFileName.c_str(),sCurrentDir.c_str()) != 0 ) &&
( strcmp(sFileName.c_str(),sParentDir.c_str()) != 0 ))
{
std::_tstring sCompleteFileName = sPath + TEXT("\\") + sFileName;
if ( aFindData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY )
{
bool fSuccess = RemoveCompleteDirectory(sCompleteFileName);
if ( fSuccess )
{
mystr = "Successfully removed content of dir " + sCompleteFileName;
// MessageBox(NULL, mystr.c_str(), "Removed Directory", MB_OK);
}
else
{
mystr = "An error occurred during removing content of " + sCompleteFileName;
// MessageBox(NULL, mystr.c_str(), "Error removing directory", MB_OK);
}
}
else
{
bool fSuccess = DeleteFile( sCompleteFileName.c_str() );
if ( fSuccess )
{
mystr = "Successfully removed file " + sCompleteFileName;
// MessageBox(NULL, mystr.c_str(), "Removed File", MB_OK);
}
else
{
mystr = "An error occurred during removal of file " + sCompleteFileName;
// MessageBox(NULL, mystr.c_str(), "Error removing file", MB_OK);
}
}
}
fNextFile = FindNextFile( hFindContent, &aFindData );
} while ( fNextFile );
FindClose( hFindContent );
// empty directory can be removed now
// RemoveDirectory is only successful, if the last handle to the directory is closed
// -> first removing content -> closing handle -> remove empty directory
bool fRemoveDirSuccess = RemoveDirectory(sPath.c_str());
if ( fRemoveDirSuccess )
{
mystr = "Successfully removed dir " + sPath;
// MessageBox(NULL, mystr.c_str(), "Removed Directory", MB_OK);
}
else
{
mystr = "An error occurred during removal of empty directory " + sPath;
// MessageBox(NULL, mystr.c_str(), "Error removing directory", MB_OK);
bDirectoryRemoved = false;
}
}
return bDirectoryRemoved;
}
extern "C" UINT __stdcall RegisterExtensions(MSIHANDLE handle)
{
// std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") );
std::_tstring sInstDir = GetMsiProperty( handle, TEXT("CustomActionData") );
std::_tstring sUnoPkgFile = sInstDir + TEXT("program\\unopkg.exe");
std::_tstring mystr;
WIN32_FIND_DATA aFindFileData;
bool registrationError = false;
// Find unopkg.exe
HANDLE hFindUnopkg = FindFirstFile( sUnoPkgFile.c_str(), &aFindFileData );
if ( hFindUnopkg != INVALID_HANDLE_VALUE )
{
// unopkg.exe exists in program directory
std::_tstring sCommand = sUnoPkgFile + " sync";
DWORD exitCode = 0;
bool fSuccess = ExecuteCommand( sCommand.c_str(), & exitCode);
// if ( fSuccess )
// {
// mystr = "Executed successfully!";
// MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
// }
// else
// {
// mystr = "An error occurred during execution!";
// MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
// }
if ( ! fSuccess )
{
mystr = "ERROR: An error occurred during registration of extensions!";
MessageBox(NULL, mystr.c_str(), "ERROR", MB_OK);
registrationError = true;
}
FindClose( hFindUnopkg );
}
// else
// {
// mystr = "Error: Did not find " + sUnoPkgFile;
// MessageBox(NULL, mystr.c_str(), "Command", MB_OK);
// }
if ( registrationError )
{
return 1;
}
else
{
return ERROR_SUCCESS;
}
}
extern "C" UINT __stdcall RemoveExtensions(MSIHANDLE handle)
{
std::_tstring mystr;
// Finding the product with the help of the propery FINDPRODUCT,
// that contains a Windows Registry key, that points to the install location.
TCHAR szValue[8192];
DWORD nValueSize = sizeof(szValue);
HKEY hKey;
std::_tstring sInstDir;
std::_tstring sProductKey = GetMsiProperty( handle, TEXT("FINDPRODUCT") );
//MessageBox( NULL, sProductKey.c_str(), "Titel", MB_OK );
if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, sProductKey.c_str(), &hKey ) )
{
if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
{
sInstDir = szValue;
}
RegCloseKey( hKey );
}
else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sProductKey.c_str(), &hKey ) )
{
if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
{
sInstDir = szValue;
}
RegCloseKey( hKey );
}
else
{
return ERROR_SUCCESS;
}
// Removing complete directory "Basis\presets\bundled"
std::_tstring sCacheDir = sInstDir + TEXT("share\\prereg\\bundled");
bool fSuccess = RemoveCompleteDirectory( sCacheDir );
// if ( fSuccess )
// {
// mystr = "Executed successfully!";
// MessageBox(NULL, mystr.c_str(), "Main methode", MB_OK);
// }
// else
// {
// mystr = "An error occurred during execution!";
// MessageBox(NULL, mystr.c_str(), "Main methode", MB_OK);
// }
return ERROR_SUCCESS;
}