Bug 288474 - Saving a docx file fails silently due to not killing WINWORD process on close
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 6f01198..ac03d47 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
@@ -178,28 +178,12 @@
 		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();
@@ -307,7 +291,15 @@
 }
 
 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
@@ -337,6 +329,7 @@
 			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) {
@@ -846,9 +839,17 @@
 	}
 	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$ 
@@ -1111,6 +1112,14 @@
  * @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);
@@ -1189,6 +1198,31 @@
 		
 	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 
@@ -1210,38 +1244,8 @@
 	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 {
@@ -1284,34 +1288,6 @@
 	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$