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