aboutsummaryrefslogtreecommitdiff
path: root/src/windows
diff options
context:
space:
mode:
authorVyacheslav Moklev <slavam2605@bk.ru>2019-02-14 11:42:45 +0300
committerVyacheslav Moklev <slavam2605@bk.ru>2019-02-14 11:42:45 +0300
commit9349ef4f697543a80d097e556fc38df7c6ef69fa (patch)
tree17a1faf361d485b46dc1d578eb41c18efcc606aa /src/windows
parent8fa6e6c4a9393593fc7c2f26ea402358b950d2e7 (diff)
downloadjdk8u_jdk-9349ef4f697543a80d097e556fc38df7c6ef69fa.tar.gz
JRE-1217 Backport JRE-1216 to JBRE8
Add implementation of file dialogs with the new Common Items Dialog API
Diffstat (limited to 'src/windows')
-rw-r--r--src/windows/classes/sun/awt/windows/WFileDialogPeer.java5
-rw-r--r--src/windows/native/sun/windows/awt_FileDialog.cpp565
-rw-r--r--src/windows/native/sun/windows/awt_ole.h17
3 files changed, 523 insertions, 64 deletions
diff --git a/src/windows/classes/sun/awt/windows/WFileDialogPeer.java b/src/windows/classes/sun/awt/windows/WFileDialogPeer.java
index 4d80996cae..7e828bcbfb 100644
--- a/src/windows/classes/sun/awt/windows/WFileDialogPeer.java
+++ b/src/windows/classes/sun/awt/windows/WFileDialogPeer.java
@@ -36,6 +36,7 @@ import java.util.MissingResourceException;
import java.util.Vector;
import sun.awt.CausedFocusEvent;
import sun.awt.AWTAccessor;
+import sun.security.action.GetBooleanAction;
final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
@@ -97,6 +98,10 @@ final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
_dispose();
}
+ private static boolean useCommonItemDialog() {
+ return AccessController.doPrivileged(new GetBooleanAction("sun.awt.windows.useCommonItemDialog"));
+ }
+
private native void _show();
private native void _hide();
diff --git a/src/windows/native/sun/windows/awt_FileDialog.cpp b/src/windows/native/sun/windows/awt_FileDialog.cpp
index 0749cf1b70..1e5d78da69 100644
--- a/src/windows/native/sun/windows/awt_FileDialog.cpp
+++ b/src/windows/native/sun/windows/awt_FileDialog.cpp
@@ -27,11 +27,13 @@
#include "awt_FileDialog.h"
#include "awt_Dialog.h"
#include "awt_Toolkit.h"
+#include "awt_ole.h"
#include "ComCtl32Util.h"
#include <commdlg.h>
#include <cderr.h>
#include <shlobj.h>
-
+#include <shlwapi.h>
+#include <shobjidl.h>
/************************************************************************
* AwtFileDialog fields
@@ -52,11 +54,92 @@ jfieldID AwtFileDialog::dirID;
jfieldID AwtFileDialog::fileID;
jfieldID AwtFileDialog::filterID;
+class CoTaskStringHolder {
+public:
+ CoTaskStringHolder() : m_str(NULL) {}
+
+ CoTaskStringHolder& operator=(CoTaskStringHolder& other) {
+ Clean();
+ m_str = other.m_str;
+ other.m_str = NULL;
+ return *this;
+ }
+
+ LPTSTR* operator&() {
+ return &m_str;
+ }
+
+ operator bool() {
+ return m_str != NULL;
+ }
+
+ operator LPTSTR() {
+ return m_str;
+ }
+
+ ~CoTaskStringHolder() {
+ Clean();
+ }
+private:
+ LPTSTR m_str;
+
+ void Clean() {
+ if (m_str)
+ ::CoTaskMemFree(m_str);
+ }
+};
+
+template <typename T>
+class SmartHolderBase {
+public:
+ SmartHolderBase() : m_pointer(NULL) {}
+
+ SmartHolderBase& operator=(const SmartHolderBase&) = delete;
+
+ void Attach(T* other) {
+ Clean();
+ m_pointer = other;
+ }
+
+ operator bool() {
+ return m_pointer != NULL;
+ }
+
+ operator T*() {
+ return m_pointer;
+ }
+
+ ~SmartHolderBase() {
+ Clean();
+ }
+protected:
+ T* m_pointer;
+
+ virtual void Clean() {
+ if (m_pointer)
+ delete m_pointer;
+ }
+};
+
+template<typename T>
+class SmartHolder : public SmartHolderBase<T> {
+};
+
+template <typename T>
+class SmartHolder<T[]> : public SmartHolderBase<T> {
+ virtual void Clean() {
+ if (m_pointer)
+ delete [] m_pointer;
+ }
+};
+
/* Localized filter string */
#define MAX_FILTER_STRING 128
static TCHAR s_fileFilterString[MAX_FILTER_STRING];
/* Non-localized suffix of the filter string */
static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0");
+static SmartHolder<COMDLG_FILTERSPEC> s_fileFilterSpec;
+static UINT s_fileFilterCount;
// Default limit of the output buffer.
#define SINGLE_MODE_BUFFER_LIMIT MAX_PATH+1
@@ -65,8 +148,45 @@ static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0");
// The name of the property holding the pointer to the OPENFILENAME structure.
static LPCTSTR OpenFileNameProp = TEXT("AWT_OFN");
+_COM_SMARTPTR_TYPEDEF(IFileDialog, __uuidof(IFileDialog));
+_COM_SMARTPTR_TYPEDEF(IFileDialogEvents, __uuidof(IFileDialogEvents));
+_COM_SMARTPTR_TYPEDEF(IShellItem, __uuidof(IShellItem));
+_COM_SMARTPTR_TYPEDEF(IFileOpenDialog, __uuidof(IFileOpenDialog));
+_COM_SMARTPTR_TYPEDEF(IShellItemArray, __uuidof(IShellItemArray));
+_COM_SMARTPTR_TYPEDEF(IOleWindowPtr, __uuidof(IOleWindowPtr));
+
/***********************************************************************/
+COMDLG_FILTERSPEC *CreateFilterSpec(UINT *count) {
+ UINT filterCount = 0;
+ for (UINT index = 0; index < MAX_FILTER_STRING - 1; index++) {
+ if (s_fileFilterString[index] == _T('\0')) {
+ filterCount++;
+ if (s_fileFilterString[index + 1] == _T('\0'))
+ break;
+ }
+ }
+ filterCount /= 2;
+ COMDLG_FILTERSPEC *filterSpec = new COMDLG_FILTERSPEC[filterCount];
+ UINT currentIndex = 0;
+ TCHAR *currentStart = s_fileFilterString;
+ for (UINT index = 0; index < MAX_FILTER_STRING - 1; index++) {
+ if (s_fileFilterString[index] == _T('\0')) {
+ if (currentIndex & 1) {
+ filterSpec[currentIndex / 2].pszSpec = currentStart;
+ } else {
+ filterSpec[currentIndex / 2].pszName = currentStart;
+ }
+ currentStart = s_fileFilterString + index + 1;
+ currentIndex++;
+ if (s_fileFilterString[index + 1] == _T('\0'))
+ break;
+ }
+ }
+ *count = filterCount;
+ return filterSpec;
+}
+
void
AwtFileDialog::Initialize(JNIEnv *env, jstring filterDescription)
{
@@ -86,6 +206,7 @@ AwtFileDialog::Initialize(JNIEnv *env, jstring filterDescription)
}
DASSERT(s + sizeof(s_additionalString) < s_fileFilterString + MAX_FILTER_STRING);
memcpy(s, s_additionalString, sizeof(s_additionalString));
+ s_fileFilterSpec.Attach(CreateFilterSpec(&s_fileFilterCount));
}
LRESULT CALLBACK FileDialogWndProc(HWND hWnd, UINT message,
@@ -229,12 +350,237 @@ FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
CATCH_BAD_ALLOC_RET(TRUE);
}
+struct FileDialogData {
+ IFileDialogPtr fileDialog;
+ SmartHolder<TCHAR[]> result;
+ UINT resultSize;
+ jobject peer;
+};
+
+HRESULT GetSelectedResults(FileDialogData *data) {
+ OLE_TRY
+
+ IFileOpenDialogPtr fileOpenDialog;
+ UINT currentOffset = 0;
+ IShellItemArrayPtr psia;
+ DWORD itemsCount;
+
+ OLE_HRT(data->fileDialog->QueryInterface(IID_PPV_ARGS(&fileOpenDialog)))
+ OLE_HRT(fileOpenDialog->GetSelectedItems(&psia));
+ OLE_HRT(psia->GetCount(&itemsCount));
+
+ UINT maxBufferSize = (MAX_PATH + 1) * itemsCount + 1;
+ data->result.Attach(new TCHAR[maxBufferSize]);
+ data->resultSize = maxBufferSize;
+ LPTSTR resultBuffer = data->result;
+ for (DWORD i = 0; i < itemsCount; i++) {
+ IShellItemPtr psi;
+ OLE_HRT(psia->GetItemAt(i, &psi));
+ if (i == 0 && itemsCount > 1) {
+ IShellItemPtr psiParent;
+ CoTaskStringHolder filePath;
+ OLE_HRT(psi->GetParent(&psiParent));
+ OLE_HRT(psiParent->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
+ size_t filePathLength = _tcslen(filePath);
+ _tcsncpy(resultBuffer + currentOffset, filePath, filePathLength);
+ resultBuffer[currentOffset + filePathLength] = _T('\0');
+ currentOffset += filePathLength + 1;
+ }
+
+ CoTaskStringHolder filePath;
+ SIGDN displayForm = itemsCount > 1 ? SIGDN_PARENTRELATIVE : SIGDN_FILESYSPATH;
+ OLE_HRT(psi->GetDisplayName(displayForm, &filePath));
+ size_t filePathLength = _tcslen(filePath);
+ _tcsncpy(resultBuffer + currentOffset, filePath, filePathLength);
+ resultBuffer[currentOffset + filePathLength] = _T('\0');
+ currentOffset += filePathLength + 1;
+ }
+ resultBuffer[currentOffset] = _T('\0');
+ resultBuffer[currentOffset + 1] = _T('\0');
+ data->fileDialog->Close(S_OK);
+
+ OLE_CATCH
+ OLE_RETURN_HR
+}
+
+LRESULT CALLBACK
+FileDialogSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
+{
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+ TRY;
+
+ HWND parent = ::GetParent(hWnd);
+
+ switch (uMsg) {
+ case WM_COMMAND: {
+ if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK) {
+ OLE_TRY
+ OLE_HRT(GetSelectedResults((FileDialogData*) dwRefData));
+ OLE_CATCH
+ }
+ if (LOWORD(wParam) == IDCANCEL) {
+ jobject peer = (jobject) (::GetProp(hWnd, ModalDialogPeerProp));
+ env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong) 0);
+ }
+ break;
+ }
+ case WM_SETICON: {
+ return 0;
+ }
+ case WM_DESTROY: {
+ HIMC hIMC = ::ImmGetContext(hWnd);
+ if (hIMC != NULL) {
+ ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
+ ::ImmReleaseContext(hWnd, hIMC);
+ }
+
+ RemoveWindowSubclass(hWnd, &FileDialogSubclassProc, uIdSubclass);
+
+ ::RemoveProp(parent, ModalDialogPeerProp);
+ break;
+ }
+ }
+
+ return DefSubclassProc(hWnd, uMsg, wParam, lParam);
+
+ CATCH_BAD_ALLOC_RET(TRUE);
+}
+
+class CDialogEventHandler : public IFileDialogEvents
+{
+public:
+ IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv)
+ {
+ static const QITAB qit[] = {
+ QITABENT(CDialogEventHandler, IFileDialogEvents),
+ { 0 },
+ };
+ return QISearch(this, qit, riid, ppv);
+ }
+
+ IFACEMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_refCount);
+ }
+
+ IFACEMETHODIMP_(ULONG) Release()
+ {
+ long retVal = InterlockedDecrement(&m_refCount);
+ if (!retVal)
+ delete this;
+ return retVal;
+ }
+
+ IFACEMETHODIMP OnFolderChange(IFileDialog *fileDialog) {
+ if (!m_activated) {
+ InitDialog(fileDialog);
+ m_activated = true;
+ }
+ return S_OK;
+ };
+
+ IFACEMETHODIMP OnFileOk(IFileDialog *) {
+ if (!data->result) {
+ OLE_TRY
+ OLE_HRT(GetSelectedResults(data));
+ OLE_CATCH
+ }
+ return S_OK;
+ };
+
+ IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *) { return S_OK; };
+ IFACEMETHODIMP OnHelp(IFileDialog *) { return S_OK; };
+ IFACEMETHODIMP OnSelectionChange(IFileDialog *) { return S_OK; };
+ IFACEMETHODIMP OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; };
+ IFACEMETHODIMP OnTypeChange(IFileDialog *pfd) { return S_OK; };
+ IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; };
+
+ CDialogEventHandler(FileDialogData *data) : data(data), m_refCount(1), m_activated(false) { };
+private:
+ ~CDialogEventHandler() { };
+ FileDialogData *data;
+ bool m_activated;
+ long m_refCount;
+
+ void InitDialog(IFileDialog *fileDialog) {
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+ TRY;
+ OLE_TRY
+
+ IOleWindowPtr pWindow;
+ OLE_HR = fileDialog->QueryInterface(IID_PPV_ARGS(&pWindow));
+ if (!SUCCEEDED(OLE_HR))
+ return;
+
+ HWND hdlg;
+ OLE_HRT(pWindow->GetWindow(&hdlg));
+
+ HWND parent = ::GetParent(hdlg);
+ jobject peer = data->peer;
+ env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)parent);
+ ::SetProp(parent, ModalDialogPeerProp, reinterpret_cast<HANDLE>(peer));
+
+ // fix for 4508670 - disable CS_SAVEBITS
+ DWORD style = ::GetClassLong(hdlg, GCL_STYLE);
+ ::SetClassLong(hdlg, GCL_STYLE, style & ~CS_SAVEBITS);
+
+ // set appropriate icon for parentless dialogs
+ jobject awtParent = env->GetObjectField(peer, AwtFileDialog::parentID);
+ if (awtParent == NULL) {
+ ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_BIG,
+ (LPARAM)AwtToolkit::GetInstance().GetAwtIcon());
+ } else {
+ AwtWindow *awtWindow = (AwtWindow *)JNI_GET_PDATA(awtParent);
+ ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_BIG,
+ (LPARAM)(awtWindow->GetHIcon()));
+ ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_SMALL,
+ (LPARAM)(awtWindow->GetHIconSm()));
+ env->DeleteLocalRef(awtParent);
+ }
+
+ SetWindowSubclass(hdlg, &FileDialogSubclassProc, 0, (DWORD_PTR) data);
+
+ OLE_CATCH
+ CATCH_BAD_ALLOC;
+ }
+};
+
+HRESULT CDialogEventHandler_CreateInstance(FileDialogData *data, REFIID riid, void **ppv)
+{
+ OLE_TRY
+ IFileDialogEventsPtr dlg(new CDialogEventHandler(data), false);
+ OLE_HRT(dlg->QueryInterface(riid, ppv));
+ OLE_CATCH
+ OLE_RETURN_HR
+}
+
+HRESULT CreateShellItem(LPTSTR path, IShellItem *shellItem) {
+ size_t pathLength = _tcslen(path);
+ for (size_t index = 0; index < pathLength; index++) {
+ if (path[index] == _T('/'))
+ path[index] = _T('\\');
+ }
+
+ return ::SHCreateItemInKnownFolder(FOLDERID_ComputerFolder, 0, path, IID_PPV_ARGS(&shellItem));
+}
+
+CoTaskStringHolder GetShortName(LPTSTR path) {
+ CoTaskStringHolder shortName;
+ OLE_TRY
+ IShellItemPtr shellItem;
+ OLE_HRT(CreateShellItem(path, shellItem));
+ OLE_HRT(shellItem->GetDisplayName(SIGDN_PARENTRELATIVE, &shortName));
+ OLE_CATCH
+ return SUCCEEDED(OLE_HR) ? shortName : CoTaskStringHolder();
+}
+
void
AwtFileDialog::Show(void *p)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject peer;
- LPTSTR fileBuffer = NULL;
LPTSTR currentDirectory = NULL;
jint mode = 0;
BOOL result = FALSE;
@@ -248,13 +594,24 @@ AwtFileDialog::Show(void *p)
AwtComponent* awtParent = NULL;
jboolean multipleMode = JNI_FALSE;
+ OLE_DECL
+ OLEHolder _ole_;
+ IFileDialogPtr pfd;
+ IFileDialogEventsPtr pfde;
+ IShellItemPtr psiResult;
+ FileDialogData data;
+ DWORD dwCookie;
+
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
peer = (jobject)p;
+ static BOOL useCommonItemDialog = JNU_CallStaticMethodByName(env, NULL,
+ "sun/awt/windows/WFileDialogPeer", "useCommonItemDialog", "()Z").z == JNI_TRUE;
try {
DASSERT(peer);
+
target = env->GetObjectField(peer, AwtObject::targetID);
parent = env->GetObjectField(peer, AwtFileDialog::parentID);
if (parent != NULL) {
@@ -296,68 +653,132 @@ AwtFileDialog::Show(void *p)
fileBuffer[0] = _T('\0');
}
- ofn.lStructSize = sizeof(ofn);
- ofn.lpstrFilter = s_fileFilterString;
- ofn.nFilterIndex = 1;
- /*
- Fix for 6488834.
- To disable Win32 native parent modality we have to set
- hwndOwner field to either NULL or some hidden window. For
- parentless dialogs we use NULL to show them in the taskbar,
- and for all other dialogs AwtToolkit's HWND is used.
- */
- if (awtParent != NULL)
- {
- ofn.hwndOwner = AwtToolkit::GetInstance().GetHWnd();
- }
- else
- {
- ofn.hwndOwner = NULL;
- }
- ofn.lpstrFile = fileBuffer;
- ofn.nMaxFile = bufferLimit;
- ofn.lpstrTitle = titleBuffer;
- ofn.lpstrInitialDir = directoryBuffer;
- ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
- OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING;
- fileFilter = env->GetObjectField(peer,
- AwtFileDialog::fileFilterID);
- if (!JNU_IsNull(env,fileFilter)) {
- ofn.Flags |= OFN_ENABLEINCLUDENOTIFY;
- }
- ofn.lCustData = (LPARAM)peer;
- ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc;
+ fileFilter = env->GetObjectField(peer, AwtFileDialog::fileFilterID);
+
+ if (!useCommonItemDialog) {
+ ofn.lStructSize = sizeof(ofn);
+ ofn.lpstrFilter = s_fileFilterString;
+ ofn.nFilterIndex = 1;
+ /*
+ Fix for 6488834.
+ To disable Win32 native parent modality we have to set
+ hwndOwner field to either NULL or some hidden window. For
+ parentless dialogs we use NULL to show them in the taskbar,
+ and for all other dialogs AwtToolkit's HWND is used.
+ */
+ if (awtParent != NULL) {
+ ofn.hwndOwner = AwtToolkit::GetInstance().GetHWnd();
+ } else {
+ ofn.hwndOwner = NULL;
+ }
+ ofn.lpstrFile = fileBuffer;
+ ofn.nMaxFile = bufferLimit;
+ ofn.lpstrTitle = titleBuffer;
+ ofn.lpstrInitialDir = directoryBuffer;
+ ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
+ OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING;
+
+ if (!JNU_IsNull(env,fileFilter)) {
+ ofn.Flags |= OFN_ENABLEINCLUDENOTIFY;
+ }
+ ofn.lCustData = (LPARAM)peer;
+ ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc;
- if (multipleMode == JNI_TRUE) {
- ofn.Flags |= OFN_ALLOWMULTISELECT;
- }
+ if (multipleMode == JNI_TRUE) {
+ ofn.Flags |= OFN_ALLOWMULTISELECT;
+ }
- // Save current directory, so we can reset if it changes.
- currentDirectory = new TCHAR[MAX_PATH+1];
+ // Save current directory, so we can reset if it changes.
+ currentDirectory = new TCHAR[MAX_PATH+1];
- VERIFY(::GetCurrentDirectory(MAX_PATH, currentDirectory) > 0);
+ VERIFY(::GetCurrentDirectory(MAX_PATH, currentDirectory) > 0);
+ }
mode = env->GetIntField(target, AwtFileDialog::modeID);
AwtDialog::CheckInstallModalHook();
- // show the Win32 file dialog
- if (mode == java_awt_FileDialog_LOAD) {
- result = ::GetOpenFileName(&ofn);
- } else {
- result = ::GetSaveFileName(&ofn);
+ if (useCommonItemDialog) {
+ OLE_NEXT_TRY
+ GUID fileDialogMode = mode == java_awt_FileDialog_LOAD ? CLSID_FileOpenDialog : CLSID_FileSaveDialog;
+ OLE_HRT(pfd.CreateInstance(fileDialogMode));
+
+ data.fileDialog = pfd;
+ data.peer = peer;
+ OLE_HRT(CDialogEventHandler_CreateInstance(&data, IID_PPV_ARGS(&pfde)));
+ OLE_HRT(pfd->Advise(pfde, &dwCookie));
+
+ DWORD dwFlags;
+ OLE_HRT(pfd->GetOptions(&dwFlags));
+ dwFlags |= FOS_FORCEFILESYSTEM;
+ if (multipleMode == JNI_TRUE) {
+ dwFlags |= FOS_ALLOWMULTISELECT;
+ }
+ OLE_HRT(pfd->SetOptions(dwFlags));
+
+ OLE_HRT(pfd->SetTitle(titleBuffer));
+
+ OLE_HRT(pfd->SetFileTypes(s_fileFilterCount, s_fileFilterSpec));
+ OLE_HRT(pfd->SetFileTypeIndex(1));
+
+ IShellItemPtr directoryItem;
+ if (SUCCEEDED(CreateShellItem(directoryBuffer, directoryItem))) {
+ pfd->SetFolder(directoryItem);
+ }
+ CoTaskStringHolder shortName = GetShortName(fileBuffer);
+ if (shortName) {
+ OLE_HRT(pfd->SetFileName(shortName));
+ }
+ OLE_CATCH
}
- // Fix for 4181310: FileDialog does not show up.
- // If the dialog is not shown because of invalid file name
- // replace the file name by empty string.
- if (!result) {
- dlgerr = ::CommDlgExtendedError();
- if (dlgerr == FNERR_INVALIDFILENAME) {
- _tcscpy_s(fileBuffer, bufferLimit, TEXT(""));
- if (mode == java_awt_FileDialog_LOAD) {
- result = ::GetOpenFileName(&ofn);
- } else {
- result = ::GetSaveFileName(&ofn);
+
+ if (useCommonItemDialog && SUCCEEDED(OLE_HR)) {
+ if (mode == java_awt_FileDialog_LOAD) {
+ result = SUCCEEDED(pfd->Show(NULL)) && data.result;
+ if (!result) {
+ OLE_NEXT_TRY
+ OLE_HRT(pfd->GetResult(&psiResult));
+ CoTaskStringHolder filePath;
+ OLE_HRT(psiResult->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
+ size_t filePathLength = _tcslen(filePath);
+ data.result.Attach(new TCHAR[filePathLength + 1]);
+ _tcscpy_s(data.result, filePathLength + 1, filePath);
+ OLE_CATCH
+ result = SUCCEEDED(OLE_HR);
+ }
+ } else {
+ result = SUCCEEDED(pfd->Show(NULL));
+ if (result) {
+ OLE_NEXT_TRY
+ OLE_HRT(pfd->GetResult(&psiResult));
+ CoTaskStringHolder filePath;
+ OLE_HRT(psiResult->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
+ size_t filePathLength = _tcslen(filePath);
+ data.result.Attach(new TCHAR[filePathLength + 1]);
+ _tcscpy_s(data.result, filePathLength + 1, filePath);
+ OLE_CATCH
+ result = SUCCEEDED(OLE_HR);
+ }
+ }
+ } else {
+ // show the Win32 file dialog
+ if (mode == java_awt_FileDialog_LOAD) {
+ result = ::GetOpenFileName(&ofn);
+ } else {
+ result = ::GetSaveFileName(&ofn);
+ }
+ // Fix for 4181310: FileDialog does not show up.
+ // If the dialog is not shown because of invalid file name
+ // replace the file name by empty string.
+ if (!result) {
+ dlgerr = ::CommDlgExtendedError();
+ if (dlgerr == FNERR_INVALIDFILENAME) {
+ _tcscpy_s(fileBuffer, bufferLimit, TEXT(""));
+ if (mode == java_awt_FileDialog_LOAD) {
+ result = ::GetOpenFileName(&ofn);
+ } else {
+ result = ::GetSaveFileName(&ofn);
+ }
}
}
}
@@ -368,19 +789,31 @@ AwtFileDialog::Show(void *p)
AwtDialog::ModalActivateNextWindow(NULL, target, peer);
- VERIFY(::SetCurrentDirectory(currentDirectory));
+ if (useCommonItemDialog) {
+ VERIFY(::SetCurrentDirectory(currentDirectory));
+ }
// Report result to peer.
if (result) {
- jint length = multipleMode
- ? (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile)
- : (jint)_tcslen(ofn.lpstrFile);
+ jint length;
+ if (useCommonItemDialog) {
+ length = (jint) GetBufferLength(data.result, data.resultSize);
+ } else {
+ length = multipleMode
+ ? (jint) GetBufferLength(ofn.lpstrFile, ofn.nMaxFile)
+ : (jint) _tcslen(ofn.lpstrFile);
+ }
+
jcharArray jnames = env->NewCharArray(length);
if (jnames == NULL) {
throw std::bad_alloc();
}
- env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile);
+ if (useCommonItemDialog) {
+ env->SetCharArrayRegion(jnames, 0, length, (jchar *) (LPTSTR) data.result);
+ } else {
+ env->SetCharArrayRegion(jnames, 0, length, (jchar *) ofn.lpstrFile);
+ }
env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames);
env->DeleteLocalRef(jnames);
} else {
@@ -389,6 +822,12 @@ AwtFileDialog::Show(void *p)
DASSERT(!safe_ExceptionOccurred(env));
} catch (...) {
+ if (useCommonItemDialog) {
+ if (pfd) {
+ pfd->Unadvise(dwCookie);
+ }
+ }
+
env->DeleteLocalRef(target);
env->DeleteLocalRef(parent);
env->DeleteLocalRef(title);
@@ -403,6 +842,12 @@ AwtFileDialog::Show(void *p)
throw;
}
+ if (useCommonItemDialog) {
+ if (pfd) {
+ pfd->Unadvise(dwCookie);
+ }
+ }
+
env->DeleteLocalRef(target);
env->DeleteLocalRef(parent);
env->DeleteLocalRef(title);
diff --git a/src/windows/native/sun/windows/awt_ole.h b/src/windows/native/sun/windows/awt_ole.h
index db54c64fce..cbca45bed8 100644
--- a/src/windows/native/sun/windows/awt_ole.h
+++ b/src/windows/native/sun/windows/awt_ole.h
@@ -183,11 +183,20 @@ struct CLogEntryPoint0 {
struct OLEHolder
{
OLEHolder()
- : m_hr(::OleInitialize(NULL))
- {}
+ : m_hr(::OleInitialize(NULL))
+ {
+ if (SUCCEEDED(m_hr)) {
+ STRACE(_T("{OLE"));
+ }
+ }
- ~OLEHolder(){}
- operator bool() const { return S_OK==SUCCEEDED(m_hr); }
+ ~OLEHolder(){
+ if (SUCCEEDED(m_hr)) {
+ ::OleUninitialize();
+ STRACE(_T("}OLE"));
+ }
+ }
+ operator bool() const { return TRUE==SUCCEEDED(m_hr); }
HRESULT m_hr;
};