| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| // XMergeFilter.cpp: implementation of the CXMergeFilter class. |
| // |
| ////////////////////////////////////////////////////////////////////// |
| |
| |
| #include "stdafx.h" |
| |
| #include "XMergeFilter.h" |
| |
| #include <string> |
| |
| |
| #define ERR_NOJAVA 1 |
| #define ERR_BADCLASSPATH 2 |
| #define ERR_INITJAVA 3 |
| |
| |
| const LPTSTR CXMergeFilter::m_pszPSWExportCLSID = _T("{BDD611C3-7BAB-460F-8711-5B9AC9EF6020}"); |
| const LPTSTR CXMergeFilter::m_pszPSWExportExt = _T("sxw"); |
| const LPTSTR CXMergeFilter::m_pszPSWExportDesc = _T("OpenOffice.org XML Writer Document"); |
| const LPTSTR CXMergeFilter::m_pszPSWExportShortDesc = _T("OpenOffice.org XML Writer"); |
| |
| const LPTSTR CXMergeFilter::m_pszPSWImportCLSID = _T("{CB43F086-838D-4FA4-B5F6-3406B9A57439}"); |
| const LPTSTR CXMergeFilter::m_pszPSWImportExt = _T("psw"); |
| const LPTSTR CXMergeFilter::m_pszPSWImportDesc = _T("Pocket Word Document - Pocket PC"); |
| const LPTSTR CXMergeFilter::m_pszPSWImportShortDesc = _T("Pocket Word"); |
| |
| const LPTSTR CXMergeFilter::m_pszPXLExportCLSID = _T("{C6AB3E74-9F4F-4370-8120-A8A6FABB7A7C}"); |
| const LPTSTR CXMergeFilter::m_pszPXLExportExt = _T("sxc"); |
| const LPTSTR CXMergeFilter::m_pszPXLExportDesc = _T("OpenOffice.org XML Calc Document"); |
| const LPTSTR CXMergeFilter::m_pszPXLExportShortDesc = _T("OpenOffice.org XML Calc"); |
| |
| const LPTSTR CXMergeFilter::m_pszPXLImportCLSID = _T("{43887C67-4D5D-4127-BAAC-87A288494C7C}"); |
| const LPTSTR CXMergeFilter::m_pszPXLImportExt = _T("pxl"); |
| const LPTSTR CXMergeFilter::m_pszPXLImportDesc = _T("Pocket Excel Document - Pocket PC"); |
| const LPTSTR CXMergeFilter::m_pszPXLImportShortDesc = _T("Pocket Excel"); |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| // Construction/Destruction |
| ////////////////////////////////////////////////////////////////////// |
| |
| CXMergeFilter::CXMergeFilter() : m_cRef(1) |
| { |
| m_bHaveExcel = FALSE; |
| m_bHaveWord = FALSE; |
| |
| m_szClasspath = NULL; |
| m_szJavaBaseDir = NULL; |
| } |
| |
| CXMergeFilter::~CXMergeFilter() |
| { |
| if (m_szClasspath != NULL) |
| { |
| delete m_szClasspath; |
| } |
| |
| if (m_szJavaBaseDir != NULL) |
| { |
| delete m_szJavaBaseDir; |
| } |
| |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| // IUnknown Methods |
| ////////////////////////////////////////////////////////////////////// |
| |
| STDMETHODIMP CXMergeFilter::QueryInterface(REFIID riid, void **ppvObject) |
| { |
| if(ppvObject == NULL) |
| return E_INVALIDARG; |
| |
| if (::IsEqualIID(riid, IID_IUnknown)) |
| { |
| *ppvObject = static_cast<IUnknown *>(this); |
| } |
| else if (::IsEqualIID(riid, IID_ICeFileFilter)) |
| { |
| *ppvObject = static_cast<ICeFileFilter *>(this); |
| } |
| else |
| { |
| *ppvObject = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| reinterpret_cast<IUnknown *>(*ppvObject)->AddRef(); |
| return S_OK; |
| } |
| |
| |
| STDMETHODIMP_(ULONG) CXMergeFilter::AddRef() |
| { |
| return ::InterlockedIncrement(&m_cRef); |
| } |
| |
| |
| STDMETHODIMP_(ULONG) CXMergeFilter::Release() |
| { |
| if(::InterlockedDecrement(&m_cRef) == 0) |
| { |
| delete this; |
| return 0; |
| } |
| return m_cRef; |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| // ICeFileFilter |
| ////////////////////////////////////////////////////////////////////// |
| |
| STDMETHODIMP CXMergeFilter::FilterOptions(HWND hwndParent) |
| { |
| // We don't currently allow any options |
| return HRESULT_FROM_WIN32(NOERROR); |
| } |
| |
| STDMETHODIMP CXMergeFilter::FormatMessage(DWORD dwFlags, DWORD dwMessageId, |
| DWORD dwLanguageId, LPTSTR lpBuffer, DWORD nSize, |
| va_list *Arguments, DWORD *pcb) |
| { |
| TCHAR errMsg[1024]; |
| |
| HKEY hKey = NULL; |
| DWORD dwSize = 1024; |
| |
| |
| long lRet = 0; |
| |
| // Attempt to find the messages in the registry |
| lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Sun Microsystems\\StarOffice\\XMergeSync\\Messages\\Error"), |
| 0, KEY_READ, &hKey); |
| if (lRet != ERROR_SUCCESS) |
| { |
| // Try the user's portion of the registry |
| lRet = ::RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Sun Microsystems\\StarOffice\\XMergeSync\\Messages\\Error"), |
| 0, KEY_READ, &hKey); |
| if (lRet != ERROR_SUCCESS) |
| { |
| hKey = NULL; |
| } |
| } |
| |
| |
| switch(dwMessageId) |
| { |
| case ERR_NOJAVA: |
| lRet = ::RegQueryValueEx(hKey, _T("Java"), 0, NULL, (LPBYTE)errMsg, &dwSize); |
| if (lRet != ERROR_SUCCESS) |
| { |
| lstrcpy(errMsg, "Unable to locate Java 1.4/1.5 installation."); |
| } |
| break; |
| |
| case ERR_BADCLASSPATH: |
| lRet = ::RegQueryValueEx(hKey, _T("Classpath"), 0, NULL, (LPBYTE)errMsg, &dwSize); |
| if (lRet != ERROR_SUCCESS) |
| { |
| lstrcpy(errMsg, "Unable to locate XMerge Jar files."); |
| } |
| break; |
| |
| case ERR_INITJAVA: |
| lRet = ::RegQueryValueEx(hKey, _T("JavaInit"), 0, NULL, (LPBYTE)errMsg, &dwSize); |
| if (lRet != ERROR_SUCCESS) |
| { |
| lstrcpy(errMsg, "Error initialising the Java Runtime Environment."); |
| } |
| break; |
| } |
| |
| char* buf = (char*)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, (lstrlen(errMsg) + 1) * sizeof(TCHAR)); |
| lstrcpyn(buf, errMsg, lstrlen(errMsg)); |
| |
| *(char**)lpBuffer = buf; |
| *pcb = strlen(errMsg); |
| |
| return HRESULT_FROM_WIN32(NOERROR); |
| } |
| |
| |
| STDMETHODIMP CXMergeFilter::NextConvertFile(int nConversion, CFF_CONVERTINFO *pci, |
| CFF_SOURCEFILE *psf, CFF_DESTINATIONFILE *pdf, |
| volatile BOOL *pbCancel, CF_ERROR *perr) |
| { |
| std::string appArgs; |
| std::string appName; |
| |
| STARTUPINFO si; |
| PROCESS_INFORMATION pi; |
| |
| ZeroMemory( &si, sizeof(si) ); |
| ZeroMemory( &pi, sizeof(pi) ); |
| |
| si.cb = sizeof(si); |
| |
| |
| /* |
| * First step: Locate Java and establish the classpath. If these can't |
| * be done succesfully, then avoid all further processing. |
| */ |
| |
| // Locate Java Home if it hasn't already been done. |
| if (m_szJavaBaseDir == NULL) |
| { |
| m_szJavaBaseDir = GetJavaBaseDir(); |
| |
| if (m_szJavaBaseDir == NULL) |
| { |
| *perr = ERR_NOJAVA; |
| return HRESULT_FROM_WIN32(E_FAIL); |
| } |
| } |
| |
| // Get the Apache OpenOffice class directory |
| if (m_szClasspath == NULL) |
| { |
| m_szClasspath = GetXMergeClassPath(); |
| |
| if (m_szClasspath == NULL) |
| { |
| *perr = ERR_BADCLASSPATH; |
| return HRESULT_FROM_WIN32(E_FAIL); |
| } |
| } |
| |
| |
| /* |
| * Second step: Check the files we're going to process. If we don't have |
| * an XMerge plugin for the file then we can't convert. |
| */ |
| if ((!lstrcmp(psf->szExtension, "sxw") || !lstrcmp(psf->szExtension, "psw")) |
| && !m_bHaveWord) |
| { |
| *perr = ERR_BADCLASSPATH; |
| return HRESULT_FROM_WIN32(E_FAIL); |
| } |
| else if ((!lstrcmp(psf->szExtension, "sxc") || !lstrcmp(psf->szExtension, "pxl")) |
| && !m_bHaveExcel) |
| { |
| *perr = ERR_BADCLASSPATH; |
| return HRESULT_FROM_WIN32(E_FAIL); |
| } |
| |
| |
| /* |
| * Third step: Locate the Java executable and build and execute the command |
| * line to carry out the conversion. |
| */ |
| |
| // Find the Java executable and make sure it exists |
| appName += m_szJavaBaseDir; |
| appName += "\\bin\\javaw.exe"; |
| |
| if (GetFileAttributes(appName.c_str()) == INVALID_FILE_SIZE) |
| { |
| *perr = ERR_NOJAVA; |
| return HRESULT_FROM_WIN32(E_FAIL); |
| } |
| |
| // Wrap the executable path in quotes in case of spaces |
| appName.insert(0, "\""); |
| appName.append("\""); |
| |
| |
| |
| // Need to build the entire command line for calling out to Java |
| appArgs = appName + " -Djava.class.path="; |
| appArgs += m_szClasspath; |
| appArgs += " org.openoffice.xmerge.util.ActiveSyncDriver "; |
| |
| if (!lstrcmp(psf->szExtension, "sxw")) |
| { |
| appArgs += "staroffice/sxw "; |
| appArgs += "application/x-pocket-word "; |
| } |
| else if(!lstrcmp(psf->szExtension, "psw")) |
| { |
| appArgs += "application/x-pocket-word "; |
| appArgs += "staroffice/sxw "; |
| } |
| else if(!lstrcmp(psf->szExtension, "sxc")) |
| { |
| appArgs += "staroffice/sxc "; |
| appArgs += "application/x-pocket-excel "; |
| } |
| else if(!lstrcmp(psf->szExtension, "pxl")) |
| { |
| appArgs += "application/x-pocket-excel "; |
| appArgs += "staroffice/sxc "; |
| } |
| |
| |
| // ActiveSync sometimes gives out long file names, especially when automatically syncing |
| appArgs += "\""; |
| appArgs += psf->szFullpath; |
| appArgs += "\" \""; |
| appArgs += pdf->szFullpath; |
| appArgs += "\""; |
| |
| if(!CreateProcess(NULL, |
| (char*)appArgs.c_str(), |
| NULL, // No Process Attributes |
| NULL, // No Thread Attributes |
| FALSE, // Don't want this process getting handles |
| CREATE_NO_WINDOW, // No console |
| NULL, // No special environment |
| NULL, // Current Working Directory is okay |
| &si, |
| &pi)) |
| { |
| *perr = ERR_INITJAVA; |
| return HRESULT_FROM_WIN32(E_FAIL); |
| } |
| |
| // Wait for the new process to work |
| WaitForSingleObject(pi.hProcess, INFINITE); |
| |
| CloseHandle(pi.hProcess); |
| CloseHandle(pi.hThread); |
| |
| return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); |
| } |
| |
| |
| typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD, LPTSTR ); |
| |
| |
| TCHAR* CXMergeFilter::GetJavaBaseDir() |
| { |
| HRESULT lRet; |
| |
| HKEY hKey = NULL; |
| HKEY hDataKey = NULL; |
| |
| TCHAR szClassName[_MAX_PATH] = "\0"; |
| TCHAR szKeyName[_MAX_PATH] = "\0"; |
| TCHAR szCurrentJava[_MAX_PATH] = "\0"; |
| DWORD dwClassName = _MAX_PATH; |
| DWORD dwKeyName = _MAX_PATH; |
| |
| /* |
| * Java leaves registry keys at HKLM\SOFTWARE\JavaSoft. |
| * |
| * Check for a JRE installation first |
| */ |
| lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\JavaSoft\\Java Runtime Environment"), 0, KEY_READ, &hKey); |
| if (lRet != ERROR_SUCCESS) |
| return NULL; |
| |
| // Locations shouldn't be greater than _MAX_PATH |
| TCHAR* szJavaHome = new TCHAR[_MAX_PATH + 1]; |
| DWORD dwSize = _MAX_PATH + 1; |
| |
| /* use current version */ |
| lRet = ::RegQueryValueEx(hKey, _T("CurrentVersion"), 0, NULL, (LPBYTE)szCurrentJava, &dwSize); |
| |
| /* |
| for (DWORD i = 0; lRet != ERROR_NO_MORE_ITEMS; i++) |
| { |
| lRet = ::RegEnumKeyEx(hKey, i, szKeyName, &dwKeyName, 0, szClassName, &dwClassName, NULL); |
| if(!strncmp(szKeyName, "1.4", 3)) |
| break; |
| dwKeyName = _MAX_PATH; |
| } |
| // Found a Java 1.4 installation. Can now read its home directory. |
| */ |
| |
| |
| lRet = ::RegOpenKeyEx(hKey, _T(szCurrentJava), 0, KEY_READ, &hDataKey); |
| if (lRet != ERROR_SUCCESS) |
| { |
| RegCloseKey(hKey); |
| delete [] szJavaHome; |
| return NULL; |
| } |
| |
| |
| // Now read the JavaHome value |
| dwSize = _MAX_PATH + 1; |
| lRet = ::RegQueryValueEx(hDataKey, _T("JavaHome"), 0, NULL, (LPBYTE)szJavaHome, &dwSize); |
| if (lRet != ERROR_SUCCESS) |
| { |
| RegCloseKey(hDataKey); |
| RegCloseKey(hKey); |
| delete [] szJavaHome; |
| return NULL; |
| } |
| |
| RegCloseKey(hDataKey); |
| RegCloseKey(hKey); |
| |
| |
| // Check that the directory exists before returning it |
| DWORD dwAttrs = GetFileAttributes(szJavaHome); |
| |
| if (((dwAttrs & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) || dwAttrs == INVALID_FILE_SIZE) |
| { |
| delete [] szJavaHome; |
| return NULL; |
| } |
| |
| return szJavaHome; |
| } |
| |
| |
| |
| TCHAR* CXMergeFilter::GetXMergeClassPath() |
| { |
| /* |
| * The DLL will be installed by setup in the program directory of |
| * the installation. The XMerge Jar files, if present, will be |
| * located in the classes directory below program. |
| */ |
| |
| TCHAR szJarPath[MAX_PATH]; |
| TCHAR szTmpPath[MAX_PATH]; |
| |
| ZeroMemory(szJarPath, MAX_PATH); |
| ZeroMemory(szTmpPath, MAX_PATH); |
| |
| WIN32_FILE_ATTRIBUTE_DATA fInfo; |
| |
| std::string clsPath; |
| |
| |
| // Get the location of the module. |
| GetModuleFileName(_Module.m_hInst, szTmpPath, MAX_PATH); |
| |
| // Strip off the xmergesync.dll component |
| _strlwr(szTmpPath); |
| char* modName = strstr(szTmpPath, "xmergesync.dll"); |
| strncpy(szJarPath, szTmpPath, modName - szTmpPath); |
| |
| // Append the classes directory |
| strncat(szJarPath, "classes\\", 8); |
| |
| |
| // The core xmerge.jar must be present |
| ZeroMemory(szTmpPath, MAX_PATH); |
| _snprintf(szTmpPath, MAX_PATH, "%s%s\0", szJarPath, "xmerge.jar"); |
| |
| if (!GetFileAttributesEx(szTmpPath, GetFileExInfoStandard, &fInfo)) |
| { |
| return NULL; |
| } |
| else |
| { |
| clsPath += szTmpPath; |
| clsPath += ";"; |
| } |
| |
| |
| // Now check for Pocket Word |
| ZeroMemory(szTmpPath, MAX_PATH); |
| _snprintf(szTmpPath, MAX_PATH, "%s%s\0", szJarPath, "pocketword.jar"); |
| |
| if (!GetFileAttributesEx(szTmpPath, GetFileExInfoStandard, &fInfo)) |
| { |
| m_bHaveWord = FALSE; |
| } |
| else |
| { |
| m_bHaveWord = TRUE; |
| clsPath += szTmpPath; |
| clsPath += ";"; |
| } |
| |
| // Now check for Pocket Excel |
| ZeroMemory(szTmpPath, MAX_PATH); |
| _snprintf(szTmpPath, MAX_PATH, "%s%s\0", szJarPath, "pexcel.jar"); |
| |
| if (!GetFileAttributesEx(szTmpPath, GetFileExInfoStandard, &fInfo)) |
| { |
| m_bHaveExcel = FALSE; |
| } |
| else |
| { |
| m_bHaveExcel = TRUE; |
| clsPath += szTmpPath; |
| clsPath += ";"; |
| } |
| |
| // Quotes may be need around the ClassPath |
| clsPath.insert(0, "\""); |
| clsPath += "\""; |
| |
| |
| // Return the data |
| return _strdup(clsPath.c_str()); |
| } |