1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski /*
25*b1cdbd2cSJim Jagielski     Windows shell extensions need to be approved in order to be used by the
26*b1cdbd2cSJim Jagielski     Windows shell for clarification read the following section from the
27*b1cdbd2cSJim Jagielski     Microsoft Developers Network Library (MSDN) see
28*b1cdbd2cSJim Jagielski     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_int/shell_int_extending/extensionhandlers/shell_ext.asp
29*b1cdbd2cSJim Jagielski 
30*b1cdbd2cSJim Jagielski 
31*b1cdbd2cSJim Jagielski     <MSDN>
32*b1cdbd2cSJim Jagielski     Shell extension handlers run in the Shell process. Because it is a system process,
33*b1cdbd2cSJim Jagielski     the administrator of a Windows NT system can limit Shell extension handlers to
34*b1cdbd2cSJim Jagielski     those on an approved list by setting the EnforceShellExtensionSecurity value of the
35*b1cdbd2cSJim Jagielski     HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer key to 1
36*b1cdbd2cSJim Jagielski     (one).
37*b1cdbd2cSJim Jagielski     To place a Shell extension handler on the approved list, create a REG_SZ value whose
38*b1cdbd2cSJim Jagielski     name is the string form of the handler's GUID under
39*b1cdbd2cSJim Jagielski     HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved.
40*b1cdbd2cSJim Jagielski 
41*b1cdbd2cSJim Jagielski     The Shell does not use the value that is assigned to the GUID, but it should be set to
42*b1cdbd2cSJim Jagielski     make inspecting the registry easier.
43*b1cdbd2cSJim Jagielski 
44*b1cdbd2cSJim Jagielski     Your setup application can add values to the Approved key only if the person installing
45*b1cdbd2cSJim Jagielski     the application has sufficient privileges. If the attempt to add an extension handler
46*b1cdbd2cSJim Jagielski     fails, you should inform the user that administrative privileges are required to fully
47*b1cdbd2cSJim Jagielski     install the application. If the handler is essential to the application, you should fail
48*b1cdbd2cSJim Jagielski     the setup and notify the user to contact an administrator.
49*b1cdbd2cSJim Jagielski 
50*b1cdbd2cSJim Jagielski     While there is no need to add values to the Approved key on Windows 95 or Windows 98
51*b1cdbd2cSJim Jagielski     systems, there is no harm in doing so. The system will simply ignore them. However, there
52*b1cdbd2cSJim Jagielski     is no guarantee that the key will exist on these systems. Your setup program must be able
53*b1cdbd2cSJim Jagielski     to handle this case.
54*b1cdbd2cSJim Jagielski     </MSDN>
55*b1cdbd2cSJim Jagielski 
56*b1cdbd2cSJim Jagielski     We add the following entries to the respective registry key
57*b1cdbd2cSJim Jagielski     "{C52AF81D-F7A0-4AAB-8E87-F80A60CCD396}"="OpenOffice Column Handler"
58*b1cdbd2cSJim Jagielski     "{087B3AE3-E237-4467-B8DB-5A38AB959AC9}"="OpenOffice Infotip Handler"
59*b1cdbd2cSJim Jagielski     "{63542C48-9552-494A-84F7-73AA6A7C99C1}"="OpenOffice Property Sheet Handler"
60*b1cdbd2cSJim Jagielski     "{3B092F0C-7696-40E3-A80F-68D74DA84210}"="OpenOffice Thumbnail Viewer"
61*b1cdbd2cSJim Jagielski 
62*b1cdbd2cSJim Jagielski     These shell extensions are implemented in the 'shell' project. We ignore registration
63*b1cdbd2cSJim Jagielski     failures because of insufficient privileges. The reason is: On systems which restrict the
64*b1cdbd2cSJim Jagielski     use of shell extensions by applying the aforementioned policy probably only people with
65*b1cdbd2cSJim Jagielski     sufficient privileges are allowed to install applications anyway. On systems where the
66*b1cdbd2cSJim Jagielski     use of shell extensions is not restricted registration failures because of insufficient
67*b1cdbd2cSJim Jagielski     prviliges have no negative effect because the shell extensions will work anyhow.
68*b1cdbd2cSJim Jagielski */
69*b1cdbd2cSJim Jagielski 
70*b1cdbd2cSJim Jagielski #ifdef _MSC_VER
71*b1cdbd2cSJim Jagielski #pragma warning(push, 1) /* disable warnings within system headers */
72*b1cdbd2cSJim Jagielski #endif
73*b1cdbd2cSJim Jagielski #define WIN32_LEAN_AND_MEAN
74*b1cdbd2cSJim Jagielski #include <windows.h>
75*b1cdbd2cSJim Jagielski #include <msiquery.h>
76*b1cdbd2cSJim Jagielski #ifdef _MSC_VER
77*b1cdbd2cSJim Jagielski #pragma warning(pop)
78*b1cdbd2cSJim Jagielski #endif
79*b1cdbd2cSJim Jagielski 
80*b1cdbd2cSJim Jagielski #include <malloc.h>
81*b1cdbd2cSJim Jagielski 
82*b1cdbd2cSJim Jagielski #ifdef UNICODE
83*b1cdbd2cSJim Jagielski #define _UNICODE
84*b1cdbd2cSJim Jagielski #endif
85*b1cdbd2cSJim Jagielski #include <tchar.h>
86*b1cdbd2cSJim Jagielski 
87*b1cdbd2cSJim Jagielski struct RegistryEntry
88*b1cdbd2cSJim Jagielski {
89*b1cdbd2cSJim Jagielski     TCHAR* Key;
90*b1cdbd2cSJim Jagielski     TCHAR* Value;
91*b1cdbd2cSJim Jagielski };
92*b1cdbd2cSJim Jagielski 
93*b1cdbd2cSJim Jagielski RegistryEntry ColumnHandler = { TEXT("{C52AF81D-F7A0-4AAB-8E87-F80A60CCD396}"), TEXT("OpenOffice Column Handler") };
94*b1cdbd2cSJim Jagielski RegistryEntry InfotipHandler = { TEXT("{087B3AE3-E237-4467-B8DB-5A38AB959AC9}"), TEXT("OpenOffice Infotip Handler") };
95*b1cdbd2cSJim Jagielski RegistryEntry PropHandler = { TEXT("{63542C48-9552-494A-84F7-73AA6A7C99C1}"), TEXT("OpenOffice Property Sheet Handler") };
96*b1cdbd2cSJim Jagielski RegistryEntry ThumbViewer = { TEXT("{3B092F0C-7696-40E3-A80F-68D74DA84210}"), TEXT("OpenOffice Thumbnail Viewer") };
97*b1cdbd2cSJim Jagielski 
GetMsiProp(MSIHANDLE hMSI,const char * pPropName,char ** ppValue)98*b1cdbd2cSJim Jagielski BOOL GetMsiProp( MSIHANDLE hMSI, const char* pPropName, char** ppValue )
99*b1cdbd2cSJim Jagielski {
100*b1cdbd2cSJim Jagielski     DWORD sz = 0;
101*b1cdbd2cSJim Jagielski    	if ( MsiGetProperty( hMSI, pPropName, 0, &sz ) == ERROR_MORE_DATA )
102*b1cdbd2cSJim Jagielski    	{
103*b1cdbd2cSJim Jagielski        	sz++;
104*b1cdbd2cSJim Jagielski        	DWORD nbytes = sz * sizeof( char );
105*b1cdbd2cSJim Jagielski        	char* buff = reinterpret_cast<char*>( malloc( nbytes ) );
106*b1cdbd2cSJim Jagielski        	ZeroMemory( buff, nbytes );
107*b1cdbd2cSJim Jagielski        	MsiGetProperty( hMSI, pPropName, buff, &sz );
108*b1cdbd2cSJim Jagielski    		*ppValue = buff;
109*b1cdbd2cSJim Jagielski 
110*b1cdbd2cSJim Jagielski 		return TRUE;
111*b1cdbd2cSJim Jagielski 	}
112*b1cdbd2cSJim Jagielski 
113*b1cdbd2cSJim Jagielski 	return FALSE;
114*b1cdbd2cSJim Jagielski }
115*b1cdbd2cSJim Jagielski 
IsVersionNT64(MSIHANDLE hMSI)116*b1cdbd2cSJim Jagielski bool IsVersionNT64( MSIHANDLE hMSI )
117*b1cdbd2cSJim Jagielski {
118*b1cdbd2cSJim Jagielski     char* pVal = NULL;
119*b1cdbd2cSJim Jagielski 
120*b1cdbd2cSJim Jagielski 	if ( GetMsiProp( hMSI, "VersionNT64", &pVal ) && pVal )
121*b1cdbd2cSJim Jagielski 	{
122*b1cdbd2cSJim Jagielski 		free( pVal );
123*b1cdbd2cSJim Jagielski 		return true;
124*b1cdbd2cSJim Jagielski 	}
125*b1cdbd2cSJim Jagielski 
126*b1cdbd2cSJim Jagielski 	return false;
127*b1cdbd2cSJim Jagielski }
128*b1cdbd2cSJim Jagielski 
129*b1cdbd2cSJim Jagielski 
130*b1cdbd2cSJim Jagielski 
131*b1cdbd2cSJim Jagielski 
132*b1cdbd2cSJim Jagielski /*
133*b1cdbd2cSJim Jagielski     Called during installation when the module "Windows Explorer Extensions" is
134*b1cdbd2cSJim Jagielski     selected.
135*b1cdbd2cSJim Jagielski */
InstallExecSequenceEntry(MSIHANDLE hMSI)136*b1cdbd2cSJim Jagielski extern "C" UINT __stdcall InstallExecSequenceEntry(MSIHANDLE hMSI)
137*b1cdbd2cSJim Jagielski {
138*b1cdbd2cSJim Jagielski     //MessageBox(NULL, TEXT("InstallExecSequenceEntry"), TEXT("Pythonmsi"), MB_OK | MB_ICONINFORMATION);
139*b1cdbd2cSJim Jagielski     HKEY hKey;
140*b1cdbd2cSJim Jagielski 
141*b1cdbd2cSJim Jagielski 
142*b1cdbd2cSJim Jagielski // 06.11.2009 tkr: to provide windows xp as build systems for mingw we need to define KEY_WOW64_64KEY
143*b1cdbd2cSJim Jagielski // in mingw 3.13 KEY_WOW64_64KEY isn't available < Win2003 systems.
144*b1cdbd2cSJim Jagielski // Also defined in setup_native\source\win32\customactions\reg64\reg64.cxx,source\win32\customactions\shellextensions\shellextensions.cxx and
145*b1cdbd2cSJim Jagielski // extensions\source\activex\main\so_activex.cpp
146*b1cdbd2cSJim Jagielski #ifndef KEY_WOW64_64KEY
147*b1cdbd2cSJim Jagielski 	#define KEY_WOW64_64KEY	(0x0100)
148*b1cdbd2cSJim Jagielski #endif
149*b1cdbd2cSJim Jagielski 
150*b1cdbd2cSJim Jagielski 	if (IsVersionNT64(hMSI))
151*b1cdbd2cSJim Jagielski 	{
152*b1cdbd2cSJim Jagielski 		// Open Windows 64 Bit Registry
153*b1cdbd2cSJim Jagielski 		if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"),0, KEY_WRITE | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS)
154*b1cdbd2cSJim Jagielski 		{
155*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, ColumnHandler.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(ColumnHandler.Value), _tcslen(ColumnHandler.Value) + 1);
156*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, InfotipHandler.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(InfotipHandler.Value), _tcslen(InfotipHandler.Value) + 1);
157*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, PropHandler.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(PropHandler.Value), _tcslen(PropHandler.Value) + 1);
158*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, ThumbViewer.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(ThumbViewer.Value), _tcslen(ThumbViewer.Value) + 1);
159*b1cdbd2cSJim Jagielski 
160*b1cdbd2cSJim Jagielski 			RegCloseKey(hKey);
161*b1cdbd2cSJim Jagielski 		}
162*b1cdbd2cSJim Jagielski 
163*b1cdbd2cSJim Jagielski 		// Open Windows 32 Bit Registry on Win64 maschine
164*b1cdbd2cSJim Jagielski 
165*b1cdbd2cSJim Jagielski 		if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"),0, KEY_WRITE, &hKey ) == ERROR_SUCCESS)
166*b1cdbd2cSJim Jagielski 		{
167*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, ColumnHandler.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(ColumnHandler.Value), _tcslen(ColumnHandler.Value) + 1);
168*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, InfotipHandler.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(InfotipHandler.Value), _tcslen(InfotipHandler.Value) + 1);
169*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, PropHandler.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(PropHandler.Value), _tcslen(PropHandler.Value) + 1);
170*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, ThumbViewer.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(ThumbViewer.Value), _tcslen(ThumbViewer.Value) + 1);
171*b1cdbd2cSJim Jagielski 
172*b1cdbd2cSJim Jagielski 			RegCloseKey(hKey);
173*b1cdbd2cSJim Jagielski 		}
174*b1cdbd2cSJim Jagielski 
175*b1cdbd2cSJim Jagielski 
176*b1cdbd2cSJim Jagielski 	} else
177*b1cdbd2cSJim Jagielski 	{
178*b1cdbd2cSJim Jagielski 		if (RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), &hKey) == ERROR_SUCCESS)
179*b1cdbd2cSJim Jagielski 		{
180*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, ColumnHandler.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(ColumnHandler.Value), _tcslen(ColumnHandler.Value) + 1);
181*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, InfotipHandler.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(InfotipHandler.Value), _tcslen(InfotipHandler.Value) + 1);
182*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, PropHandler.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(PropHandler.Value), _tcslen(PropHandler.Value) + 1);
183*b1cdbd2cSJim Jagielski 			RegSetValueEx(hKey, ThumbViewer.Key, 0, REG_SZ, reinterpret_cast<const BYTE*>(ThumbViewer.Value), _tcslen(ThumbViewer.Value) + 1);
184*b1cdbd2cSJim Jagielski 
185*b1cdbd2cSJim Jagielski 			RegCloseKey(hKey);
186*b1cdbd2cSJim Jagielski 		}
187*b1cdbd2cSJim Jagielski 	}
188*b1cdbd2cSJim Jagielski     return ERROR_SUCCESS;
189*b1cdbd2cSJim Jagielski }
190*b1cdbd2cSJim Jagielski 
191*b1cdbd2cSJim Jagielski /*
192*b1cdbd2cSJim Jagielski     Called during deinstallation when the module "Windows Explorer Extensions" has
193*b1cdbd2cSJim Jagielski     been installed.
194*b1cdbd2cSJim Jagielski */
DeinstallExecSequenceEntry(MSIHANDLE)195*b1cdbd2cSJim Jagielski extern "C" UINT __stdcall DeinstallExecSequenceEntry(MSIHANDLE)
196*b1cdbd2cSJim Jagielski {
197*b1cdbd2cSJim Jagielski     //MessageBox(NULL, TEXT("DeinstallExecSequenceEntry"), TEXT("Pythonmsi"), MB_OK | MB_ICONINFORMATION);
198*b1cdbd2cSJim Jagielski     HKEY hKey;
199*b1cdbd2cSJim Jagielski     if (RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), &hKey) == ERROR_SUCCESS)
200*b1cdbd2cSJim Jagielski     {
201*b1cdbd2cSJim Jagielski         RegDeleteValue(hKey, ColumnHandler.Key);
202*b1cdbd2cSJim Jagielski         RegDeleteValue(hKey, InfotipHandler.Key);
203*b1cdbd2cSJim Jagielski         RegDeleteValue(hKey, PropHandler.Key);
204*b1cdbd2cSJim Jagielski         RegDeleteValue(hKey, ThumbViewer.Key);
205*b1cdbd2cSJim Jagielski 
206*b1cdbd2cSJim Jagielski         RegCloseKey(hKey);
207*b1cdbd2cSJim Jagielski     }
208*b1cdbd2cSJim Jagielski     return ERROR_SUCCESS;
209*b1cdbd2cSJim Jagielski }
210