JRE-1216 Implement Windows native file dialogs with the new Common Item Dialog API

Add implementation of file dialogs with the new Common Items Dialog API
This commit is contained in:
Vyacheslav Moklev
2019-02-07 17:28:28 +03:00
committed by Vitaly Provodin
parent ce23ff88d6
commit 93261b19f9
3 changed files with 524 additions and 65 deletions

View File

@@ -36,6 +36,7 @@ import java.util.ResourceBundle;
import java.util.MissingResourceException;
import java.util.Vector;
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();

View File

@@ -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,
@@ -237,12 +358,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;
@@ -256,13 +602,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) {
@@ -304,68 +661,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 (multipleMode == JNI_TRUE) {
ofn.Flags |= OFN_ALLOWMULTISELECT;
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;
}
// Save current directory, so we can reset if it changes.
currentDirectory = new TCHAR[MAX_PATH+1];
VERIFY(::GetCurrentDirectory(MAX_PATH, currentDirectory) > 0);
}
// Save current directory, so we can reset if it changes.
currentDirectory = new TCHAR[MAX_PATH+1];
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);
}
}
}
}
@@ -376,19 +797,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 {
@@ -397,6 +830,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);
@@ -411,6 +850,12 @@ AwtFileDialog::Show(void *p)
throw;
}
if (useCommonItemDialog) {
if (pfd) {
pfd->Unadvise(dwCookie);
}
}
env->DeleteLocalRef(target);
env->DeleteLocalRef(parent);
env->DeleteLocalRef(title);

View File

@@ -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;
};