132b1fd08SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
332b1fd08SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
432b1fd08SAndrew Rist * or more contributor license agreements. See the NOTICE file
532b1fd08SAndrew Rist * distributed with this work for additional information
632b1fd08SAndrew Rist * regarding copyright ownership. The ASF licenses this file
732b1fd08SAndrew Rist * to you under the Apache License, Version 2.0 (the
832b1fd08SAndrew Rist * "License"); you may not use this file except in compliance
932b1fd08SAndrew Rist * with the License. You may obtain a copy of the License at
1032b1fd08SAndrew Rist *
1132b1fd08SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
1232b1fd08SAndrew Rist *
1332b1fd08SAndrew Rist * Unless required by applicable law or agreed to in writing,
1432b1fd08SAndrew Rist * software distributed under the License is distributed on an
1532b1fd08SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1632b1fd08SAndrew Rist * KIND, either express or implied. See the License for the
1732b1fd08SAndrew Rist * specific language governing permissions and limitations
1832b1fd08SAndrew Rist * under the License.
1932b1fd08SAndrew Rist *
2032b1fd08SAndrew Rist *************************************************************/
2132b1fd08SAndrew Rist
2232b1fd08SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir #define _WIN32_WINDOWS 0x0410
25cdf0e10cSrcweir
26cdf0e10cSrcweir #ifdef _MSC_VER
27cdf0e10cSrcweir #pragma warning(push, 1) /* disable warnings within system headers */
28cdf0e10cSrcweir #endif
29cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN
30cdf0e10cSrcweir #include <windows.h>
31cdf0e10cSrcweir #include <msiquery.h>
32cdf0e10cSrcweir #ifdef _MSC_VER
33cdf0e10cSrcweir #pragma warning(pop)
34cdf0e10cSrcweir #endif
35cdf0e10cSrcweir
36cdf0e10cSrcweir #include <malloc.h>
37cdf0e10cSrcweir #include <assert.h>
38cdf0e10cSrcweir
39cdf0e10cSrcweir #ifdef UNICODE
40cdf0e10cSrcweir #define _UNICODE
41cdf0e10cSrcweir #define _tstring wstring
42cdf0e10cSrcweir #else
43cdf0e10cSrcweir #define _tstring string
44cdf0e10cSrcweir #endif
45cdf0e10cSrcweir #include <tchar.h>
46cdf0e10cSrcweir #include <string>
47cdf0e10cSrcweir #include <queue>
48cdf0e10cSrcweir #include <stdio.h>
49cdf0e10cSrcweir
50cdf0e10cSrcweir #include <systools/win32/uwinapi.h>
51cdf0e10cSrcweir #include <../tools/seterror.hxx>
52cdf0e10cSrcweir
53cdf0e10cSrcweir #define WININIT_FILENAME "wininit.ini"
54cdf0e10cSrcweir #define RENAME_SECTION "rename"
55cdf0e10cSrcweir
56cdf0e10cSrcweir #ifdef DEBUG
OutputDebugStringFormat(LPCTSTR pFormat,...)57cdf0e10cSrcweir inline void OutputDebugStringFormat( LPCTSTR pFormat, ... )
58cdf0e10cSrcweir {
59cdf0e10cSrcweir _TCHAR buffer[1024];
60cdf0e10cSrcweir va_list args;
61cdf0e10cSrcweir
62cdf0e10cSrcweir va_start( args, pFormat );
63cdf0e10cSrcweir _vsntprintf( buffer, elementsof(buffer), pFormat, args );
64cdf0e10cSrcweir OutputDebugString( buffer );
65cdf0e10cSrcweir }
66cdf0e10cSrcweir #else
OutputDebugStringFormat(LPCTSTR,...)67cdf0e10cSrcweir static inline void OutputDebugStringFormat( LPCTSTR, ... )
68cdf0e10cSrcweir {
69cdf0e10cSrcweir }
70cdf0e10cSrcweir #endif
71cdf0e10cSrcweir
GetMsiProperty(MSIHANDLE handle,const std::_tstring & sProperty)72cdf0e10cSrcweir static std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty )
73cdf0e10cSrcweir {
74cdf0e10cSrcweir std::_tstring result;
75cdf0e10cSrcweir TCHAR szDummy[1] = TEXT("");
76cdf0e10cSrcweir DWORD nChars = 0;
77cdf0e10cSrcweir
78cdf0e10cSrcweir if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA )
79cdf0e10cSrcweir {
80cdf0e10cSrcweir DWORD nBytes = ++nChars * sizeof(TCHAR);
81cdf0e10cSrcweir LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
82cdf0e10cSrcweir ZeroMemory( buffer, nBytes );
83cdf0e10cSrcweir MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
84cdf0e10cSrcweir result = buffer;
85cdf0e10cSrcweir }
86cdf0e10cSrcweir
87cdf0e10cSrcweir return result;
88cdf0e10cSrcweir }
89cdf0e10cSrcweir
90cdf0e10cSrcweir // The provided GUID must be without surounding '{}'
GetGuidPart(const std::_tstring & guid,int index)91cdf0e10cSrcweir static std::_tstring GetGuidPart(const std::_tstring& guid, int index)
92cdf0e10cSrcweir {
93cdf0e10cSrcweir assert((guid.length() == 36) && "No GUID or wrong format!");
94cdf0e10cSrcweir assert(((index > -1) && (index < 5)) && "Out of range!");
95cdf0e10cSrcweir
96cdf0e10cSrcweir if (index == 0) return std::_tstring(guid.c_str(), 8);
97cdf0e10cSrcweir if (index == 1) return std::_tstring(guid.c_str() + 9, 4);
98cdf0e10cSrcweir if (index == 2) return std::_tstring(guid.c_str() + 14, 4);
99cdf0e10cSrcweir if (index == 3) return std::_tstring(guid.c_str() + 19, 4);
100cdf0e10cSrcweir if (index == 4) return std::_tstring(guid.c_str() + 24, 12);
101cdf0e10cSrcweir
102cdf0e10cSrcweir return std::_tstring();
103cdf0e10cSrcweir }
104cdf0e10cSrcweir
Swap(char * p1,char * p2)105cdf0e10cSrcweir static void Swap(char* p1, char* p2)
106cdf0e10cSrcweir {
107cdf0e10cSrcweir char tmp = *p1;
108cdf0e10cSrcweir *p1 = *p2;
109cdf0e10cSrcweir *p2 = tmp;
110cdf0e10cSrcweir }
111cdf0e10cSrcweir
Invert(const std::_tstring & str)112cdf0e10cSrcweir static std::_tstring Invert(const std::_tstring& str)
113cdf0e10cSrcweir {
114cdf0e10cSrcweir char* buff = reinterpret_cast<char*>(_alloca(str.length()));
115cdf0e10cSrcweir strncpy(buff, str.c_str(), str.length());
116cdf0e10cSrcweir
117cdf0e10cSrcweir char* front = buff;
118cdf0e10cSrcweir char* back = buff + str.length() - 1;
119cdf0e10cSrcweir
120cdf0e10cSrcweir while (front < back)
121cdf0e10cSrcweir Swap(front++, back--);
122cdf0e10cSrcweir
123cdf0e10cSrcweir return std::_tstring(buff, str.length());
124cdf0e10cSrcweir }
125cdf0e10cSrcweir
126cdf0e10cSrcweir // Convert the upgrade code (which is a GUID) according
127cdf0e10cSrcweir // to the way the windows installer does when writing it
128cdf0e10cSrcweir // to the registry
129cdf0e10cSrcweir // The first 8 bytes will be inverted, from the the last
130cdf0e10cSrcweir // 8 bytes always the nibbles will be inverted for further
131cdf0e10cSrcweir // details look in the MSDN under compressed registry keys
ConvertGuid(const std::_tstring & guid)132cdf0e10cSrcweir static std::_tstring ConvertGuid(const std::_tstring& guid)
133cdf0e10cSrcweir {
134cdf0e10cSrcweir std::_tstring convertedGuid;
135cdf0e10cSrcweir
136cdf0e10cSrcweir std::_tstring part = GetGuidPart(guid, 0);
137cdf0e10cSrcweir convertedGuid = Invert(part);
138cdf0e10cSrcweir
139cdf0e10cSrcweir part = GetGuidPart(guid, 1);
140cdf0e10cSrcweir convertedGuid += Invert(part);
141cdf0e10cSrcweir
142cdf0e10cSrcweir part = GetGuidPart(guid, 2);
143cdf0e10cSrcweir convertedGuid += Invert(part);
144cdf0e10cSrcweir
145cdf0e10cSrcweir part = GetGuidPart(guid, 3);
146cdf0e10cSrcweir convertedGuid += Invert(std::_tstring(part.c_str(), 2));
147cdf0e10cSrcweir convertedGuid += Invert(std::_tstring(part.c_str() + 2, 2));
148cdf0e10cSrcweir
149cdf0e10cSrcweir part = GetGuidPart(guid, 4);
150cdf0e10cSrcweir int pos = 0;
151cdf0e10cSrcweir for (int i = 0; i < 6; i++)
152cdf0e10cSrcweir {
153cdf0e10cSrcweir convertedGuid += Invert(std::_tstring(part.c_str() + pos, 2));
154cdf0e10cSrcweir pos += 2;
155cdf0e10cSrcweir }
156cdf0e10cSrcweir return convertedGuid;
157cdf0e10cSrcweir }
158cdf0e10cSrcweir
IsSetMsiProperty(MSIHANDLE handle,const std::_tstring & sProperty)159cdf0e10cSrcweir static inline bool IsSetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty)
160cdf0e10cSrcweir {
161cdf0e10cSrcweir std::_tstring value = GetMsiProperty(handle, sProperty);
162cdf0e10cSrcweir return (value.length() > 0);
163cdf0e10cSrcweir }
164cdf0e10cSrcweir
UnsetMsiProperty(MSIHANDLE handle,const std::_tstring & sProperty)165cdf0e10cSrcweir static inline void UnsetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty)
166cdf0e10cSrcweir {
167cdf0e10cSrcweir MsiSetProperty(handle, sProperty.c_str(), NULL);
168cdf0e10cSrcweir }
169cdf0e10cSrcweir
SetMsiProperty(MSIHANDLE handle,const std::_tstring & sProperty)170cdf0e10cSrcweir static inline void SetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty)
171cdf0e10cSrcweir {
172cdf0e10cSrcweir MsiSetProperty(handle, sProperty.c_str(), TEXT("1"));
173cdf0e10cSrcweir }
174cdf0e10cSrcweir
MoveFileEx9x(LPCSTR lpExistingFileNameA,LPCSTR lpNewFileNameA,DWORD dwFlags)175cdf0e10cSrcweir static BOOL MoveFileEx9x( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, DWORD dwFlags )
176cdf0e10cSrcweir {
177cdf0e10cSrcweir BOOL fSuccess = FALSE; // assume failure
178cdf0e10cSrcweir
179cdf0e10cSrcweir // Windows 9x has a special mechanism to move files after reboot
180cdf0e10cSrcweir
181cdf0e10cSrcweir if ( dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT )
182cdf0e10cSrcweir {
183cdf0e10cSrcweir CHAR szExistingFileNameA[MAX_PATH];
184cdf0e10cSrcweir CHAR szNewFileNameA[MAX_PATH] = "NUL";
185cdf0e10cSrcweir
186cdf0e10cSrcweir // Path names in WININIT.INI must be in short path name form
187cdf0e10cSrcweir
188cdf0e10cSrcweir if (
189cdf0e10cSrcweir GetShortPathNameA( lpExistingFileNameA, szExistingFileNameA, MAX_PATH ) &&
190cdf0e10cSrcweir (!lpNewFileNameA || GetShortPathNameA( lpNewFileNameA, szNewFileNameA, MAX_PATH ))
191cdf0e10cSrcweir )
192cdf0e10cSrcweir {
193cdf0e10cSrcweir CHAR szBuffer[32767]; // The buffer size must not exceed 32K
194cdf0e10cSrcweir DWORD dwBufLen = GetPrivateProfileSectionA( RENAME_SECTION, szBuffer, elementsof(szBuffer), WININIT_FILENAME );
195cdf0e10cSrcweir
196cdf0e10cSrcweir CHAR szRename[MAX_PATH]; // This is enough for at most to times 67 chracters
197cdf0e10cSrcweir strcpy( szRename, szNewFileNameA );
198cdf0e10cSrcweir strcat( szRename, "=" );
199cdf0e10cSrcweir strcat( szRename, szExistingFileNameA );
200cdf0e10cSrcweir size_t lnRename = strlen(szRename);
201cdf0e10cSrcweir
202cdf0e10cSrcweir if ( dwBufLen + lnRename + 2 <= elementsof(szBuffer) )
203cdf0e10cSrcweir {
204cdf0e10cSrcweir CopyMemory( &szBuffer[dwBufLen], szRename, lnRename );
205cdf0e10cSrcweir szBuffer[dwBufLen + lnRename ] = 0;
206cdf0e10cSrcweir szBuffer[dwBufLen + lnRename + 1 ] = 0;
207cdf0e10cSrcweir
208cdf0e10cSrcweir fSuccess = WritePrivateProfileSectionA( RENAME_SECTION, szBuffer, WININIT_FILENAME );
209cdf0e10cSrcweir }
210cdf0e10cSrcweir else
211cdf0e10cSrcweir SetLastError( ERROR_BUFFER_OVERFLOW );
212cdf0e10cSrcweir }
213cdf0e10cSrcweir }
214cdf0e10cSrcweir else
215cdf0e10cSrcweir {
216cdf0e10cSrcweir
217cdf0e10cSrcweir fSuccess = MoveFileA( lpExistingFileNameA, lpNewFileNameA );
218cdf0e10cSrcweir
219cdf0e10cSrcweir if ( !fSuccess && GetLastError() != ERROR_ACCESS_DENIED &&
220cdf0e10cSrcweir 0 != (dwFlags & (MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) )
221cdf0e10cSrcweir {
222cdf0e10cSrcweir BOOL bFailIfExist = 0 == (dwFlags & MOVEFILE_REPLACE_EXISTING);
223cdf0e10cSrcweir
224cdf0e10cSrcweir fSuccess = CopyFileA( lpExistingFileNameA, lpNewFileNameA, bFailIfExist );
225cdf0e10cSrcweir
226cdf0e10cSrcweir if ( fSuccess )
227cdf0e10cSrcweir fSuccess = DeleteFileA( lpExistingFileNameA );
228cdf0e10cSrcweir }
229cdf0e10cSrcweir
230cdf0e10cSrcweir }
231cdf0e10cSrcweir
232cdf0e10cSrcweir return fSuccess;
233cdf0e10cSrcweir }
234cdf0e10cSrcweir
MoveFileExImpl(LPCSTR lpExistingFileNameA,LPCSTR lpNewFileNameA,DWORD dwFlags)235cdf0e10cSrcweir static BOOL MoveFileExImpl( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, DWORD dwFlags )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir if ( 0 > ((LONG)GetVersion())) // High order bit indicates Win 9x
238cdf0e10cSrcweir return MoveFileEx9x( lpExistingFileNameA, lpNewFileNameA, dwFlags );
239cdf0e10cSrcweir else
240cdf0e10cSrcweir return MoveFileExA( lpExistingFileNameA, lpNewFileNameA, dwFlags );
241cdf0e10cSrcweir }
242cdf0e10cSrcweir
SwapFiles(const std::_tstring & sFileName1,const std::_tstring & sFileName2)243cdf0e10cSrcweir static bool SwapFiles( const std::_tstring& sFileName1, const std::_tstring& sFileName2 )
244cdf0e10cSrcweir {
245cdf0e10cSrcweir std::_tstring sTempFileName = sFileName1 + TEXT(".tmp");
246cdf0e10cSrcweir
247cdf0e10cSrcweir bool fSuccess = true;
248cdf0e10cSrcweir
249cdf0e10cSrcweir //Try to move the original file to a temp file
250cdf0e10cSrcweir fSuccess = MoveFileExImpl( sFileName1.c_str(), sTempFileName.c_str(), MOVEFILE_REPLACE_EXISTING);
251cdf0e10cSrcweir
252cdf0e10cSrcweir std::_tstring mystr;
253cdf0e10cSrcweir
254cdf0e10cSrcweir if ( fSuccess )
255cdf0e10cSrcweir {
256cdf0e10cSrcweir fSuccess = MoveFileExImpl( sFileName2.c_str(), sFileName1.c_str(), MOVEFILE_REPLACE_EXISTING );
257cdf0e10cSrcweir
258cdf0e10cSrcweir if ( fSuccess )
259cdf0e10cSrcweir {
260cdf0e10cSrcweir fSuccess = MoveFileExImpl( sTempFileName.c_str(), sFileName2.c_str(),
261cdf0e10cSrcweir MOVEFILE_REPLACE_EXISTING );
262cdf0e10cSrcweir if ( !fSuccess )
263cdf0e10cSrcweir {
264cdf0e10cSrcweir MoveFileExImpl( sFileName1.c_str(), sFileName2.c_str(), MOVEFILE_REPLACE_EXISTING );
265cdf0e10cSrcweir }
266cdf0e10cSrcweir }
267cdf0e10cSrcweir else
268cdf0e10cSrcweir {
269cdf0e10cSrcweir MoveFileExImpl( sTempFileName.c_str(), sFileName1.c_str(), MOVEFILE_REPLACE_EXISTING );
270cdf0e10cSrcweir }
271cdf0e10cSrcweir }
272cdf0e10cSrcweir else
273cdf0e10cSrcweir {
274cdf0e10cSrcweir //It could be that there is no original file and therefore copying the original to a temp
275cdf0e10cSrcweir // file failed. Examine if there is no original and if so then move file2 to file1
276cdf0e10cSrcweir
277cdf0e10cSrcweir WIN32_FIND_DATA data;
278cdf0e10cSrcweir HANDLE hdl = FindFirstFile(sFileName1.c_str(), &data);
279cdf0e10cSrcweir if (hdl == INVALID_HANDLE_VALUE)
280cdf0e10cSrcweir {
281cdf0e10cSrcweir fSuccess = MoveFileExImpl( sFileName2.c_str(), sFileName1.c_str(), MOVEFILE_REPLACE_EXISTING );
282cdf0e10cSrcweir
283cdf0e10cSrcweir // if ( fSuccess )
284cdf0e10cSrcweir // {
285cdf0e10cSrcweir // mystr = "Success";
286cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK );
287cdf0e10cSrcweir // }
288cdf0e10cSrcweir // else
289cdf0e10cSrcweir // {
290cdf0e10cSrcweir // char buff[256];
291cdf0e10cSrcweir // wsprintf(buff, "Failure %d", GetLastError());
292cdf0e10cSrcweir // MessageBox( NULL, buff, "Titel", MB_OK );
293cdf0e10cSrcweir // }
294cdf0e10cSrcweir }
295cdf0e10cSrcweir else
296cdf0e10cSrcweir {
297cdf0e10cSrcweir FindClose(hdl);
298cdf0e10cSrcweir }
299cdf0e10cSrcweir }
300cdf0e10cSrcweir
301cdf0e10cSrcweir OutputDebugStringFormat( TEXT("%s <-> %s: %s"), sFileName1.c_str(), sFileName2.c_str(), fSuccess ? TEXT("OK") : TEXT("FAILED") );
302cdf0e10cSrcweir
303cdf0e10cSrcweir if (!fSuccess )
304cdf0e10cSrcweir {
305cdf0e10cSrcweir DWORD dwError = GetLastError();
306cdf0e10cSrcweir LPVOID lpMsgBuf;
307cdf0e10cSrcweir if ( FormatMessage(
308cdf0e10cSrcweir FORMAT_MESSAGE_ALLOCATE_BUFFER |
309cdf0e10cSrcweir FORMAT_MESSAGE_FROM_SYSTEM |
310cdf0e10cSrcweir FORMAT_MESSAGE_IGNORE_INSERTS,
311cdf0e10cSrcweir NULL,
312cdf0e10cSrcweir GetLastError(),
313cdf0e10cSrcweir MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
314cdf0e10cSrcweir (LPTSTR) &lpMsgBuf,
315cdf0e10cSrcweir 0,
316cdf0e10cSrcweir NULL ))
317cdf0e10cSrcweir {
318cdf0e10cSrcweir OutputDebugStringFormat( TEXT("Error Code %d: %s"), dwError, lpMsgBuf );
319cdf0e10cSrcweir LocalFree( lpMsgBuf );
320cdf0e10cSrcweir }
321cdf0e10cSrcweir else
322cdf0e10cSrcweir OutputDebugStringFormat( TEXT("Error Code %d: Unknown"), dwError );
323cdf0e10cSrcweir SetMsiErrorCode( dwError );
324cdf0e10cSrcweir }
325cdf0e10cSrcweir
326cdf0e10cSrcweir return fSuccess;
327cdf0e10cSrcweir }
328cdf0e10cSrcweir
strip(const std::_tstring & s,_TCHAR c)329cdf0e10cSrcweir static std::_tstring strip( const std::_tstring& s, _TCHAR c )
330cdf0e10cSrcweir {
331cdf0e10cSrcweir std::_tstring result = s;
332cdf0e10cSrcweir
333cdf0e10cSrcweir std::_tstring::size_type f;
334cdf0e10cSrcweir
335cdf0e10cSrcweir do
336cdf0e10cSrcweir {
337cdf0e10cSrcweir f = result.find( c );
338cdf0e10cSrcweir if ( f != std::_tstring::npos )
339cdf0e10cSrcweir result.erase( f, 1 );
340cdf0e10cSrcweir } while ( f != std::_tstring::npos );
341cdf0e10cSrcweir
342cdf0e10cSrcweir return result;
343cdf0e10cSrcweir }
344cdf0e10cSrcweir
trim(const std::_tstring & rString)345cdf0e10cSrcweir static std::_tstring trim( const std::_tstring& rString )
346cdf0e10cSrcweir {
347cdf0e10cSrcweir std::_tstring temp = rString;
348cdf0e10cSrcweir
349cdf0e10cSrcweir while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' )
350cdf0e10cSrcweir temp.erase( 0, 1 );
351cdf0e10cSrcweir
352cdf0e10cSrcweir std::_tstring::size_type len = temp.length();
353cdf0e10cSrcweir
354cdf0e10cSrcweir while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' )
355cdf0e10cSrcweir {
356cdf0e10cSrcweir temp.erase( len - 1, 1 );
357cdf0e10cSrcweir len = temp.length();
358cdf0e10cSrcweir }
359cdf0e10cSrcweir
360cdf0e10cSrcweir return temp;
361cdf0e10cSrcweir }
362cdf0e10cSrcweir
readLine(FILE * fp,std::_tstring & rLine)363cdf0e10cSrcweir static bool readLine( FILE *fp, std::_tstring& rLine )
364cdf0e10cSrcweir {
365cdf0e10cSrcweir _TCHAR szBuffer[1024];
366cdf0e10cSrcweir bool bSuccess = false;
367cdf0e10cSrcweir bool bEOL = false;
368cdf0e10cSrcweir std::_tstring line;
369cdf0e10cSrcweir
370cdf0e10cSrcweir
371cdf0e10cSrcweir while ( !bEOL && _fgetts( szBuffer, sizeof(szBuffer), fp ) )
372cdf0e10cSrcweir {
373cdf0e10cSrcweir int len = _tcslen(szBuffer);
374cdf0e10cSrcweir
375cdf0e10cSrcweir bSuccess = true;
376cdf0e10cSrcweir
377cdf0e10cSrcweir while ( len && szBuffer[len - 1] == '\n' )
378cdf0e10cSrcweir {
379cdf0e10cSrcweir szBuffer[--len] = 0;
380cdf0e10cSrcweir bEOL = true;
381cdf0e10cSrcweir }
382cdf0e10cSrcweir
383cdf0e10cSrcweir line.append( szBuffer );
384cdf0e10cSrcweir }
385cdf0e10cSrcweir
386cdf0e10cSrcweir rLine = line;
387cdf0e10cSrcweir return bSuccess;
388cdf0e10cSrcweir }
389cdf0e10cSrcweir
390cdf0e10cSrcweir
getProfileString(const std::_tstring & aFileName,const std::_tstring & aSectionName,const std::_tstring & aKeyName,const std::_tstring & aDefault=_T (""))391cdf0e10cSrcweir static std::_tstring getProfileString(
392cdf0e10cSrcweir const std::_tstring& aFileName,
393cdf0e10cSrcweir const std::_tstring& aSectionName,
394cdf0e10cSrcweir const std::_tstring& aKeyName,
395cdf0e10cSrcweir const std::_tstring& aDefault = _T("") )
396cdf0e10cSrcweir {
397cdf0e10cSrcweir FILE *fp = _tfopen( aFileName.c_str(), _T("r") );
398cdf0e10cSrcweir std::_tstring retValue = aDefault.length() ? aDefault : _T("");
399cdf0e10cSrcweir
400cdf0e10cSrcweir if ( fp )
401cdf0e10cSrcweir {
402cdf0e10cSrcweir std::_tstring line;
403cdf0e10cSrcweir std::_tstring section;
404cdf0e10cSrcweir
405cdf0e10cSrcweir while ( readLine( fp, line ) )
406cdf0e10cSrcweir {
407cdf0e10cSrcweir line = trim( line );
408cdf0e10cSrcweir
409cdf0e10cSrcweir if ( line.length() && line[0] == '[' )
410cdf0e10cSrcweir {
411cdf0e10cSrcweir line.erase( 0, 1 );
412cdf0e10cSrcweir std::_tstring::size_type end = line.find( ']', 0 );
413cdf0e10cSrcweir
414cdf0e10cSrcweir if ( std::_tstring::npos != end )
415cdf0e10cSrcweir section = trim( line.substr( 0, end ) );
416cdf0e10cSrcweir }
417cdf0e10cSrcweir else
418cdf0e10cSrcweir {
419cdf0e10cSrcweir
420cdf0e10cSrcweir std::_tstring::size_type iEqualSign = line.find( '=', 0 );
421cdf0e10cSrcweir
422cdf0e10cSrcweir if ( iEqualSign != std::_tstring::npos )
423cdf0e10cSrcweir {
424cdf0e10cSrcweir std::_tstring keyname = line.substr( 0, iEqualSign );
425cdf0e10cSrcweir keyname = trim( keyname );
426cdf0e10cSrcweir
427cdf0e10cSrcweir std::_tstring value = line.substr( iEqualSign + 1 /*, std::_tstring::npos */ );
428cdf0e10cSrcweir value = trim( value );
429cdf0e10cSrcweir
430cdf0e10cSrcweir if (
431cdf0e10cSrcweir 0 == _tcsicmp( section.c_str(), aSectionName.c_str() ) &&
432cdf0e10cSrcweir 0 == _tcsicmp( keyname.c_str(), aKeyName.c_str() )
433cdf0e10cSrcweir )
434cdf0e10cSrcweir {
435cdf0e10cSrcweir retValue = value;
436cdf0e10cSrcweir break;
437cdf0e10cSrcweir }
438cdf0e10cSrcweir }
439cdf0e10cSrcweir }
440cdf0e10cSrcweir }
441cdf0e10cSrcweir
442cdf0e10cSrcweir fclose( fp );
443cdf0e10cSrcweir }
444cdf0e10cSrcweir
445cdf0e10cSrcweir return retValue;
446cdf0e10cSrcweir }
447cdf0e10cSrcweir
getProfileSections(const std::_tstring & aFileName)448cdf0e10cSrcweir static std::queue< std::_tstring > getProfileSections( const std::_tstring& aFileName )
449cdf0e10cSrcweir {
450cdf0e10cSrcweir FILE *fp = _tfopen( aFileName.c_str(), _T("r") );
451cdf0e10cSrcweir std::queue< std::_tstring > aResult;
452cdf0e10cSrcweir
453cdf0e10cSrcweir OutputDebugStringFormat( TEXT("*** Retrieving Section Names ****") );
454cdf0e10cSrcweir
455cdf0e10cSrcweir if ( fp )
456cdf0e10cSrcweir {
457cdf0e10cSrcweir std::_tstring line;
458cdf0e10cSrcweir std::_tstring section;
459cdf0e10cSrcweir
460cdf0e10cSrcweir while ( readLine( fp, line ) )
461cdf0e10cSrcweir {
462cdf0e10cSrcweir line = trim( line );
463cdf0e10cSrcweir
464cdf0e10cSrcweir if ( line.length() && line[0] == '[' )
465cdf0e10cSrcweir {
466cdf0e10cSrcweir line.erase( 0, 1 );
467cdf0e10cSrcweir std::_tstring::size_type end = line.find( ']', 0 );
468cdf0e10cSrcweir
469cdf0e10cSrcweir if ( std::_tstring::npos != end )
470cdf0e10cSrcweir section = trim( line.substr( 0, end ) );
471cdf0e10cSrcweir
472cdf0e10cSrcweir aResult.push( section );
473cdf0e10cSrcweir
474cdf0e10cSrcweir OutputDebugStringFormat( TEXT("Section: %s"), section.c_str() );
475cdf0e10cSrcweir
476cdf0e10cSrcweir }
477cdf0e10cSrcweir }
478cdf0e10cSrcweir
479cdf0e10cSrcweir fclose( fp );
480cdf0e10cSrcweir }
481cdf0e10cSrcweir
482cdf0e10cSrcweir OutputDebugStringFormat( TEXT("*** Done Section Names ***") );
483cdf0e10cSrcweir
484cdf0e10cSrcweir return aResult;
485cdf0e10cSrcweir }
486cdf0e10cSrcweir
getProfileKeys(const std::_tstring & aFileName,const std::_tstring & aSectionName)487cdf0e10cSrcweir static std::queue< std::_tstring > getProfileKeys( const std::_tstring& aFileName, const std::_tstring& aSectionName )
488cdf0e10cSrcweir {
489cdf0e10cSrcweir FILE *fp = _tfopen( aFileName.c_str(), _T("r") );
490cdf0e10cSrcweir std::queue< std::_tstring > aResult;
491cdf0e10cSrcweir
492cdf0e10cSrcweir OutputDebugStringFormat( TEXT("*** Retrieving Key Names for [%s] ***"), aSectionName.c_str() );
493cdf0e10cSrcweir
494cdf0e10cSrcweir if ( fp )
495cdf0e10cSrcweir {
496cdf0e10cSrcweir std::_tstring line;
497cdf0e10cSrcweir std::_tstring section;
498cdf0e10cSrcweir
499cdf0e10cSrcweir while ( readLine( fp, line ) )
500cdf0e10cSrcweir {
501cdf0e10cSrcweir line = trim( line );
502cdf0e10cSrcweir
503cdf0e10cSrcweir if ( line.length() && line[0] == '[' )
504cdf0e10cSrcweir {
505cdf0e10cSrcweir line.erase( 0, 1 );
506cdf0e10cSrcweir std::_tstring::size_type end = line.find( ']', 0 );
507cdf0e10cSrcweir
508cdf0e10cSrcweir if ( std::_tstring::npos != end )
509cdf0e10cSrcweir section = trim( line.substr( 0, end ) );
510cdf0e10cSrcweir }
511cdf0e10cSrcweir else
512cdf0e10cSrcweir {
513cdf0e10cSrcweir
514cdf0e10cSrcweir std::_tstring::size_type iEqualSign = line.find( '=', 0 );
515cdf0e10cSrcweir
516cdf0e10cSrcweir if ( iEqualSign != std::_tstring::npos )
517cdf0e10cSrcweir {
518cdf0e10cSrcweir std::_tstring keyname = line.substr( 0, iEqualSign );
519cdf0e10cSrcweir keyname = trim( keyname );
520cdf0e10cSrcweir
521cdf0e10cSrcweir if ( 0 == _tcsicmp( section.c_str(), aSectionName.c_str() ) )
522cdf0e10cSrcweir {
523cdf0e10cSrcweir aResult.push( keyname );
524cdf0e10cSrcweir
525cdf0e10cSrcweir OutputDebugStringFormat( keyname.c_str() );
526cdf0e10cSrcweir
527cdf0e10cSrcweir }
528cdf0e10cSrcweir }
529cdf0e10cSrcweir }
530cdf0e10cSrcweir }
531cdf0e10cSrcweir
532cdf0e10cSrcweir fclose( fp );
533cdf0e10cSrcweir }
534cdf0e10cSrcweir
535cdf0e10cSrcweir OutputDebugStringFormat( TEXT("*** Done Key Names for [%s] ***"), aSectionName.c_str() );
536cdf0e10cSrcweir
537cdf0e10cSrcweir return aResult;
538cdf0e10cSrcweir }
539cdf0e10cSrcweir
InstallPatchedFiles(MSIHANDLE handle)540cdf0e10cSrcweir extern "C" UINT __stdcall InstallPatchedFiles( MSIHANDLE handle )
541cdf0e10cSrcweir {
542cdf0e10cSrcweir std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") );
543910823aeSJürgen Schmidt // std::_tstring sProgramDir = sInstDir + TEXT("Basis\\program\\");
544910823aeSJürgen Schmidt std::_tstring sProgramDir = sInstDir + TEXT("program\\");
545cdf0e10cSrcweir std::_tstring sPatchFile = sProgramDir + TEXT("patchlist.txt");
546cdf0e10cSrcweir
547cdf0e10cSrcweir std::queue< std::_tstring > aSectionNames;
548cdf0e10cSrcweir std::queue< std::_tstring > aKeyNames;
549cdf0e10cSrcweir
550cdf0e10cSrcweir OutputDebugStringA( "Starting Custom Action" );
551cdf0e10cSrcweir
552cdf0e10cSrcweir // std::_tstring mystr;
553cdf0e10cSrcweir // mystr = "Patchfile: " + sPatchFile;
554cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Patchfile", MB_OK );
555cdf0e10cSrcweir
556cdf0e10cSrcweir aSectionNames = getProfileSections( sPatchFile );
557cdf0e10cSrcweir while ( !aSectionNames.empty() )
558cdf0e10cSrcweir {
559cdf0e10cSrcweir std::_tstring sSectionName = aSectionNames.front();
560cdf0e10cSrcweir if ( std::_tstring(TEXT("_root")) == sSectionName ) { sSectionName = TEXT(""); }
561cdf0e10cSrcweir // mystr = "Section: " + sSectionName;
562cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK );
563cdf0e10cSrcweir
564cdf0e10cSrcweir aKeyNames = getProfileKeys( sPatchFile, sSectionName );
565cdf0e10cSrcweir while ( !aKeyNames.empty() )
566cdf0e10cSrcweir {
567cdf0e10cSrcweir std::_tstring sKeyName = aKeyNames.front();
568cdf0e10cSrcweir std::_tstring sValue = getProfileString( sPatchFile, sSectionName, sKeyName );
569cdf0e10cSrcweir
570cdf0e10cSrcweir if ( sValue.length() )
571cdf0e10cSrcweir {
572cdf0e10cSrcweir std::_tstring sFileName1 = sKeyName;
573cdf0e10cSrcweir std::_tstring sExtension = sValue;
574cdf0e10cSrcweir std::_tstring sFileName2;
575cdf0e10cSrcweir
576cdf0e10cSrcweir sFileName1 = strip( sFileName1, '\"' );
577cdf0e10cSrcweir sExtension = strip( sExtension, '\"' );
578cdf0e10cSrcweir
579cdf0e10cSrcweir sFileName1 = sInstDir + sSectionName + sFileName1;
580cdf0e10cSrcweir sFileName2 = sFileName1 + sExtension;
581cdf0e10cSrcweir
582cdf0e10cSrcweir // mystr = "Convert: " + sFileName1 + " to " + sFileName2;
583cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK );
584cdf0e10cSrcweir
585cdf0e10cSrcweir SwapFiles( sFileName1, sFileName2 );
586cdf0e10cSrcweir }
587cdf0e10cSrcweir
588cdf0e10cSrcweir aKeyNames.pop();
589cdf0e10cSrcweir }
590cdf0e10cSrcweir
591cdf0e10cSrcweir aSectionNames.pop();
592cdf0e10cSrcweir }
593cdf0e10cSrcweir
594cdf0e10cSrcweir return ERROR_SUCCESS;
595cdf0e10cSrcweir }
596cdf0e10cSrcweir
UninstallPatchedFiles(MSIHANDLE handle)597cdf0e10cSrcweir extern "C" UINT __stdcall UninstallPatchedFiles( MSIHANDLE handle )
598cdf0e10cSrcweir {
599cdf0e10cSrcweir TCHAR szValue[8192];
600cdf0e10cSrcweir DWORD nValueSize = sizeof(szValue);
601cdf0e10cSrcweir HKEY hKey;
602cdf0e10cSrcweir
603cdf0e10cSrcweir std::_tstring sInstDir;
604cdf0e10cSrcweir
605cdf0e10cSrcweir std::_tstring sProductKey = GetMsiProperty( handle, TEXT("FINDPRODUCT") );
606cdf0e10cSrcweir
607cdf0e10cSrcweir if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, sProductKey.c_str(), &hKey ) )
608cdf0e10cSrcweir {
609cdf0e10cSrcweir if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
610cdf0e10cSrcweir {
611cdf0e10cSrcweir sInstDir = szValue;
612cdf0e10cSrcweir }
613cdf0e10cSrcweir RegCloseKey( hKey );
614cdf0e10cSrcweir }
615cdf0e10cSrcweir else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sProductKey.c_str(), &hKey ) )
616cdf0e10cSrcweir {
617cdf0e10cSrcweir if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
618cdf0e10cSrcweir {
619cdf0e10cSrcweir sInstDir = szValue;
620cdf0e10cSrcweir }
621cdf0e10cSrcweir RegCloseKey( hKey );
622cdf0e10cSrcweir }
623cdf0e10cSrcweir else
624cdf0e10cSrcweir return ERROR_SUCCESS;
625cdf0e10cSrcweir
626*28b67305SJürgen Schmidt // std::_tstring sProgramDir = sInstDir + TEXT("Basis\\program\\");
627*28b67305SJürgen Schmidt std::_tstring sProgramDir = sInstDir + TEXT("program\\");
628cdf0e10cSrcweir std::_tstring sPatchFile = sProgramDir + TEXT("patchlist.txt");
629cdf0e10cSrcweir
630cdf0e10cSrcweir std::queue< std::_tstring > aSectionNames;
631cdf0e10cSrcweir std::queue< std::_tstring > aKeyNames;
632cdf0e10cSrcweir
633cdf0e10cSrcweir // std::_tstring mystr;
634cdf0e10cSrcweir // mystr = "Patchfile: " + sPatchFile;
635cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK );
636cdf0e10cSrcweir
637cdf0e10cSrcweir aSectionNames = getProfileSections( sPatchFile );
638cdf0e10cSrcweir while ( !aSectionNames.empty() )
639cdf0e10cSrcweir {
640cdf0e10cSrcweir std::_tstring sSectionName = aSectionNames.front();
641cdf0e10cSrcweir if ( std::_tstring(TEXT("_root")) == sSectionName ) { sSectionName = TEXT(""); }
642cdf0e10cSrcweir // mystr = "Section: " + sSectionName;
643cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK );
644cdf0e10cSrcweir
645cdf0e10cSrcweir aKeyNames = getProfileKeys( sPatchFile, sSectionName );
646cdf0e10cSrcweir while( !aKeyNames.empty() )
647cdf0e10cSrcweir {
648cdf0e10cSrcweir std::_tstring sKeyName = aKeyNames.front();
649cdf0e10cSrcweir std::_tstring sValue = getProfileString( sPatchFile, sSectionName, sKeyName );
650cdf0e10cSrcweir
651cdf0e10cSrcweir if ( sValue.length() )
652cdf0e10cSrcweir {
653cdf0e10cSrcweir std::_tstring sFileName1 = sKeyName;
654cdf0e10cSrcweir std::_tstring sExtension = sValue;
655cdf0e10cSrcweir std::_tstring sFileName2;
656cdf0e10cSrcweir
657cdf0e10cSrcweir sFileName1 = strip( sFileName1, '\"' );
658cdf0e10cSrcweir sExtension = strip( sExtension, '\"' );
659cdf0e10cSrcweir
660cdf0e10cSrcweir sFileName1 = sInstDir + sSectionName + sFileName1;
661cdf0e10cSrcweir sFileName2 = sFileName1 + sExtension;
662cdf0e10cSrcweir
663cdf0e10cSrcweir // mystr = "Convert: " + sFileName1 + " to " + sFileName2;
664cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK );
665cdf0e10cSrcweir
666cdf0e10cSrcweir SwapFiles( sFileName2, sFileName1 );
667cdf0e10cSrcweir }
668cdf0e10cSrcweir
669cdf0e10cSrcweir aKeyNames.pop();
670cdf0e10cSrcweir }
671cdf0e10cSrcweir
672cdf0e10cSrcweir aSectionNames.pop();
673cdf0e10cSrcweir }
674cdf0e10cSrcweir
675cdf0e10cSrcweir return ERROR_SUCCESS;
676cdf0e10cSrcweir }
677cdf0e10cSrcweir
IsOfficeRunning(MSIHANDLE handle)678cdf0e10cSrcweir extern "C" UINT __stdcall IsOfficeRunning( MSIHANDLE handle )
679cdf0e10cSrcweir {
680cdf0e10cSrcweir std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") );
681*28b67305SJürgen Schmidt // std::_tstring sResourceDir = sInstDir + TEXT("Basis\\program\\resource\\");
682*28b67305SJürgen Schmidt std::_tstring sResourceDir = sInstDir + TEXT("program\\resource\\");
683cdf0e10cSrcweir std::_tstring sPattern = sResourceDir + TEXT("vcl*.res");
684cdf0e10cSrcweir
685cdf0e10cSrcweir WIN32_FIND_DATA aFindFileData;
686cdf0e10cSrcweir HANDLE hFind = FindFirstFile( sPattern.c_str(), &aFindFileData );
687cdf0e10cSrcweir
688cdf0e10cSrcweir if ( IsValidHandle(hFind) )
689cdf0e10cSrcweir {
690cdf0e10cSrcweir BOOL fSuccess = false;
691cdf0e10cSrcweir bool fRenameSucceeded;
692cdf0e10cSrcweir
693cdf0e10cSrcweir do
694cdf0e10cSrcweir {
695cdf0e10cSrcweir std::_tstring sResourceFile = sResourceDir + aFindFileData.cFileName;
696cdf0e10cSrcweir std::_tstring sIntermediate = sResourceFile + TEXT(".tmp");
697cdf0e10cSrcweir
698cdf0e10cSrcweir fRenameSucceeded = MoveFileExImpl( sResourceFile.c_str(), sIntermediate.c_str(), MOVEFILE_REPLACE_EXISTING );
699cdf0e10cSrcweir if ( fRenameSucceeded )
700cdf0e10cSrcweir {
701cdf0e10cSrcweir MoveFileExImpl( sIntermediate.c_str(), sResourceFile.c_str(), 0 );
702cdf0e10cSrcweir fSuccess = FindNextFile( hFind, &aFindFileData );
703cdf0e10cSrcweir }
704cdf0e10cSrcweir } while ( fSuccess && fRenameSucceeded );
705cdf0e10cSrcweir
706cdf0e10cSrcweir if ( !fRenameSucceeded )
707cdf0e10cSrcweir {
708cdf0e10cSrcweir MsiSetProperty(handle, TEXT("OFFICERUNS"), TEXT("1"));
709cdf0e10cSrcweir SetMsiErrorCode( MSI_ERROR_OFFICE_IS_RUNNING );
710cdf0e10cSrcweir }
711cdf0e10cSrcweir
712cdf0e10cSrcweir FindClose( hFind );
713cdf0e10cSrcweir }
714cdf0e10cSrcweir
715cdf0e10cSrcweir
716cdf0e10cSrcweir return ERROR_SUCCESS;
717cdf0e10cSrcweir }
718cdf0e10cSrcweir
SetFeatureState(MSIHANDLE handle)719cdf0e10cSrcweir extern "C" UINT __stdcall SetFeatureState( MSIHANDLE handle )
720cdf0e10cSrcweir {
721cdf0e10cSrcweir std::_tstring mystr;
722cdf0e10cSrcweir
723cdf0e10cSrcweir // 1. Reading Product Code from setup.ini of installed Office
724cdf0e10cSrcweir
725cdf0e10cSrcweir std::_tstring sInstallPath = GetMsiProperty(handle, TEXT("INSTALLLOCATION"));
726cdf0e10cSrcweir // MessageBox(NULL, sInstallPath.c_str(), "INSTALLLOCATION", MB_OK);
727cdf0e10cSrcweir std::_tstring sSetupiniPath = sInstallPath + TEXT("program\\setup.ini");
728cdf0e10cSrcweir
729cdf0e10cSrcweir TCHAR szProductCode[32767];
730cdf0e10cSrcweir
731cdf0e10cSrcweir GetPrivateProfileString(
732cdf0e10cSrcweir TEXT("Bootstrap"),
733cdf0e10cSrcweir TEXT("ProductCode"),
734cdf0e10cSrcweir TEXT("NOTFOUND"),
735cdf0e10cSrcweir szProductCode,
736cdf0e10cSrcweir elementsof(szProductCode),
737cdf0e10cSrcweir sSetupiniPath.c_str()
738cdf0e10cSrcweir );
739cdf0e10cSrcweir
740cdf0e10cSrcweir if ( !_tcsicmp( szProductCode, TEXT("NOTFOUND") ) )
741cdf0e10cSrcweir {
742cdf0e10cSrcweir // No setup.ini or no "ProductCode" in setup.ini. This is an invalid directory.
743cdf0e10cSrcweir // MessageBox(NULL, "NOTFOUND set", "DEBUG", MB_OK);
744cdf0e10cSrcweir return ERROR_SUCCESS;
745cdf0e10cSrcweir }
746cdf0e10cSrcweir
747cdf0e10cSrcweir // 2. Converting Product code
748cdf0e10cSrcweir
749cdf0e10cSrcweir std::_tstring productCode = TEXT(szProductCode);
750cdf0e10cSrcweir productCode = ConvertGuid(std::_tstring(productCode.c_str() + 1, productCode.length() - 2));
751cdf0e10cSrcweir mystr = TEXT("Changed product code: ") + productCode;
752cdf0e10cSrcweir // MessageBox(NULL, mystr.c_str(), "ProductCode", MB_OK);
753cdf0e10cSrcweir
754cdf0e10cSrcweir // 3. Setting path in the Windows registry to find installed features
755cdf0e10cSrcweir
756cdf0e10cSrcweir std::_tstring registryKey;
757cdf0e10cSrcweir HKEY registryRoot;
758cdf0e10cSrcweir
759cdf0e10cSrcweir if ( IsSetMsiProperty(handle, TEXT("ALLUSERS")) )
760cdf0e10cSrcweir {
761cdf0e10cSrcweir registryRoot = HKEY_LOCAL_MACHINE;
762cdf0e10cSrcweir registryKey = TEXT("Software\\Classes\\Installer\\Features\\") + productCode;
763cdf0e10cSrcweir mystr = registryKey;
764cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ALLUSERS", MB_OK );
765cdf0e10cSrcweir }
766cdf0e10cSrcweir else
767cdf0e10cSrcweir {
768cdf0e10cSrcweir registryRoot = HKEY_CURRENT_USER;
769cdf0e10cSrcweir registryKey = TEXT("Software\\Microsoft\\Installer\\Features\\") + productCode;
770cdf0e10cSrcweir mystr = registryKey;
771cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ALLUSERS", MB_OK );
772cdf0e10cSrcweir }
773cdf0e10cSrcweir
774cdf0e10cSrcweir // 4. Collecting all installed features from Windows registry
775cdf0e10cSrcweir
776cdf0e10cSrcweir HKEY hKey;
777cdf0e10cSrcweir if (RegOpenKey(registryRoot, registryKey.c_str(), &hKey) == ERROR_SUCCESS)
778cdf0e10cSrcweir {
779cdf0e10cSrcweir int counter = 0;
780cdf0e10cSrcweir // DWORD counter = 0;
781cdf0e10cSrcweir LONG lEnumResult;
782cdf0e10cSrcweir
783cdf0e10cSrcweir do
784cdf0e10cSrcweir {
785cdf0e10cSrcweir TCHAR szValueName[8192];
786cdf0e10cSrcweir DWORD nValueNameSize = sizeof(szValueName);
787cdf0e10cSrcweir LPDWORD pValueNameSize = &nValueNameSize;
788cdf0e10cSrcweir TCHAR szValueData[8192];
789cdf0e10cSrcweir DWORD nValueDataSize = sizeof(szValueData);
790cdf0e10cSrcweir
791cdf0e10cSrcweir lEnumResult = RegEnumValue( hKey, counter, szValueName, pValueNameSize, NULL, NULL, (LPBYTE)szValueData, &nValueDataSize);
792cdf0e10cSrcweir
793cdf0e10cSrcweir if ( ERROR_SUCCESS == lEnumResult )
794cdf0e10cSrcweir {
795cdf0e10cSrcweir std::_tstring sValueName = szValueName;
796cdf0e10cSrcweir std::_tstring sValueData = szValueData;
797cdf0e10cSrcweir
798cdf0e10cSrcweir // mystr = sValueName;
799cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ValueName", MB_OK );
800cdf0e10cSrcweir // mystr = sValueData;
801cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ValueData", MB_OK );
802cdf0e10cSrcweir
803cdf0e10cSrcweir // Does this feature exist in this patch?
804cdf0e10cSrcweir if ( IsSetMsiProperty(handle, sValueName) )
805cdf0e10cSrcweir {
806cdf0e10cSrcweir // Feature is not installed, if szValueData starts with a "square" (ascii 6)
807cdf0e10cSrcweir if ( 6 == szValueData[0] )
808cdf0e10cSrcweir {
809cdf0e10cSrcweir MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_ABSENT); // do not install this feature
810cdf0e10cSrcweir // mystr = TEXT("Do NOT install: ") + sValueName;
811cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ValueName", MB_OK );
812cdf0e10cSrcweir }
813cdf0e10cSrcweir else
814cdf0e10cSrcweir {
815cdf0e10cSrcweir MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_LOCAL); // do install this feature
816cdf0e10cSrcweir // mystr = TEXT("Do install: ") + sValueName;
817cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ValueName", MB_OK );
818cdf0e10cSrcweir }
819cdf0e10cSrcweir }
820cdf0e10cSrcweir }
821cdf0e10cSrcweir
822cdf0e10cSrcweir counter = counter + 1;
823cdf0e10cSrcweir
824cdf0e10cSrcweir } while ( ERROR_SUCCESS == lEnumResult );
825cdf0e10cSrcweir
826cdf0e10cSrcweir RegCloseKey( hKey );
827cdf0e10cSrcweir }
828cdf0e10cSrcweir
829cdf0e10cSrcweir return ERROR_SUCCESS;
830cdf0e10cSrcweir }
831cdf0e10cSrcweir
SetNewFeatureState(MSIHANDLE handle)832cdf0e10cSrcweir extern "C" UINT __stdcall SetNewFeatureState( MSIHANDLE handle )
833cdf0e10cSrcweir {
834cdf0e10cSrcweir std::_tstring mystr;
835cdf0e10cSrcweir std::_tstring sValueName;
836cdf0e10cSrcweir
837cdf0e10cSrcweir sValueName = TEXT("gm_o_Onlineupdate");
838cdf0e10cSrcweir
839cdf0e10cSrcweir if (IsSetMsiProperty(handle, TEXT("SELECT_OU_FEATURE")))
840cdf0e10cSrcweir {
841cdf0e10cSrcweir MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_LOCAL); // do install this feature
842cdf0e10cSrcweir // mystr = TEXT("OnlineUpdate wird installiert!");
843cdf0e10cSrcweir // MessageBox(NULL, mystr.c_str(), "INSTALLSTATE_LOCAL", MB_OK);
844cdf0e10cSrcweir }
845cdf0e10cSrcweir else
846cdf0e10cSrcweir {
847cdf0e10cSrcweir MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_ABSENT); // do not install this feature
848cdf0e10cSrcweir // mystr = TEXT("OnlineUpdate wird NICHT installiert!");
849cdf0e10cSrcweir // MessageBox(NULL, mystr.c_str(), "INSTALLSTATE_ABSENT", MB_OK);
850cdf0e10cSrcweir }
851cdf0e10cSrcweir
852cdf0e10cSrcweir return ERROR_SUCCESS;
853cdf0e10cSrcweir }
854cdf0e10cSrcweir
ShowOnlineUpdateDialog(MSIHANDLE handle)855cdf0e10cSrcweir extern "C" UINT __stdcall ShowOnlineUpdateDialog( MSIHANDLE handle )
856cdf0e10cSrcweir {
857cdf0e10cSrcweir // Checking existence of file "updchk.uno.dll", which shows, that
858cdf0e10cSrcweir // Online Update functionality is always available. Then the dialog
859cdf0e10cSrcweir // that offers the Online Update is superfluous.
860cdf0e10cSrcweir
861cdf0e10cSrcweir std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") );
862*28b67305SJürgen Schmidt // std::_tstring sProgramDir = sInstDir + TEXT("Basis\\program\\");
863*28b67305SJürgen Schmidt std::_tstring sProgramDir = sInstDir + TEXT("program\\");
864cdf0e10cSrcweir std::_tstring sSearchFile = sProgramDir + TEXT("updchk.uno.dll");
865cdf0e10cSrcweir
866cdf0e10cSrcweir WIN32_FIND_DATA data;
867cdf0e10cSrcweir HANDLE hdl = FindFirstFile(sSearchFile.c_str(), &data);
868cdf0e10cSrcweir if (hdl != INVALID_HANDLE_VALUE) // the file exists
869cdf0e10cSrcweir {
870cdf0e10cSrcweir // std::_tstring mystr;
871cdf0e10cSrcweir // mystr = "Found file: " + sSearchFile;
872cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Found file", MB_OK );
873cdf0e10cSrcweir
874cdf0e10cSrcweir // And finally setting property SHOW_ONLINEUPDATE_DIALOG
875cdf0e10cSrcweir // to hide this dialog
876cdf0e10cSrcweir UnsetMsiProperty(handle, TEXT("SHOW_ONLINEUPDATE_DIALOG"));
877cdf0e10cSrcweir
878cdf0e10cSrcweir // Setting SELECT_OU_FEATURE to 1, which is probably superfluous
879cdf0e10cSrcweir // because this is already the default value. But only this
880cdf0e10cSrcweir // guarantees, that CustomAction SetNewFeatureState always sets
881cdf0e10cSrcweir // the correct FeatureState for "gm_o_Onlineupdate", if it is
882cdf0e10cSrcweir // already installed.
883cdf0e10cSrcweir SetMsiProperty(handle, TEXT("SELECT_OU_FEATURE"));
884cdf0e10cSrcweir }
885cdf0e10cSrcweir else
886cdf0e10cSrcweir {
887cdf0e10cSrcweir // std::_tstring mystr;
888cdf0e10cSrcweir // mystr = "Did not find file: " + sSearchFile;
889cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "File not found", MB_OK );
890cdf0e10cSrcweir
891cdf0e10cSrcweir // If the file does not exist, the Online Update dialog
892cdf0e10cSrcweir // has to be shown.
893cdf0e10cSrcweir SetMsiProperty(handle, TEXT("SHOW_ONLINEUPDATE_DIALOG"));
894cdf0e10cSrcweir FindClose(hdl);
895cdf0e10cSrcweir }
896cdf0e10cSrcweir
897cdf0e10cSrcweir return ERROR_SUCCESS;
898cdf0e10cSrcweir }
899