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