xref: /trunk/main/xmerge/source/activesync/XMergeSync.cpp (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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