diff options
author | Felipe Heidrich <fheidric> | 2009-10-07 20:28:51 +0000 |
---|---|---|
committer | Felipe Heidrich <fheidric> | 2009-10-07 20:28:51 +0000 |
commit | 8c113a426e5f05549192616bd0df00498451eac3 (patch) | |
tree | 610c48ad5bd2fa64f9a7c648d80eb4af44a12cbe /bundles/org.eclipse.swt/Eclipse SWT OLE Win32 | |
parent | 647ee8ac0b4674688a64286f665d0bc51c0718e8 (diff) | |
download | eclipse.platform.swt-8c113a426e5f05549192616bd0df00498451eac3.tar.gz eclipse.platform.swt-8c113a426e5f05549192616bd0df00498451eac3.tar.xz eclipse.platform.swt-8c113a426e5f05549192616bd0df00498451eac3.zip |
Bug 288474 - Saving a docx file fails silently due to not killing WINWORD process on close
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT OLE Win32')
-rwxr-xr-x | bundles/org.eclipse.swt/Eclipse SWT OLE Win32/win32/org/eclipse/swt/ole/win32/OleClientSite.java | 138 |
1 files changed, 57 insertions, 81 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT OLE Win32/win32/org/eclipse/swt/ole/win32/OleClientSite.java b/bundles/org.eclipse.swt/Eclipse SWT OLE Win32/win32/org/eclipse/swt/ole/win32/OleClientSite.java index 2802c7a739..fb9d3f73d9 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT OLE Win32/win32/org/eclipse/swt/ole/win32/OleClientSite.java +++ b/bundles/org.eclipse.swt/Eclipse SWT OLE Win32/win32/org/eclipse/swt/ole/win32/OleClientSite.java @@ -183,28 +183,12 @@ public OleClientSite(Composite parent, int style, File file) { GUID fileClsid = new GUID(); char[] fileName = (file.getAbsolutePath()+"\0").toCharArray(); int result = COM.GetClassFile(fileName, fileClsid); - if (result != COM.S_OK) - OLE.error(OLE.ERROR_INVALID_CLASSID, result); + if (result != COM.S_OK) OLE.error(OLE.ERROR_INVALID_CLASSID, result); // associated CLSID may not be installed on this machine - appClsid = fileClsid; - String progID = getProgramID(); - if (progID == null) - OLE.error(OLE.ERROR_INVALID_CLASSID, result); + String progID = getProgID(fileClsid); + if (progID == null) OLE.error(OLE.ERROR_INVALID_CLASSID, result); - /* Bug in Windows. In some machines running Windows Vista and - * Office 2007, OleCreateFromFile() fails to open files from - * Office Word 97 - 2003. The fix is to detect this case and create - * the activeX using CoCreateInstance() and then load the file - * using IPersistStorage.Load(). - */ - if (progID.equals("Word.Document.8")) { //$NON-NLS-1$ - GUID clsid = getClassID(WORDPROGID); - String latestProgID = getProgID(clsid); - if (latestProgID.equals("Word.Document.12")) { //$NON-NLS-1$ - appClsid = clsid; - } - } - + appClsid = fileClsid; OleCreate(appClsid, fileClsid, fileName, file); } catch (SWTException e) { dispose(); @@ -312,7 +296,15 @@ public OleClientSite(Composite parent, int style, String progId, File file) { } void OleCreate(GUID appClsid, GUID fileClsid, char[] fileName, File file) { - if (COM.IsEqualGUID(appClsid, fileClsid)){ + + /* Bug in Windows. In some machines running Windows Vista and + * Office 2007, OleCreateFromFile() fails to open files from + * Office Word 97 - 2003 and in some other cases it fails to + * save files due to a lock. The fix is to detect this case and + * create the activeX using CoCreateInstance(). + */ + boolean isOffice2007 = isOffice2007(true); + if (!isOffice2007 && COM.IsEqualGUID(appClsid, fileClsid)){ // Using the same application that created file, therefore, use default mechanism. tempStorage = createTempStorage(); // Create ole object with storage object @@ -342,6 +334,7 @@ void OleCreate(GUID appClsid, GUID fileClsid, char[] fileName, File file) { String streamName = "CONTENTS"; //$NON-NLS-1$ GUID wordGUID = getClassID(WORDPROGID); if (wordGUID != null && COM.IsEqualGUID(appClsid, wordGUID)) streamName = "WordDocument"; //$NON-NLS-1$ + if (isOffice2007) streamName = "Package"; //$NON-NLS-1$ address = new int /*long*/[1]; result = storage.CreateStream(streamName, mode, 0, 0, address); // Increments ref count if successful if (result != COM.S_OK) { @@ -864,9 +857,17 @@ public boolean isFocusControl () { } return false; } -private boolean isOffice2007() { +private boolean isOffice2007(boolean program) { String programID = getProgramID(); if (programID == null) return false; + if (program) { + int lastDot = programID.lastIndexOf('.'); + if (lastDot != -1) { + programID = programID.substring(0, lastDot); + GUID guid = getClassID(programID); + programID = getProgID(guid); + } + } if (programID.equals("Word.Document.12")) return true; //$NON-NLS-1$ if (programID.equals("Excel.Sheet.12")) return true; //$NON-NLS-1$ if (programID.equals("PowerPoint.Show.12")) return true; //$NON-NLS-1$ @@ -1139,6 +1140,14 @@ protected void releaseObjectInterfaces() { * @return true if the save was successful */ public boolean save(File file, boolean includeOleInfo) { + /* + * Bug in Office 2007. Saving Office 2007 documents to compound file storage object + * causes the output file to be corrupted. The fix is to detect Office 2007 documents + * using the program ID and save only the content of the 'Package' stream. + */ + if (isOffice2007(false)) { + return saveOffice2007(file); + } if (includeOleInfo) return saveToStorageFile(file); return saveToTraditionalFile(file); @@ -1217,6 +1226,31 @@ private int SaveObject() { return COM.S_OK; } +private boolean saveOffice2007(File file) { + if (file == null || file.isDirectory()) return false; + if (!updateStorage()) return false; + boolean result = false; + + /* Excel fails to open the package stream when the PersistStorage is not in hands off mode */ + int /*long*/[] ppv = new int /*long*/[1]; + IPersistStorage iPersistStorage = null; + if (objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppv) == COM.S_OK) { + iPersistStorage = new IPersistStorage(ppv[0]); + tempStorage.AddRef(); + iPersistStorage.HandsOffStorage(); + } + int /*long*/[] address = new int /*long*/[1]; + int grfMode = COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE; + if (tempStorage.OpenStream("Package", 0, grfMode, 0, address) == COM.S_OK) { //$NON-NLS-1$ + result = saveFromContents(address[0], file); + } + if (iPersistStorage != null) { + iPersistStorage.SaveCompleted(tempStorage.getAddress()); + tempStorage.Release(); + iPersistStorage.Release(); + } + return result; +} /** * Saves the document to the specified file and includes OLE specific information. This method * must <b>only</b> be used for files that have an OLE Storage format. For example, a word file @@ -1238,38 +1272,8 @@ private boolean saveToStorageFile(File file) { if (file == null || file.isDirectory()) return false; if (!updateStorage()) return false; - int /*long*/[] address = new int /*long*/[1]; - if (objIOleObject.QueryInterface(COM.IIDIPersistFile, address) == COM.S_OK) { - String fileName = null; - IPersistFile persistFile = new IPersistFile(address[0]); - int /*long*/[] ppszFileName = new int /*long*/[1]; - if (persistFile.GetCurFile(ppszFileName) == COM.S_OK) { - int /*long*/ pszFileName = ppszFileName [0]; - int length = OS.wcslen(pszFileName); - char[] buffer = new char[length]; - OS.MoveMemory(buffer, pszFileName, length * 2); - fileName = new String(buffer, 0, length); - // Doc says to use IMalloc::Free, but CoTaskMemFree() does the same - COM.CoTaskMemFree(pszFileName); - } - int result; - String newFile = file.getAbsolutePath(); - if (fileName != null && fileName.equalsIgnoreCase(newFile)) { - result = persistFile.Save(0, false); - } else { - int length = newFile.length(); - char[] buffer = new char[length + 1]; - newFile.getChars(0, length, buffer, 0); - int /*long*/ lpszNewFile = COM.CoTaskMemAlloc(buffer.length * 2); - COM.MoveMemory(lpszNewFile, buffer, buffer.length * 2); - result = persistFile.Save(lpszNewFile, false); - COM.CoTaskMemFree(lpszNewFile); - } - persistFile.Release(); - if (result == COM.S_OK) return true; - } - // get access to the persistent storage mechanism + int /*long*/[] address = new int /*long*/[1]; if (objIOleObject.QueryInterface(COM.IIDIPersistStorage, address) != COM.S_OK) return false; IPersistStorage permStorage = new IPersistStorage(address[0]); try { @@ -1312,34 +1316,6 @@ private boolean saveToTraditionalFile(File file) { if (!updateStorage()) return false; - /* - * Bug in Office 2007. Saving Office 2007 documents to compound file storage object - * causes the output file to be corrupted. The fix is to detect Office 2007 documents - * using the program ID and save only the content of the 'Package' stream. - */ - if (isOffice2007()) { - /* Excel fails to open the package stream when the PersistStorage is not in hands off mode */ - int /*long*/[] ppv = new int /*long*/[1]; - IPersistStorage iPersistStorage = null; - if (objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppv) == COM.S_OK) { - iPersistStorage = new IPersistStorage(ppv[0]); - tempStorage.AddRef(); - iPersistStorage.HandsOffStorage(); - } - boolean result = false; - int /*long*/[] address = new int /*long*/[1]; - int grfMode = COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE; - if (tempStorage.OpenStream("Package", 0, grfMode, 0, address) == COM.S_OK) { //$NON-NLS-1$ - result = saveFromContents(address[0], file); - } - if (iPersistStorage != null) { - iPersistStorage.SaveCompleted(tempStorage.getAddress()); - tempStorage.Release(); - iPersistStorage.Release(); - } - return result; - } - int /*long*/[] address = new int /*long*/[1]; // Look for a CONTENTS stream if (tempStorage.OpenStream("CONTENTS", 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, address) == COM.S_OK) //$NON-NLS-1$ |