xref: /trunk/main/setup_native/source/win32/customactions/languagepacks/checkrunningofficelanguagepack.cxx (revision 989b13ef2270bbb43d1b5fb03162470a47d7f4cc)
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 #define _WIN32_WINDOWS 0x0410
23 
24 #ifdef _MSC_VER
25 #pragma warning(push, 1) /* disable warnings within system headers */
26 #endif
27 #define WIN32_LEAN_AND_MEAN
28 #include <windows.h>
29 #include <msiquery.h>
30 #ifdef _MSC_VER
31 #pragma warning(pop)
32 #endif
33 
34 #include <malloc.h>
35 #include <assert.h>
36 
37 #ifdef UNICODE
38 #define _UNICODE
39 #define _tstring    wstring
40 #else
41 #define _tstring    string
42 #endif
43 #include <tchar.h>
44 #include <string>
45 #include <queue>
46 #include <stdio.h>
47 
48 #include <systools/win32/uwinapi.h>
49 #include <../tools/seterror.hxx>
50 
51 #define WININIT_FILENAME    "wininit.ini"
52 #define RENAME_SECTION      "rename"
53 
54 #ifdef DEBUG
55 inline void OutputDebugStringFormat( LPCTSTR pFormat, ... )
56 {
57     _TCHAR  buffer[1024];
58     va_list args;
59 
60     va_start( args, pFormat );
61     _vsntprintf( buffer, elementsof(buffer), pFormat, args );
62     OutputDebugString( buffer );
63 }
64 #else
65 static inline void OutputDebugStringFormat( LPCTSTR, ... )
66 {
67 }
68 #endif
69 
70 static std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty )
71 {
72     std::_tstring   result;
73     TCHAR   szDummy[1] = TEXT("");
74     DWORD   nChars = 0;
75 
76     if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA )
77     {
78         DWORD nBytes = ++nChars * sizeof(TCHAR);
79         LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
80         ZeroMemory( buffer, nBytes );
81         MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
82         result = buffer;
83     }
84 
85     return  result;
86 }
87 
88 static inline bool IsSetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty)
89 {
90     std::_tstring value = GetMsiProperty(handle, sProperty);
91     return (value.length() > 0);
92 }
93 
94 static inline void UnsetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty)
95 {
96     MsiSetProperty(handle, sProperty.c_str(), NULL);
97 }
98 
99 static inline void SetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty)
100 {
101     MsiSetProperty(handle, sProperty.c_str(), TEXT("1"));
102 }
103 
104 static BOOL MoveFileEx9x( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, DWORD dwFlags )
105 {
106     BOOL    fSuccess = FALSE;   // assume failure
107 
108     // Windows 9x has a special mechanism to move files after reboot
109 
110     if ( dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT )
111     {
112         CHAR    szExistingFileNameA[MAX_PATH];
113         CHAR    szNewFileNameA[MAX_PATH] = "NUL";
114 
115         // Path names in WININIT.INI must be in short path name form
116 
117         if (
118             GetShortPathNameA( lpExistingFileNameA, szExistingFileNameA, MAX_PATH ) &&
119             (!lpNewFileNameA || GetShortPathNameA( lpNewFileNameA, szNewFileNameA, MAX_PATH ))
120             )
121         {
122             CHAR    szBuffer[32767];    // The buffer size must not exceed 32K
123             DWORD   dwBufLen = GetPrivateProfileSectionA( RENAME_SECTION, szBuffer, elementsof(szBuffer), WININIT_FILENAME );
124 
125             CHAR    szRename[MAX_PATH]; // This is enough for at most to times 67 characters
126             strcpy( szRename, szNewFileNameA );
127             strcat( szRename, "=" );
128             strcat( szRename, szExistingFileNameA );
129             size_t  lnRename = strlen(szRename);
130 
131             if ( dwBufLen + lnRename + 2 <= elementsof(szBuffer) )
132             {
133                 CopyMemory( &szBuffer[dwBufLen], szRename, lnRename );
134                 szBuffer[dwBufLen + lnRename ] = 0;
135                 szBuffer[dwBufLen + lnRename + 1 ] = 0;
136 
137                 fSuccess = WritePrivateProfileSectionA( RENAME_SECTION, szBuffer, WININIT_FILENAME );
138             }
139             else
140                 SetLastError( ERROR_BUFFER_OVERFLOW );
141         }
142     }
143     else
144     {
145 
146         fSuccess = MoveFileA( lpExistingFileNameA, lpNewFileNameA );
147 
148         if ( !fSuccess && GetLastError() != ERROR_ACCESS_DENIED &&
149             0 != (dwFlags & (MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) )
150         {
151             BOOL    bFailIfExist = 0 == (dwFlags & MOVEFILE_REPLACE_EXISTING);
152 
153             fSuccess = CopyFileA( lpExistingFileNameA, lpNewFileNameA, bFailIfExist );
154 
155             if ( fSuccess )
156                 fSuccess = DeleteFileA( lpExistingFileNameA );
157         }
158 
159     }
160 
161     return fSuccess;
162 }
163 
164 static BOOL MoveFileExImpl( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, DWORD dwFlags )
165 {
166     if ( 0 > ((LONG)GetVersion())) // High order bit indicates Win 9x
167         return MoveFileEx9x( lpExistingFileNameA, lpNewFileNameA, dwFlags );
168     else
169         return MoveFileExA( lpExistingFileNameA, lpNewFileNameA, dwFlags );
170 }
171 
172 extern "C" UINT __stdcall IsOfficeRunning( MSIHANDLE handle )
173 {
174     std::_tstring   sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") );
175 //  std::_tstring   sResourceDir = sInstDir + TEXT("Basis\\program\\resource\\");
176     std::_tstring   sResourceDir = sInstDir + TEXT("program\\resource\\");
177     std::_tstring   sPattern = sResourceDir + TEXT("vcl*.res");
178 
179     WIN32_FIND_DATA aFindFileData;
180     HANDLE  hFind = FindFirstFile( sPattern.c_str(), &aFindFileData );
181 
182     if ( IsValidHandle(hFind) )
183     {
184         BOOL    fSuccess = false;
185         bool    fRenameSucceeded;
186 
187         do
188         {
189             std::_tstring   sResourceFile = sResourceDir + aFindFileData.cFileName;
190             std::_tstring   sIntermediate = sResourceFile + TEXT(".tmp");
191 
192             fRenameSucceeded = MoveFileExImpl( sResourceFile.c_str(), sIntermediate.c_str(), MOVEFILE_REPLACE_EXISTING );
193             if ( fRenameSucceeded )
194             {
195                 MoveFileExImpl( sIntermediate.c_str(), sResourceFile.c_str(), 0 );
196                 fSuccess = FindNextFile( hFind, &aFindFileData );
197             }
198         } while ( fSuccess && fRenameSucceeded );
199 
200         if ( !fRenameSucceeded )
201         {
202             MsiSetProperty(handle, TEXT("OFFICERUNS"), TEXT("1"));
203             SetMsiErrorCode( MSI_ERROR_OFFICE_IS_RUNNING );
204         }
205 
206         FindClose( hFind );
207     }
208 
209     return ERROR_SUCCESS;
210 }
211 
212 /* vim: set noet sw=4 ts=4: */
213