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 //#include <stdio.h>
25 
26 #ifdef _MSC_VER
27 #pragma warning(push, 1) /* disable warnings within system headers */
28 #endif
29 #include <windows.h>
30 #include <msi.h>
31 #include <msiquery.h>
32 #ifdef _MSC_VER
33 #pragma warning(pop)
34 #endif
35 
36 #if defined UNICODE
37 #define _UNICODE
38 #endif
39 #include <tchar.h>
40 
41 // Simple function prototypes
42 bool update_activesync_regvalues(bool, bool, char** );
43 void createKeys(HKEY hKey, char **);
44 void deleteKeys(HKEY hKey, char **);
45 bool isMulti(MSIHANDLE);
46 
47 // Simple data arrays for registry values
48 TCHAR *pxlData[8]= {
49 	"{C6AB3E74-9F4F-4370-8120-A8A6FABB7A7C}", // CLSID 1 - key name at InstalledFilters Key
50 	"{43887C67-4D5D-4127-BAAC-87A288494C7C}", // CLSID 2 - key value for Default Export
51 	".pxl",									  // Registry key for device type - already there if ActiveSync installed
52 	".sxc",									  // New registry key for SO docs
53 	"InstalledFilters",						  // Sub-key of device/so doc key
54 	"DefaultImport",						  // Key name added at device/so level key
55 	"DefaultExport",						  // Key name added at device/so level key
56 	"Binary Copy",							  // Key value for DefaultImport
57 };
58 
59 TCHAR *pswData[8] = {
60 	"{BDD611C3-7BAB-460F-8711-5B9AC9EF6020}", // CLSID 1 - key name at InstalledFilters Key
61 	"{CB43F086-838D-4FA4-B5F6-3406B9A57439}", // CLSID 2 - key value for Default Export
62 	".psw",									  // Registry key for device type - already there if ActiveSync installed
63 	".sxw",									  // New registry key for SO docs
64 	"InstalledFilters",						  // Sub-key of device/so doc key
65 	"DefaultImport",						  // Key name added at device/so level key
66 	"DefaultExport",						  // Key name added at device/so level key
67 	"Binary Copy",							  // Key value for DefaultImport
68 };
69 
70 
71 // index into registry value arrays
72 #define CLSID1 0
73 #define CLSID2 1
74 #define DEVICE_PATH 2
75 #define SO_PATH 3
76 #define IF_PATH 4
77 #define DEFIMPORT_KEY 5
78 #define DEFEXPORT_KEY 6
79 #define BC_VALUE 7
80 
81 // Constants for Registry buffers
82 const int MAX_KEY_LENGTH=255;
83 const int MAX_VALUE_NAME=16383;
84 
DllMain(HANDLE,DWORD ul_reason,LPVOID)85 BOOL APIENTRY DllMain( HANDLE,
86                        DWORD  ul_reason,
87                        LPVOID
88 					 )
89 {
90     switch (ul_reason)
91 	{
92 		case DLL_PROCESS_ATTACH:
93 		case DLL_THREAD_ATTACH:
94 		case DLL_THREAD_DETACH:
95 		case DLL_PROCESS_DETACH:
96 			break;
97     }
98     return TRUE;
99 }
100 
install_jf(MSIHANDLE hModule)101 extern "C" UINT install_jf ( MSIHANDLE hModule ) {
102 	bool bMulti = isMulti(hModule);
103 #ifdef _JRGREG_DEBUG
104 	MessageBox(NULL, bMulti ? "Multi" : "Single", "Install", MB_OK);
105 #endif
106 	update_activesync_regvalues(bMulti, true, pxlData);
107 	update_activesync_regvalues(bMulti, true, pswData);
108 
109     return ERROR_SUCCESS;
110 }
111 
uninstall_jf(MSIHANDLE hModule)112 extern "C" UINT uninstall_jf ( MSIHANDLE hModule ) {
113 	bool bMulti = isMulti(hModule);
114 #ifdef _JRGREG_DEBUG
115 	MessageBox(NULL, bMulti ? "Multi" : "Single", "Uninstall", MB_OK);
116 #endif
117 	update_activesync_regvalues(false, bMulti, pxlData);
118 	update_activesync_regvalues(false, bMulti, pswData);
119 
120     return ERROR_SUCCESS;
121 }
122 
123 /**
124 	Determines if this is being installed on a per user or a machine wide basis
125     @param hModule
126     [in] a valid msi handle.
127 
128 
129     @returns
130     <TRUE/>if this is a multi-user install.
131 */
isMulti(MSIHANDLE hModule)132 bool isMulti( MSIHANDLE hModule ) {
133     TCHAR* szValueBuf = NULL;
134     DWORD cchValueBuf = 0;
135 	bool bRet = false;
136     UINT uiStat =  MsiGetProperty(hModule, TEXT("ALLUSERS"), TEXT(""), &cchValueBuf);
137     if (ERROR_MORE_DATA == uiStat)
138     {
139         ++cchValueBuf; // on output does not include terminating null, so add 1
140         szValueBuf = new TCHAR[cchValueBuf];
141         if (szValueBuf)
142         {
143             uiStat = MsiGetProperty(hModule, TEXT("ALLUSERS"), szValueBuf, &cchValueBuf);
144         }
145     }
146     if (ERROR_SUCCESS != uiStat)
147     {
148         return false;
149     }
150 	bRet = _tcscmp(szValueBuf, TEXT("1")) == 0;
151     delete [] szValueBuf;
152 
153     return bRet;
154 }
155 
156 /**
157 	Add or remove ActiveSync integration entries from the registry
158     @param bMultiUser
159     [in] <TRUE/>if this is a multiuser install (<FALSE/> for single user install)
160 
161 	@param bInstall
162 	[in] <TRUE/>if installing
163 
164 	@param data
165 	[in] an array of string containing names of registry keys and values
166 
167 
168     @returns
169     <TRUE/>if this is a multi-user install.
170 */
171 
update_activesync_regvalues(bool bMultiUser,bool bInstall,char ** data)172 bool update_activesync_regvalues(bool bMultiUser, bool bInstall, char **data) {
173 	bool bReturn = false;
174 	CHAR SUKey[]    = "Software\\Microsoft\\Windows CE Services\\Partners";
175 	CHAR MUKey[]    = "Software\\Microsoft\\Windows CE Services\\Filters";
176 	HKEY hKey;
177 
178 	if (bMultiUser) {
179 		if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)MUKey, 0, KEY_ALL_ACCESS, &hKey)) {
180 			return false;
181 		}
182 		if (bInstall) {
183 			createKeys(hKey, data);
184 		} else {
185 			deleteKeys(hKey, data);
186 		}
187 		bReturn = true;
188 	} else {
189 		if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)SUKey, 0, KEY_ALL_ACCESS, &hKey)) {
190 			return false;
191 		}
192 
193 		CHAR     achKey[MAX_KEY_LENGTH];   // buffer for subkey name
194 		DWORD    cbName;                   // size of name string
195 		CHAR     achClass[MAX_PATH] = "";  // buffer for class name
196 		DWORD    cchClassName = MAX_PATH;  // size of class string
197 		DWORD    cSubKeys=0;               // number of subkeys
198 		DWORD    cbMaxSubKey;              // longest subkey size
199 		DWORD    cchMaxClass;              // longest class string
200 		DWORD    cValues;              // number of values for key
201 		DWORD    cchMaxValue;          // longest value name
202 		DWORD    cbMaxValueData;       // longest value data
203 		DWORD    cbSecurityDescriptor; // size of security descriptor
204 		FILETIME ftLastWriteTime;      // last write time
205 
206 		// Get the class name and the value count.
207 		if (ERROR_SUCCESS == RegQueryInfoKey(
208 			hKey,                    // key handle
209 			achClass,                // buffer for class name
210 			&cchClassName,           // size of class string
211 			NULL,                    // reserved
212 			&cSubKeys,               // number of subkeys
213 			&cbMaxSubKey,            // longest subkey size
214 			&cchMaxClass,            // longest class string
215 			&cValues,                // number of values for this key
216 			&cchMaxValue,            // longest value name
217 			&cbMaxValueData,         // longest value data
218 			&cbSecurityDescriptor,   // security descriptor
219 			&ftLastWriteTime)) {     // last write time
220 
221 			if (cSubKeys) {
222 				for (DWORD i=0; i<cSubKeys; i++) {
223 					cbName = 1024;
224 					if (ERROR_SUCCESS == RegEnumKeyEx(hKey,i,achKey,&cbName,NULL,NULL,NULL,&ftLastWriteTime)) {
225 						HKEY subKey;
226 						if (ERROR_SUCCESS == RegOpenKeyEx(hKey, achKey, 0, KEY_ALL_ACCESS, &subKey)) {
227 							if (ERROR_SUCCESS == RegOpenKeyEx(subKey, "Filters", 0, KEY_ALL_ACCESS, &subKey)) {
228 								if (bInstall) {
229 									createKeys(subKey, data);
230 								} else {
231 									deleteKeys(subKey, data);
232 								}
233 								RegCloseKey(subKey);
234 							}
235 						}
236 					}
237 				}
238 			}
239 
240 			bReturn = true;
241 		}
242 	}
243 	if (hKey != NULL) {
244 		RegCloseKey(hKey);
245 	}
246 
247 	return bReturn;
248 }
249 
250 /**
251 	Create Registry Keys
252 
253     @param hKey
254     [in] Handle to the parent registry key
255 
256 	@param data
257 	[in] an array of string containing names of registry keys and values
258 */
259 
createKeys(HKEY hKey,char ** data)260 void createKeys(HKEY hKey, char **data) {
261 
262 	LPCSTR clsid1     = data[CLSID1];
263 	LPCSTR clsid2     = data[CLSID2];
264 	LPCSTR devicePath = data[DEVICE_PATH];
265 	LPCSTR soPath     = data[SO_PATH];
266 	LPCSTR defImport  = data[DEFIMPORT_KEY];
267 	LPCSTR defExport  = data[DEFEXPORT_KEY];
268 	LPCSTR binaryCopy = data[BC_VALUE];
269 	LPCSTR IFPath     = data[IF_PATH];
270 
271 	HKEY deviceKey, deviceIFKey, soKey, soIFKey;
272 
273 	if (ERROR_SUCCESS == RegOpenKeyEx(hKey,devicePath,0,KEY_ALL_ACCESS, &deviceKey)) {
274 		if (ERROR_SUCCESS == RegOpenKeyEx(deviceKey,IFPath,0,KEY_ALL_ACCESS, &deviceIFKey)) {
275 			RegSetValueEx(deviceIFKey, clsid1, 0, REG_SZ, NULL, NULL);
276 		}
277 	}
278 
279 	if (ERROR_SUCCESS == RegCreateKeyEx(hKey, soPath, 0, NULL,
280 							REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &soKey, NULL)) {
281 		RegSetValueEx(soKey, defExport, 0, REG_SZ, (LPBYTE)binaryCopy, strlen(binaryCopy));
282 		RegSetValueEx(soKey, defImport, 0, REG_SZ, (LPBYTE)clsid2, strlen(clsid2));
283 
284 
285 		if (ERROR_SUCCESS == RegCreateKeyEx(soKey, IFPath, 0, NULL,
286 							REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &soIFKey, NULL)) {
287 			RegSetValueEx(soIFKey, clsid2, 0, REG_SZ, NULL, NULL);
288 		}
289 	}
290 }
291 
292 /**
293 	Delete registry keys
294 
295     @param hKey
296     [in] Handle to the parent registry key
297 */
deleteKeys(HKEY hKey,TCHAR ** data)298 void deleteKeys(HKEY hKey, TCHAR **data) {
299 	LPCSTR clsid1     = data[CLSID1];
300 	LPCSTR clsid2     = data[CLSID2];
301 	LPCSTR devicePath = data[DEVICE_PATH];
302 	LPCSTR soPath     = data[SO_PATH];
303 	LPCSTR defImport  = data[DEFIMPORT_KEY];
304 	LPCSTR defExport  = data[DEFEXPORT_KEY];
305 	LPCSTR IFPath     = data[IF_PATH];
306 
307 	HKEY deviceKey, deviceIFKey, soKey, soIFKey;
308 
309 	if (ERROR_SUCCESS == RegOpenKeyEx(hKey,devicePath,0,KEY_ALL_ACCESS, &deviceKey)) {
310 		if (ERROR_SUCCESS == RegOpenKeyEx(deviceKey,IFPath,0,KEY_ALL_ACCESS, &deviceIFKey)) {
311 			RegDeleteValue(deviceIFKey, clsid1);
312 		}
313 	}
314 
315 	if (ERROR_SUCCESS == RegOpenKeyEx(hKey, soPath, 0, KEY_ALL_ACCESS, &soKey)) {
316 		RegDeleteValue(soKey, defExport);
317 		RegDeleteValue(soKey, defImport);
318 
319 		if (ERROR_SUCCESS == RegOpenKeyEx(soKey, IFPath, 0, KEY_ALL_ACCESS, &soIFKey)) {
320 			RegDeleteValue(soIFKey, clsid2);
321 			RegCloseKey(soIFKey);
322 			RegDeleteKey(soKey, IFPath);
323 		}
324 		RegCloseKey(soKey);
325 		RegDeleteKey(hKey, soPath);
326 	}
327 }
328