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: checkrunningoffice.cxx,v $
10 * $Revision: 1.1.4.2 $
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 #define _WIN32_WINDOWS 0x0410
34 #pragma warning(push, 1) /* disable warnings within system headers */
36 #define WIN32_LEAN_AND_MEAN
48 #define _tstring wstring
50 #define _tstring string
57 #include <systools/win32/uwinapi.h>
58 #include <../tools/seterror.hxx>
60 #define WININIT_FILENAME "wininit.ini"
61 #define RENAME_SECTION "rename"
64 inline void OutputDebugStringFormat( LPCTSTR pFormat
, ... )
69 va_start( args
, pFormat
);
70 _vsntprintf( buffer
, elementsof(buffer
), pFormat
, args
);
71 OutputDebugString( buffer
);
74 static inline void OutputDebugStringFormat( LPCTSTR
, ... )
79 static std::_tstring
GetMsiProperty( MSIHANDLE handle
, const std::_tstring
& sProperty
)
82 TCHAR szDummy
[1] = TEXT("");
85 if ( MsiGetProperty( handle
, sProperty
.c_str(), szDummy
, &nChars
) == ERROR_MORE_DATA
)
87 DWORD nBytes
= ++nChars
* sizeof(TCHAR
);
88 LPTSTR buffer
= reinterpret_cast<LPTSTR
>(_alloca(nBytes
));
89 ZeroMemory( buffer
, nBytes
);
90 MsiGetProperty(handle
, sProperty
.c_str(), buffer
, &nChars
);
97 static inline bool IsSetMsiProperty(MSIHANDLE handle
, const std::_tstring
& sProperty
)
99 std::_tstring value
= GetMsiProperty(handle
, sProperty
);
100 return (value
.length() > 0);
103 static inline void UnsetMsiProperty(MSIHANDLE handle
, const std::_tstring
& sProperty
)
105 MsiSetProperty(handle
, sProperty
.c_str(), NULL
);
108 static inline void SetMsiProperty(MSIHANDLE handle
, const std::_tstring
& sProperty
)
110 MsiSetProperty(handle
, sProperty
.c_str(), TEXT("1"));
113 static BOOL
MoveFileEx9x( LPCSTR lpExistingFileNameA
, LPCSTR lpNewFileNameA
, DWORD dwFlags
)
115 BOOL fSuccess
= FALSE
; // assume failure
117 // Windows 9x has a special mechanism to move files after reboot
119 if ( dwFlags
& MOVEFILE_DELAY_UNTIL_REBOOT
)
121 CHAR szExistingFileNameA
[MAX_PATH
];
122 CHAR szNewFileNameA
[MAX_PATH
] = "NUL";
124 // Path names in WININIT.INI must be in short path name form
127 GetShortPathNameA( lpExistingFileNameA
, szExistingFileNameA
, MAX_PATH
) &&
128 (!lpNewFileNameA
|| GetShortPathNameA( lpNewFileNameA
, szNewFileNameA
, MAX_PATH
))
131 CHAR szBuffer
[32767]; // The buffer size must not exceed 32K
132 DWORD dwBufLen
= GetPrivateProfileSectionA( RENAME_SECTION
, szBuffer
, elementsof(szBuffer
), WININIT_FILENAME
);
134 CHAR szRename
[MAX_PATH
]; // This is enough for at most to times 67 chracters
135 strcpy( szRename
, szNewFileNameA
);
136 strcat( szRename
, "=" );
137 strcat( szRename
, szExistingFileNameA
);
138 size_t lnRename
= strlen(szRename
);
140 if ( dwBufLen
+ lnRename
+ 2 <= elementsof(szBuffer
) )
142 CopyMemory( &szBuffer
[dwBufLen
], szRename
, lnRename
);
143 szBuffer
[dwBufLen
+ lnRename
] = 0;
144 szBuffer
[dwBufLen
+ lnRename
+ 1 ] = 0;
146 fSuccess
= WritePrivateProfileSectionA( RENAME_SECTION
, szBuffer
, WININIT_FILENAME
);
149 SetLastError( ERROR_BUFFER_OVERFLOW
);
155 fSuccess
= MoveFileA( lpExistingFileNameA
, lpNewFileNameA
);
157 if ( !fSuccess
&& GetLastError() != ERROR_ACCESS_DENIED
&&
158 0 != (dwFlags
& (MOVEFILE_COPY_ALLOWED
| MOVEFILE_REPLACE_EXISTING
)) )
160 BOOL bFailIfExist
= 0 == (dwFlags
& MOVEFILE_REPLACE_EXISTING
);
162 fSuccess
= CopyFileA( lpExistingFileNameA
, lpNewFileNameA
, bFailIfExist
);
165 fSuccess
= DeleteFileA( lpExistingFileNameA
);
173 static BOOL
MoveFileExImpl( LPCSTR lpExistingFileNameA
, LPCSTR lpNewFileNameA
, DWORD dwFlags
)
175 if ( 0 > ((LONG
)GetVersion())) // High order bit indicates Win 9x
176 return MoveFileEx9x( lpExistingFileNameA
, lpNewFileNameA
, dwFlags
);
178 return MoveFileExA( lpExistingFileNameA
, lpNewFileNameA
, dwFlags
);
181 extern "C" UINT __stdcall
IsOfficeRunning( MSIHANDLE handle
)
183 OSVERSIONINFO osverinfo
;
184 osverinfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
185 GetVersionEx( &osverinfo
);
187 // renaming the vcl resource doesn't work reliable with OS >= Windows Vista
188 if (osverinfo
.dwMajorVersion
< 6 )
190 std::_tstring sInstDir
= GetMsiProperty( handle
, TEXT("BASISINSTALLLOCATION") );
191 // Property empty -> no office installed
192 if ( sInstDir
.length() == 0 )
193 return ERROR_SUCCESS
;
195 std::_tstring sResourceDir
= sInstDir
+ TEXT("program\\resource\\");
196 std::_tstring sPattern
= sResourceDir
+ TEXT("vcl*.res");
198 // std::_tstring mystr;
199 // mystr = "IsOfficeRunning start. Checking file in dir: " + sResourceDir;
200 // MessageBox( NULL, mystr.c_str(), "IsOfficeRunning", MB_OK );
202 WIN32_FIND_DATA aFindFileData
;
203 HANDLE hFind
= FindFirstFile( sPattern
.c_str(), &aFindFileData
);
205 if ( IsValidHandle(hFind
) )
207 BOOL fSuccess
= false;
208 bool fRenameSucceeded
;
212 std::_tstring sResourceFile
= sResourceDir
+ aFindFileData
.cFileName
;
213 std::_tstring sIntermediate
= sResourceFile
+ TEXT(".tmp");
215 fRenameSucceeded
= MoveFileExImpl( sResourceFile
.c_str(), sIntermediate
.c_str(), MOVEFILE_REPLACE_EXISTING
);
216 if ( fRenameSucceeded
)
218 MoveFileExImpl( sIntermediate
.c_str(), sResourceFile
.c_str(), 0 );
219 fSuccess
= FindNextFile( hFind
, &aFindFileData
);
221 } while ( fSuccess
&& fRenameSucceeded
);
223 if ( !fRenameSucceeded
)
225 MsiSetProperty(handle
, TEXT("OFFICERUNS"), TEXT("1"));
226 SetMsiErrorCode( MSI_ERROR_OFFICE_IS_RUNNING
);
228 // mystr = "Office is running";
229 // MessageBox( NULL, mystr.c_str(), "IsOfficeRunning", MB_OK );
234 // mystr = "IsOfficeRunning end";
235 // MessageBox( NULL, mystr.c_str(), "IsOfficeRunning", MB_OK );
239 std::_tstring sOfficeInstallPath
= GetMsiProperty(handle
, TEXT("OFFICEINSTALLLOCATION"));
240 // Property empty -> no office installed
241 if ( sOfficeInstallPath
.length() == 0 )
242 return ERROR_SUCCESS
;
244 std::_tstring sRenameSrc
= sOfficeInstallPath
+ TEXT("program");
245 std::_tstring sRenameDst
= sOfficeInstallPath
+ TEXT("program_test");
247 bool bSuccess
= MoveFile( sRenameSrc
.c_str(), sRenameDst
.c_str() );
251 MoveFile( sRenameDst
.c_str(), sRenameSrc
.c_str() );
255 DWORD dwError
= GetLastError();
257 // When there is no program folder, there could be no running office
258 if ( dwError
== ERROR_FILE_NOT_FOUND
)
259 return ERROR_SUCCESS
;
260 // The destination folder should never exist, don't know what to do here
261 if ( dwError
== ERROR_ALREADY_EXISTS
)
262 return ERROR_SUCCESS
;
265 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
266 FORMAT_MESSAGE_FROM_SYSTEM
|
267 FORMAT_MESSAGE_IGNORE_INSERTS
,
270 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
275 OutputDebugStringFormat( TEXT("Error Code %d: %s"), dwError
, lpMsgBuf
);
276 LocalFree( lpMsgBuf
);
279 OutputDebugStringFormat( TEXT("Error Code %d: Unknown"), dwError
);
281 MsiSetProperty( handle
, TEXT("OFFICERUNS"), TEXT("1") );
282 SetMsiErrorCode( MSI_ERROR_OFFICE_IS_RUNNING
);
286 return ERROR_SUCCESS
;