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 #include "stdafx.h"
24 
25 #include "XMergeFilter.h"
26 #include "XMergeFactory.h"
27 
28 
29 CXMergeSyncModule _Module;
30 
31 
32 //////////////////////////////////////////////////////////////////////
33 // DLL Functions
34 //////////////////////////////////////////////////////////////////////
DllMain(HANDLE hInst,ULONG ulReason,LPVOID lpReserved)35 BOOL WINAPI DllMain(HANDLE hInst, ULONG ulReason, LPVOID lpReserved)
36 {
37 	switch (ulReason)
38 	{
39 		case DLL_PROCESS_ATTACH:
40 			_Module.m_hInst = reinterpret_cast<HINSTANCE>(hInst);
41 			break;
42 
43 		case DLL_PROCESS_DETACH:
44 			_Module.m_hInst = NULL;
45 			break;
46 
47 		case DLL_THREAD_ATTACH:
48 			break;
49 
50 		case DLL_THREAD_DETACH:
51 			break;
52 	}
53 
54 	return TRUE;
55 }
56 
57 
DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)58 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
59 {
60 	// Create the factory object
61 	CXMergeFactory *pFactory = new CXMergeFactory();
62 	if (pFactory == NULL)
63 	{
64 		*ppv = NULL;
65 		return E_OUTOFMEMORY;
66 	}
67 
68 	HRESULT hr = pFactory->QueryInterface(riid, ppv);
69 	pFactory->Release();
70 
71 	return hr;
72 }
73 
74 
DllCanUnloadNow()75 STDAPI DllCanUnloadNow()
76 {
77 	if (_Module.GetLockCount() == 0)
78 		return S_OK;
79 
80 	return S_FALSE;
81 }
82 
83 
84 // Utility function to close open keys during registration
_signalRegError(long lRet,HKEY hKey,HKEY hDataKey)85 static _signalRegError(long lRet, HKEY hKey, HKEY hDataKey)
86 {
87 	if (hKey)
88 		::RegCloseKey(hKey);
89 
90 
91 	if (hDataKey)
92 		::RegCloseKey(hDataKey);
93 
94 	return HRESULT_FROM_WIN32(lRet);
95 }
96 
97 
DllRegisterServer()98 STDAPI DllRegisterServer()
99 {
100 	HKEY hKey = NULL;
101 	HKEY hDataKey = NULL;
102 
103 	long lRet = 0;
104 	TCHAR sTemp[_MAX_PATH + 1] = "\0";
105 
106 
107 	/*
108 	 * Following calls create the HKEY_CLASSES_ROOT\CLSID entry for the Writer export filter.
109 	 *
110 	 * Note that import are export are relative to the WinCE device, so files are
111 	 * exported to the desktop format.
112 	 */
113 
114 	// Get a handle to the CLSID key
115 	lRet = ::RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID"), 0, KEY_ALL_ACCESS, &hKey);
116 	if (lRet != ERROR_SUCCESS)
117 		return _signalRegError(lRet, hKey, hDataKey);
118 
119 	// Create the CLSID key for the XMergeFilter
120 	lRet = ::RegCreateKeyEx(hKey, CXMergeFilter::m_pszPSWExportCLSID, 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
121 	if (lRet != ERROR_SUCCESS)
122 		return _signalRegError(lRet, hKey, hDataKey);
123 
124 	lRet = ::RegSetValueEx(hKey, _T(""), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPSWExportShortDesc,
125 				(::_tcslen(CXMergeFilter::m_pszPSWExportShortDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
126 	if (lRet != ERROR_SUCCESS)
127 		return _signalRegError(lRet, hKey, hDataKey);
128 
129 
130 	// Create the DefaultIcon key.  For the moment, use one of the Async supplied ones
131 	lRet = ::RegCreateKeyEx(hKey, _T("DefaultIcon"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
132 	if (lRet != ERROR_SUCCESS)
133 		return _signalRegError(lRet, hKey, hDataKey);
134 
135 	lRet = ::RegSetValueEx(hDataKey, NULL, 0, REG_SZ, (LPBYTE)_T("C:\\Program Files\\Microsoft ActiveSync\\pwdcnv.dll,0"),
136 							(::_tcslen(_T("C:\\Program Files\\Microsoft ActiveSync\\pwdcnv.dll,0"))
137 							   * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
138 	if (lRet != ERROR_SUCCESS)
139 		return _signalRegError(lRet, hKey, hDataKey);
140 	::RegCloseKey(hDataKey);  hDataKey = NULL;
141 
142 	// Create the InprocServer32 key
143 	lRet = ::RegCreateKeyEx(hKey, _T("InProcServer32"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
144 	if (lRet != ERROR_SUCCESS)
145 		return _signalRegError(lRet, hKey, hDataKey);
146 
147 	lRet = ::RegSetValueEx(hDataKey, _T("ThreadingModel"), 0, REG_SZ, (LPBYTE)_T("Apartment"), 10);
148 	if (lRet != ERROR_SUCCESS)
149 		return _signalRegError(lRet, hKey, hDataKey);
150 
151 	// Create the key for the DLL file.  First find the filename of the dll
152 	if (!::GetModuleFileName((HMODULE)_Module.m_hInst, sTemp, (_MAX_PATH + 1)))
153 	{
154 		lRet = ::GetLastError();
155 		if (lRet != ERROR_SUCCESS)
156 			return _signalRegError(lRet, hKey, hDataKey);
157 	}
158 
159 
160 	lRet = ::RegSetValueEx(hDataKey, NULL, 0, REG_SZ, (LPBYTE)sTemp,
161 				(::_tcslen(sTemp) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
162 	if (lRet != ERROR_SUCCESS)
163 		return _signalRegError(lRet, hKey, hDataKey);
164 	::RegCloseKey(hDataKey);	hDataKey = NULL;
165 
166 
167 	// Setup the PegasusFilter key values
168 	lRet = ::RegCreateKeyEx(hKey, _T("PegasusFilter"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
169 	if (lRet != ERROR_SUCCESS)
170 		return _signalRegError(lRet, hKey, hDataKey);
171 
172 	lRet = ::RegSetValueEx(hDataKey, _T("Description"), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPSWExportDesc,
173 				(::_tcslen(CXMergeFilter::m_pszPSWExportDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
174 	if (lRet != ERROR_SUCCESS)
175 		return _signalRegError(lRet, hKey, hDataKey);
176 
177 
178 	lRet = ::RegSetValueEx(hDataKey, _T("Export"), 0, REG_SZ, (LPBYTE)_T(""), (1 * sizeof(TCHAR)));
179 	if (lRet != ERROR_SUCCESS)
180 		return _signalRegError(lRet, hKey, hDataKey);
181 
182 
183 	lRet = ::RegSetValueEx(hDataKey, _T("NewExtension"), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPSWExportExt,
184 				(::_tcslen(CXMergeFilter::m_pszPSWExportExt) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
185 	if (lRet != ERROR_SUCCESS)
186 		return _signalRegError(lRet, hKey, hDataKey);
187 
188 
189 	::RegCloseKey(hKey);		hKey = NULL;
190 	::RegCloseKey(hDataKey);	hDataKey = NULL;
191 
192 
193 
194 
195 	/*
196 	 * Following calls create the entries for the filter in
197 	 * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\Filters
198 	 */
199 
200 	lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows CE Services\\Filters"),
201 				0, KEY_ALL_ACCESS, &hKey);
202 	if (lRet != ERROR_SUCCESS)
203 		return _signalRegError(lRet, hKey, hDataKey);
204 
205 	_snprintf(sTemp, _MAX_PATH + 1, "%c%s\\InstalledFilters\0", '.', CXMergeFilter::m_pszPSWImportExt);
206 	lRet = ::RegCreateKeyEx(hKey, _T(sTemp),
207 				0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
208 	if (lRet != ERROR_SUCCESS)
209 		return _signalRegError(lRet, hKey, hDataKey);
210 
211 	lRet = ::RegSetValueEx(hDataKey, CXMergeFilter::m_pszPSWExportCLSID, 0, REG_SZ, (LPBYTE)_T(""), (1 * sizeof(TCHAR)));
212 	if (lRet != ERROR_SUCCESS)
213 		return _signalRegError(lRet, hKey, hDataKey);
214 
215 	::RegCloseKey(hKey);		hKey = NULL;
216 	::RegCloseKey(hDataKey);	hDataKey = NULL;
217 
218 
219 
220 	/*
221 	 * Following calls create the HKEY_CLASSES_ROOT\CLSID entry for the Writer import filter.
222 	 *
223 	 * Note that import are export are relative to the WinCE device, so files are
224 	 * exported to the desktop format.
225 	 */
226 	// Get a handle to the CLSID key
227 	lRet = ::RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID"), 0, KEY_ALL_ACCESS, &hKey);
228 	if (lRet != ERROR_SUCCESS)
229 		return _signalRegError(lRet, hKey, hDataKey);
230 
231 	// Create the CLSID key for the XMergeFilter
232 	lRet = ::RegCreateKeyEx(hKey, CXMergeFilter::m_pszPSWImportCLSID, 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
233 	if (lRet != ERROR_SUCCESS)
234 		return _signalRegError(lRet, hKey, hDataKey);
235 
236 	lRet = ::RegSetValueEx(hKey, _T(""), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPSWImportShortDesc,
237 				(::_tcslen(CXMergeFilter::m_pszPSWImportShortDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
238 	if (lRet != ERROR_SUCCESS)
239 		return _signalRegError(lRet, hKey, hDataKey);
240 
241 
242 	// Create the DefaultIcon key.  For the moment, use one of the Async supplied ones
243 	lRet = ::RegCreateKeyEx(hKey, _T("DefaultIcon"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
244 	if (lRet != ERROR_SUCCESS)
245 		return _signalRegError(lRet, hKey, hDataKey);
246 
247 	lRet = ::RegSetValueEx(hDataKey, NULL, 0, REG_SZ, (LPBYTE)_T("C:\\Program Files\\Microsoft ActiveSync\\pwdcnv.dll,0"),
248 							(::_tcslen(_T("C:\\Program Files\\Microsoft ActiveSync\\pwdcnv.dll,0"))
249 							   * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
250 	if (lRet != ERROR_SUCCESS)
251 		return _signalRegError(lRet, hKey, hDataKey);
252 	::RegCloseKey(hDataKey);  hDataKey = NULL;
253 
254 
255 	// Create the InprocServer32 key
256 	lRet = ::RegCreateKeyEx(hKey, _T("InProcServer32"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
257 	if (lRet != ERROR_SUCCESS)
258 		return _signalRegError(lRet, hKey, hDataKey);
259 
260 	lRet = ::RegSetValueEx(hDataKey, _T("ThreadingModel"), 0, REG_SZ, (LPBYTE)_T("Apartment"), 10);
261 	if (lRet != ERROR_SUCCESS)
262 		return _signalRegError(lRet, hKey, hDataKey);
263 
264 
265 	// Create the key for the DLL file.  First find the filename of the dll
266 	if (!::GetModuleFileName((HMODULE)_Module.m_hInst, sTemp, (_MAX_PATH + 1)))
267 	{
268 		lRet = ::GetLastError();
269 		if (lRet != ERROR_SUCCESS)
270 			return _signalRegError(lRet, hKey, hDataKey);
271 	}
272 
273 
274 	lRet = ::RegSetValueEx(hDataKey, NULL, 0, REG_SZ, (LPBYTE)sTemp,
275 				(::_tcslen(sTemp) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
276 	if (lRet != ERROR_SUCCESS)
277 		return _signalRegError(lRet, hKey, hDataKey);
278 	::RegCloseKey(hDataKey);	hDataKey = NULL;
279 
280 
281 	// Setup the PegasusFilter key values
282 	lRet = ::RegCreateKeyEx(hKey, _T("PegasusFilter"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
283 	if (lRet != ERROR_SUCCESS)
284 		return _signalRegError(lRet, hKey, hDataKey);
285 
286 		lRet = ::RegSetValueEx(hDataKey, _T("Description"), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPSWImportDesc,
287 				(::_tcslen(CXMergeFilter::m_pszPSWImportDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
288 	if (lRet != ERROR_SUCCESS)
289 		return _signalRegError(lRet, hKey, hDataKey);
290 
291 
292 	lRet = ::RegSetValueEx(hDataKey, _T("Import"), 0, REG_SZ, (LPBYTE)_T(""), (1 * sizeof(TCHAR)));
293 	if (lRet != ERROR_SUCCESS)
294 		return _signalRegError(lRet, hKey, hDataKey);
295 
296 
297 	lRet = ::RegSetValueEx(hDataKey, _T("NewExtension"), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPSWImportExt,
298 				(::_tcslen(CXMergeFilter::m_pszPSWImportExt) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
299 	if (lRet != ERROR_SUCCESS)
300 		return _signalRegError(lRet, hKey, hDataKey);
301 
302 
303 	::RegCloseKey(hKey);		hKey = NULL;
304 	::RegCloseKey(hDataKey);	hDataKey = NULL;
305 
306 
307 	/*
308 	 * Following calls create the entries for the filter in
309 	 * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\Filters
310 	 */
311 	lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows CE Services\\Filters"),
312 				0, KEY_ALL_ACCESS, &hKey);
313 	if (lRet != ERROR_SUCCESS)
314 		return _signalRegError(lRet, hKey, hDataKey);
315 
316 	// Add in defaults for import and export
317 	_snprintf(sTemp, _MAX_PATH +1, "%c%s\0", '.', CXMergeFilter::m_pszPSWExportExt);
318 	lRet = ::RegCreateKeyEx(hKey, _T(sTemp), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
319 	if (lRet != ERROR_SUCCESS)
320 		return _signalRegError(lRet, hKey, hDataKey);
321 
322 	lRet = ::RegSetValueEx(hDataKey, _T("DefaultImport"), 0, REG_SZ,
323 							(LPBYTE)CXMergeFilter::m_pszPSWImportCLSID,
324 							(::_tcslen(CXMergeFilter::m_pszPSWImportDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
325 	if (lRet != ERROR_SUCCESS)
326 		return _signalRegError(lRet, hKey, hDataKey);
327 
328 
329 	lRet = ::RegSetValueEx(hDataKey, _T("DefaultExport"), 0, REG_SZ, (LPBYTE)_T("Binary Copy"),
330 							(::_tcslen(_T("Binary Copy")) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
331 	if (lRet != ERROR_SUCCESS)
332 		return _signalRegError(lRet, hKey, hDataKey);
333 
334 	::RegCloseKey(hDataKey);
335 
336 	// Update registered filters
337 	_snprintf(sTemp, _MAX_PATH + 1, "%c%s\\InstalledFilters\0", '.', CXMergeFilter::m_pszPSWExportExt);
338 	lRet = ::RegCreateKeyEx(hKey, _T(sTemp),
339 				0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
340 	if (lRet != ERROR_SUCCESS)
341 		return _signalRegError(lRet, hKey, hDataKey);
342 
343 
344 	lRet = ::RegSetValueEx(hDataKey, CXMergeFilter::m_pszPSWImportCLSID, 0, REG_SZ, (LPBYTE)_T(""), (1 * sizeof(TCHAR)));
345 	if (lRet != ERROR_SUCCESS)
346 		return _signalRegError(lRet, hKey, hDataKey);
347 
348 	::RegCloseKey(hKey);		hKey = NULL;
349 	::RegCloseKey(hDataKey);	hDataKey = NULL;
350 
351 
352 
353 	/*
354 	 * Following calls create the HKEY_CLASSES_ROOT\CLSID entry for the Calc export filter.
355 	 *
356 	 * Note that import are export are relative to the WinCE device, so files are
357 	 * exported to the desktop format.
358 	 */
359 
360 	// Get a handle to the CLSID key
361 	lRet = ::RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID"), 0, KEY_ALL_ACCESS, &hKey);
362 	if (lRet != ERROR_SUCCESS)
363 		return _signalRegError(lRet, hKey, hDataKey);
364 
365 	// Create the CLSID key for the XMerge Filter
366 	lRet = ::RegCreateKeyEx(hKey, CXMergeFilter::m_pszPXLExportCLSID, 0, _T(""),
367 								0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
368 	if (lRet != ERROR_SUCCESS)
369 		return _signalRegError(lRet, hKey, hDataKey);
370 
371 	lRet = ::RegSetValueEx(hKey, _T(""), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPXLExportShortDesc,
372 				(::_tcslen(CXMergeFilter::m_pszPXLExportShortDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
373 	if (lRet != ERROR_SUCCESS)
374 		return _signalRegError(lRet, hKey, hDataKey);
375 
376 
377 	// Create the DefaultIcon key.  For the moment, use one of the Async supplied ones
378 	lRet = ::RegCreateKeyEx(hKey, _T("DefaultIcon"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
379 	if (lRet != ERROR_SUCCESS)
380 		return _signalRegError(lRet, hKey, hDataKey);
381 
382 	lRet = ::RegSetValueEx(hDataKey, NULL, 0, REG_SZ, (LPBYTE)_T("C:\\Program Files\\Microsoft ActiveSync\\pwdcnv.dll,0"),
383 							(::_tcslen(_T("C:\\Program Files\\Microsoft ActiveSync\\pwdcnv.dll,0"))
384 							   * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
385 	if (lRet != ERROR_SUCCESS)
386 		return _signalRegError(lRet, hKey, hDataKey);
387 	::RegCloseKey(hDataKey);  hDataKey = NULL;
388 
389 
390 	// Create the InprocServer32 key
391 	lRet = ::RegCreateKeyEx(hKey, _T("InProcServer32"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
392 	if (lRet != ERROR_SUCCESS)
393 		return _signalRegError(lRet, hKey, hDataKey);
394 
395 	lRet = ::RegSetValueEx(hDataKey, _T("ThreadingModel"), 0, REG_SZ, (LPBYTE)_T("Apartment"), 10);
396 	if (lRet != ERROR_SUCCESS)
397 		return _signalRegError(lRet, hKey, hDataKey);
398 
399 
400 	// Create the key for the DLL file.  First find the filename of the dll
401 	if (!::GetModuleFileName((HMODULE)_Module.m_hInst, sTemp, (_MAX_PATH + 1)))
402 	{
403 		lRet = ::GetLastError();
404 		if (lRet != ERROR_SUCCESS)
405 			return _signalRegError(lRet, hKey, hDataKey);
406 	}
407 
408 
409 	lRet = ::RegSetValueEx(hDataKey, NULL, 0, REG_SZ, (LPBYTE)sTemp,
410 				(::_tcslen(sTemp) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
411 	if (lRet != ERROR_SUCCESS)
412 		return _signalRegError(lRet, hKey, hDataKey);
413 	::RegCloseKey(hDataKey);	hDataKey = NULL;
414 
415 
416 	// Setup the PegasusFilter key values
417 	lRet = ::RegCreateKeyEx(hKey, _T("PegasusFilter"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
418 	if (lRet != ERROR_SUCCESS)
419 		return _signalRegError(lRet, hKey, hDataKey);
420 
421 		lRet = ::RegSetValueEx(hDataKey, _T("Description"), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPXLExportDesc,
422 				(::_tcslen(CXMergeFilter::m_pszPXLExportDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
423 	if (lRet != ERROR_SUCCESS)
424 		return _signalRegError(lRet, hKey, hDataKey);
425 
426 
427 	lRet = ::RegSetValueEx(hDataKey, _T("Export"), 0, REG_SZ, (LPBYTE)_T(""), (1 * sizeof(TCHAR)));
428 	if (lRet != ERROR_SUCCESS)
429 		return _signalRegError(lRet, hKey, hDataKey);
430 
431 
432 	lRet = ::RegSetValueEx(hDataKey, _T("NewExtension"), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPXLExportExt,
433 				(::_tcslen(CXMergeFilter::m_pszPXLExportExt) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
434 	if (lRet != ERROR_SUCCESS)
435 		return _signalRegError(lRet, hKey, hDataKey);
436 
437 
438 	::RegCloseKey(hKey);		hKey = NULL;
439 	::RegCloseKey(hDataKey);	hDataKey = NULL;
440 
441 
442 
443 
444 	/*
445 	 * Following calls create the entries for the filter in
446 	 * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\Filters
447 	 */
448 
449 	lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows CE Services\\Filters"),
450 				0, KEY_ALL_ACCESS, &hKey);
451 	if (lRet != ERROR_SUCCESS)
452 		return _signalRegError(lRet, hKey, hDataKey);
453 
454 	_snprintf(sTemp, _MAX_PATH + 1, "%c%s\\InstalledFilters\0", '.', CXMergeFilter::m_pszPXLImportExt);
455 	lRet = ::RegCreateKeyEx(hKey, _T(sTemp),
456 				0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
457 	if (lRet != ERROR_SUCCESS)
458 		return _signalRegError(lRet, hKey, hDataKey);
459 
460 	lRet = ::RegSetValueEx(hDataKey, CXMergeFilter::m_pszPXLExportCLSID, 0, REG_SZ, (LPBYTE)_T(""), (1 * sizeof(TCHAR)));
461 	if (lRet != ERROR_SUCCESS)
462 		return _signalRegError(lRet, hKey, hDataKey);
463 
464 	::RegCloseKey(hKey);		hKey = NULL;
465 	::RegCloseKey(hDataKey);	hDataKey = NULL;
466 
467 
468 
469 	/*
470 	 * Following calls create the HKEY_CLASSES_ROOT\CLSID entry for the Calc import filter.
471 	 *
472 	 * Note that import are export are relative to the WinCE device, so files are
473 	 * exported to the desktop format.
474 	 */
475 	// Get a handle to the CLSID key
476 	lRet = ::RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID"), 0, KEY_ALL_ACCESS, &hKey);
477 	if (lRet != ERROR_SUCCESS)
478 		return _signalRegError(lRet, hKey, hDataKey);
479 
480 
481 	// Create the CLSID key for the XMergeFilter
482 	lRet = ::RegCreateKeyEx(hKey, CXMergeFilter::m_pszPXLImportCLSID, 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
483 	if (lRet != ERROR_SUCCESS)
484 		return _signalRegError(lRet, hKey, hDataKey);
485 
486 	lRet = ::RegSetValueEx(hKey, _T(""), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPXLImportShortDesc,
487 				(::_tcslen(CXMergeFilter::m_pszPXLImportShortDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
488 	if (lRet != ERROR_SUCCESS)
489 		return _signalRegError(lRet, hKey, hDataKey);
490 
491 	// Create the DefaultIcon key.  For the moment, use one of the Async supplied ones
492 	lRet = ::RegCreateKeyEx(hKey, _T("DefaultIcon"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
493 	if (lRet != ERROR_SUCCESS)
494 		return _signalRegError(lRet, hKey, hDataKey);
495 
496 	lRet = ::RegSetValueEx(hDataKey, NULL, 0, REG_SZ, (LPBYTE)_T("C:\\Program Files\\Microsoft ActiveSync\\pwdcnv.dll,0"),
497 							(::_tcslen(_T("C:\\Program Files\\Microsoft ActiveSync\\pwdcnv.dll,0"))
498 							   * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
499 	if (lRet != ERROR_SUCCESS)
500 		return _signalRegError(lRet, hKey, hDataKey);
501 	::RegCloseKey(hDataKey);  hDataKey = NULL;
502 
503 
504 	// Create the InprocServer32 key
505 	lRet = ::RegCreateKeyEx(hKey, _T("InProcServer32"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
506 	if (lRet != ERROR_SUCCESS)
507 		return _signalRegError(lRet, hKey, hDataKey);
508 
509 	lRet = ::RegSetValueEx(hDataKey, _T("ThreadingModel"), 0, REG_SZ, (LPBYTE)_T("Apartment"), 10);
510 	if (lRet != ERROR_SUCCESS)
511 		return _signalRegError(lRet, hKey, hDataKey);
512 
513 
514 	// Create the key for the DLL file.  First find the filename of the dll
515 	if (!::GetModuleFileName((HMODULE)_Module.m_hInst, sTemp, (_MAX_PATH + 1)))
516 	{
517 		lRet = ::GetLastError();
518 		if (lRet != ERROR_SUCCESS)
519 			return _signalRegError(lRet, hKey, hDataKey);
520 	}
521 
522 
523 	lRet = ::RegSetValueEx(hDataKey, NULL, 0, REG_SZ, (LPBYTE)sTemp,
524 				(::_tcslen(sTemp) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
525 	if (lRet != ERROR_SUCCESS)
526 		return _signalRegError(lRet, hKey, hDataKey);
527 	::RegCloseKey(hDataKey);	hDataKey = NULL;
528 
529 
530 	// Setup the PegasusFilter key values
531 	lRet = ::RegCreateKeyEx(hKey, _T("PegasusFilter"), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
532 	if (lRet != ERROR_SUCCESS)
533 		return _signalRegError(lRet, hKey, hDataKey);
534 
535 		lRet = ::RegSetValueEx(hDataKey, _T("Description"), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPXLImportDesc,
536 				(::_tcslen(CXMergeFilter::m_pszPXLImportDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
537 	if (lRet != ERROR_SUCCESS)
538 		return _signalRegError(lRet, hKey, hDataKey);
539 
540 
541 	lRet = ::RegSetValueEx(hDataKey, _T("Import"), 0, REG_SZ, (LPBYTE)_T(""), (1 * sizeof(TCHAR)));
542 	if (lRet != ERROR_SUCCESS)
543 		return _signalRegError(lRet, hKey, hDataKey);
544 
545 
546 	lRet = ::RegSetValueEx(hDataKey, _T("NewExtension"), 0, REG_SZ, (LPBYTE)CXMergeFilter::m_pszPXLImportExt,
547 				(::_tcslen(CXMergeFilter::m_pszPXLImportExt) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
548 	if (lRet != ERROR_SUCCESS)
549 		return _signalRegError(lRet, hKey, hDataKey);
550 
551 
552 	::RegCloseKey(hKey);		hKey = NULL;
553 	::RegCloseKey(hDataKey);	hDataKey = NULL;
554 
555 
556 
557 	/*
558 	 * Following calls create the entries for the filter in
559 	 * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\Filters
560 	 */
561 	lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows CE Services\\Filters"),
562 				0, KEY_ALL_ACCESS, &hKey);
563 	if (lRet != ERROR_SUCCESS)
564 		return _signalRegError(lRet, hKey, hDataKey);
565 
566 	// Add in defaults for import and export
567 	_snprintf(sTemp, _MAX_PATH +1, "%c%s\0", '.', CXMergeFilter::m_pszPXLExportExt);
568 	lRet = ::RegCreateKeyEx(hKey, _T(sTemp), 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
569 	if (lRet != ERROR_SUCCESS)
570 		return _signalRegError(lRet, hKey, hDataKey);
571 
572 	lRet = ::RegSetValueEx(hDataKey, _T("DefaultImport"), 0, REG_SZ,
573 							(LPBYTE)CXMergeFilter::m_pszPXLImportCLSID,
574 							(::_tcslen(CXMergeFilter::m_pszPSWImportDesc) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
575 	if (lRet != ERROR_SUCCESS)
576 		return _signalRegError(lRet, hKey, hDataKey);
577 
578 
579 	lRet = ::RegSetValueEx(hDataKey, _T("DefaultExport"), 0, REG_SZ, (LPBYTE)_T("Binary Copy"),
580 							(::_tcslen(_T("Binary Copy")) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
581 	if (lRet != ERROR_SUCCESS)
582 		return _signalRegError(lRet, hKey, hDataKey);
583 
584 	::RegCloseKey(hDataKey);
585 
586 	// Update registered filters
587 
588 
589 	_snprintf(sTemp, _MAX_PATH + 1, "%c%s\\InstalledFilters\0", '.', CXMergeFilter::m_pszPXLExportExt);
590 	lRet = ::RegCreateKeyEx(hKey, _T(sTemp),
591 				0, _T(""), 0, KEY_ALL_ACCESS, NULL, &hDataKey, NULL);
592 	if (lRet != ERROR_SUCCESS)
593 		return _signalRegError(lRet, hKey, hDataKey);
594 
595 	lRet = ::RegSetValueEx(hDataKey, CXMergeFilter::m_pszPXLImportCLSID, 0, REG_SZ, (LPBYTE)_T(""), (1 * sizeof(TCHAR)));
596 	if (lRet != ERROR_SUCCESS)
597 		return _signalRegError(lRet, hKey, hDataKey);
598 
599 	::RegCloseKey(hKey);		hKey = NULL;
600 	::RegCloseKey(hDataKey);	hDataKey = NULL;
601 
602 
603 
604 	return HRESULT_FROM_WIN32(lRet);
605 }
606 
607 
DllUnregisterServer()608 STDAPI DllUnregisterServer()
609 {
610 	long lRet = 0;
611 	HKEY hKey = NULL;
612 	HKEY hDataKey = NULL;
613 
614 	TCHAR szClassName[_MAX_PATH] = "\0";
615 	TCHAR szKeyName[_MAX_PATH]   = "\0";
616 	DWORD dwClassName            = _MAX_PATH;
617 	DWORD dwKeyName              = _MAX_PATH;
618 
619 	/*
620 	 * Remove HKEY_CLASS_ROOT\CLSID\{XXX} entry for the export and import filters
621 	 *
622 	 * Windows 95/98/Me allow one step deletion of a key and all subkeys.
623 	 * Windows NT/2000/XP do not so the subkeys must be deleted individually.
624 	 */
625 	lRet = ::RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID"), 0, KEY_ALL_ACCESS, &hKey);
626 	if (lRet != ERROR_SUCCESS)
627 		return _signalRegError(lRet, hKey, hDataKey);
628 
629 
630 	// First up, the Writer export filter
631 	lRet = ::RegOpenKeyEx(hKey, CXMergeFilter::m_pszPSWExportCLSID, 0, KEY_ALL_ACCESS, &hDataKey);
632 	if (lRet != ERROR_SUCCESS)
633 		return _signalRegError(lRet, hKey, hDataKey);
634 
635 
636 	while ((lRet = ::RegEnumKeyEx(hDataKey, 0, szKeyName, &dwKeyName, 0, szClassName, &dwClassName, NULL))
637 				!= ERROR_NO_MORE_ITEMS)
638 	{
639 		lRet = ::RegDeleteKey(hDataKey, szKeyName);
640 
641 		::lstrcpy(szKeyName, "\0");
642 		::lstrcpy(szClassName, "\0");
643 
644 		dwClassName = _MAX_PATH;
645 		dwKeyName   = _MAX_PATH;
646 	}
647 
648 	::RegCloseKey(hDataKey);  hDataKey = NULL;
649 
650 	lRet = ::RegDeleteKey(hKey, CXMergeFilter::m_pszPSWExportCLSID);
651 	if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND)
652 		return _signalRegError(lRet, hKey, hDataKey);
653 
654 
655 
656 	// Next, the Writer import filter
657 	lRet = ::RegOpenKeyEx(hKey, CXMergeFilter::m_pszPSWImportCLSID, 0, KEY_ALL_ACCESS, &hDataKey);
658 	if (lRet != ERROR_SUCCESS)
659 		return _signalRegError(lRet, hKey, hDataKey);
660 
661 
662 	while ((lRet = ::RegEnumKeyEx(hDataKey, 0, szKeyName, &dwKeyName, 0, szClassName, &dwClassName, NULL))
663 				!= ERROR_NO_MORE_ITEMS)
664 	{
665 		lRet = ::RegDeleteKey(hDataKey, szKeyName);
666 
667 		::lstrcpy(szKeyName, "\0");
668 		::lstrcpy(szClassName, "\0");
669 
670 		dwClassName = _MAX_PATH;
671 		dwKeyName   = _MAX_PATH;
672 	}
673 
674 	::RegCloseKey(hDataKey);  hDataKey = NULL;
675 
676 	lRet = ::RegDeleteKey(hKey, CXMergeFilter::m_pszPSWImportCLSID);
677 	if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND)
678 		return _signalRegError(lRet, hKey, hDataKey);
679 
680 
681 	// Next up, the Calc export filter
682 	lRet = ::RegOpenKeyEx(hKey, CXMergeFilter::m_pszPXLExportCLSID, 0, KEY_ALL_ACCESS, &hDataKey);
683 	if (lRet != ERROR_SUCCESS)
684 		return _signalRegError(lRet, hKey, hDataKey);
685 
686 
687 	while ((lRet = ::RegEnumKeyEx(hDataKey, 0, szKeyName, &dwKeyName, 0, szClassName, &dwClassName, NULL))
688 				!= ERROR_NO_MORE_ITEMS)
689 	{
690 		lRet = ::RegDeleteKey(hDataKey, szKeyName);
691 
692 		::lstrcpy(szKeyName, "\0");
693 		::lstrcpy(szClassName, "\0");
694 
695 		dwClassName = _MAX_PATH;
696 		dwKeyName   = _MAX_PATH;
697 	}
698 
699 	::RegCloseKey(hDataKey);  hDataKey = NULL;
700 
701 	lRet = ::RegDeleteKey(hKey, CXMergeFilter::m_pszPXLExportCLSID);
702 	if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND)
703 		return _signalRegError(lRet, hKey, hDataKey);
704 
705 
706 	// Next, the Calc import filter
707 	lRet = ::RegOpenKeyEx(hKey, CXMergeFilter::m_pszPXLImportCLSID, 0, KEY_ALL_ACCESS, &hDataKey);
708 	if (lRet != ERROR_SUCCESS)
709 		return _signalRegError(lRet, hKey, hDataKey);
710 
711 
712 	while ((lRet = ::RegEnumKeyEx(hDataKey, 0, szKeyName, &dwKeyName, 0, szClassName, &dwClassName, NULL))
713 				!= ERROR_NO_MORE_ITEMS)
714 	{
715 		lRet = ::RegDeleteKey(hDataKey, szKeyName);
716 
717 		::lstrcpy(szKeyName, "\0");
718 		::lstrcpy(szClassName, "\0");
719 
720 		dwClassName = _MAX_PATH;
721 		dwKeyName   = _MAX_PATH;
722 	}
723 
724 	::RegCloseKey(hDataKey);  hDataKey = NULL;
725 
726 	lRet = ::RegDeleteKey(hKey, CXMergeFilter::m_pszPXLImportCLSID);
727 	if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND)
728 		return _signalRegError(lRet, hKey, hDataKey);
729 
730 	::RegCloseKey(hKey);  hKey = NULL;
731 
732 
733 
734 	/*
735 	 * Remove the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\Filters
736 	 */
737 	lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows CE Services\\Filters"),
738 							0, KEY_ALL_ACCESS, &hKey);
739 	if (lRet != ERROR_SUCCESS)
740 		return _signalRegError(lRet, hKey, hDataKey);
741 
742 
743 	// Remove the Writer export filter from the Writer import file extension subkey.
744 	_snprintf(szKeyName, _MAX_PATH, ".%s\\InstalledFilters", CXMergeFilter::m_pszPSWImportExt);
745 	lRet = ::RegOpenKeyEx(hKey, _T(szKeyName), 0, KEY_ALL_ACCESS, &hDataKey);
746 	if (lRet != ERROR_SUCCESS)
747 		return _signalRegError(lRet, hKey, hDataKey);
748 
749 	lRet = ::RegDeleteValue(hDataKey, CXMergeFilter::m_pszPSWExportCLSID);
750 	if (lRet != ERROR_SUCCESS)
751 		return _signalRegError(lRet, hKey, hDataKey);
752 
753 	::lstrcpyn(szKeyName, "\0", _MAX_PATH);
754 	::RegCloseKey(hDataKey);	hDataKey = NULL;
755 
756 
757 	// Remove the Writer import filter from the Writer export file extension subkey.
758 	_snprintf(szKeyName, _MAX_PATH, ".%s\\InstalledFilters", CXMergeFilter::m_pszPSWExportExt);
759 	lRet = ::RegOpenKeyEx(hKey, _T(szKeyName), 0, KEY_ALL_ACCESS, &hDataKey);
760 	if (lRet != ERROR_SUCCESS)
761 		return _signalRegError(lRet, hKey, hDataKey);
762 
763 	lRet = ::RegDeleteValue(hDataKey, CXMergeFilter::m_pszPSWImportCLSID);
764 	if (lRet != ERROR_SUCCESS)
765 		return _signalRegError(lRet, hKey, hDataKey);
766 
767 	::lstrcpyn(szKeyName, "\0", _MAX_PATH);
768 	::RegCloseKey(hDataKey);	hDataKey = NULL;
769 
770 
771 	// Make Binary Copy the default for Writer export file extension subkey DefaultImport
772 	_snprintf(szKeyName, _MAX_PATH, ".%s\0", CXMergeFilter::m_pszPSWExportExt);
773 	lRet = ::RegOpenKeyEx(hKey, _T(szKeyName), 0, KEY_ALL_ACCESS, &hDataKey);
774 	if (lRet != ERROR_SUCCESS)
775 		return _signalRegError(lRet, hKey, hDataKey);
776 
777 	lRet = ::RegSetValueEx(hDataKey, _T("DefaultImport"), 0, REG_SZ, (LPBYTE)_T("Binary Copy"),
778 							(::_tcslen(_T("Binary Copy")) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
779 	if (lRet != ERROR_SUCCESS)
780 		return _signalRegError(lRet, hKey, hDataKey);
781 
782 	::lstrcpyn(szKeyName, "\0", _MAX_PATH);
783 	::RegCloseKey(hDataKey);	hDataKey = NULL;
784 
785 
786 	// Remove the Calc export filter from the Calc import file extension subkey.
787 	_snprintf(szKeyName, _MAX_PATH, ".%s\\InstalledFilters", CXMergeFilter::m_pszPXLImportExt);
788 	lRet = ::RegOpenKeyEx(hKey, _T(szKeyName), 0, KEY_ALL_ACCESS, &hDataKey);
789 	if (lRet != ERROR_SUCCESS)
790 		return _signalRegError(lRet, hKey, hDataKey);
791 
792 	lRet = ::RegDeleteValue(hDataKey, CXMergeFilter::m_pszPXLExportCLSID);
793 	if (lRet != ERROR_SUCCESS)
794 		return _signalRegError(lRet, hKey, hDataKey);
795 
796 	::lstrcpyn(szKeyName, "\0", _MAX_PATH);
797 	::RegCloseKey(hDataKey);	hDataKey = NULL;
798 
799 	// Remove the Calc import filter from the Calc export file extension subkey.
800 	_snprintf(szKeyName, _MAX_PATH, ".%s\\InstalledFilters", CXMergeFilter::m_pszPXLExportExt);
801 	lRet = ::RegOpenKeyEx(hKey, _T(szKeyName), 0, KEY_ALL_ACCESS, &hDataKey);
802 	if (lRet != ERROR_SUCCESS)
803 		return _signalRegError(lRet, hKey, hDataKey);
804 
805 	lRet = ::RegDeleteValue(hDataKey, CXMergeFilter::m_pszPXLImportCLSID);
806 	if (lRet != ERROR_SUCCESS)
807 		return _signalRegError(lRet, hKey, hDataKey);
808 
809 	::lstrcpyn(szKeyName, "\0", _MAX_PATH);
810 	::RegCloseKey(hDataKey);	hDataKey = NULL;
811 
812 
813 	// Make Binary Copy the default for Calc export file extension subkey DefaultImport
814 	_snprintf(szKeyName, _MAX_PATH, ".%s\0", CXMergeFilter::m_pszPXLExportExt);
815 	lRet = ::RegOpenKeyEx(hKey, _T(szKeyName), 0, KEY_ALL_ACCESS, &hDataKey);
816 	if (lRet != ERROR_SUCCESS)
817 		return _signalRegError(lRet, hKey, hDataKey);
818 
819 	lRet = ::RegSetValueEx(hDataKey, _T("DefaultImport"), 0, REG_SZ, (LPBYTE)_T("Binary Copy"),
820 							(::_tcslen(_T("Binary Copy")) * sizeof(TCHAR) + (1 * sizeof(TCHAR))));
821 	if (lRet != ERROR_SUCCESS)
822 		return _signalRegError(lRet, hKey, hDataKey);
823 
824 	::lstrcpyn(szKeyName, "\0", _MAX_PATH);
825 	::RegCloseKey(hDataKey);	hDataKey = NULL;
826 
827 
828 
829 	::RegCloseKey(hKey);		hKey	 = NULL;
830 
831 	return HRESULT_FROM_WIN32(lRet);
832 }
833 
834 
835 //////////////////////////////////////////////////////////////////////
836 // CXMergeSyncModule methods
837 //////////////////////////////////////////////////////////////////////
CXMergeSyncModule()838 CXMergeSyncModule::CXMergeSyncModule ()
839 {
840 }
841 
~CXMergeSyncModule()842 CXMergeSyncModule::~CXMergeSyncModule ()
843 {
844 }
845 
LockServer(BOOL fLock)846 long CXMergeSyncModule::LockServer(BOOL fLock)
847 {
848 	if(fLock)
849 		return ::InterlockedIncrement(&m_lLocks);
850 	else
851 		return ::InterlockedDecrement(&m_lLocks);
852 }
853 
GetLockCount()854 long CXMergeSyncModule::GetLockCount()
855 {
856 	return m_lLocks + m_lObjs;
857 }
858 
859