1 /*
2  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 #include "awt.h"
27 #include "awt_FileDialog.h"
28 #include "awt_Dialog.h"
29 #include "awt_Toolkit.h"
30 #include "ComCtl32Util.h"
31 #include <commdlg.h>
32 #include <cderr.h>
33 #include <shlobj.h>
34 
35 
36 /************************************************************************
37  * AwtFileDialog fields
38  */
39 
40 /* WFileDialogPeer ids */
41 jfieldID AwtFileDialog::parentID;
42 jfieldID AwtFileDialog::fileFilterID;
43 jmethodID AwtFileDialog::setHWndMID;
44 jmethodID AwtFileDialog::handleSelectedMID;
45 jmethodID AwtFileDialog::handleCancelMID;
46 jmethodID AwtFileDialog::checkFilenameFilterMID;
47 jmethodID AwtFileDialog::isMultipleModeMID;
48 
49 /* FileDialog ids */
50 jfieldID AwtFileDialog::modeID;
51 jfieldID AwtFileDialog::dirID;
52 jfieldID AwtFileDialog::fileID;
53 jfieldID AwtFileDialog::filterID;
54 
55 /* Localized filter string */
56 #define MAX_FILTER_STRING       128
57 static TCHAR s_fileFilterString[MAX_FILTER_STRING];
58 /* Non-localized suffix of the filter string */
59 static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0");
60 
61 // Default limit of the output buffer.
62 #define SINGLE_MODE_BUFFER_LIMIT     MAX_PATH+1
63 #define MULTIPLE_MODE_BUFFER_LIMIT   32768
64 
65 // The name of the property holding the pointer to the OPENFILENAME structure.
66 static LPCTSTR OpenFileNameProp = TEXT("AWT_OFN");
67 
68 /***********************************************************************/
69 
70 void
Initialize(JNIEnv * env,jstring filterDescription)71 AwtFileDialog::Initialize(JNIEnv *env, jstring filterDescription)
72 {
73     int length = env->GetStringLength(filterDescription);
74     DASSERT(length + 1 < MAX_FILTER_STRING);
75     LPCTSTR tmp = JNU_GetStringPlatformChars(env, filterDescription, NULL);
76     _tcscpy_s(s_fileFilterString, MAX_FILTER_STRING, tmp);
77     JNU_ReleaseStringPlatformChars(env, filterDescription, tmp);
78 
79     //AdditionalString should be terminated by two NULL characters (Windows
80     //requirement), so we have to organize the following cycle and use memcpy
81     //unstead of, for example, strcat.
82     LPTSTR s = s_fileFilterString;
83     while (*s) {
84         ++s;
85         DASSERT(s < s_fileFilterString + MAX_FILTER_STRING);
86     }
87     DASSERT(s + sizeof(s_additionalString) < s_fileFilterString + MAX_FILTER_STRING);
88     memcpy(s, s_additionalString, sizeof(s_additionalString));
89 }
90 
FileDialogWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)91 LRESULT CALLBACK FileDialogWndProc(HWND hWnd, UINT message,
92                                         WPARAM wParam, LPARAM lParam)
93 {
94     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
95 
96     switch (message) {
97         case WM_COMMAND: {
98             if (LOWORD(wParam) == IDCANCEL)
99             {
100                 // Unlike Print/Page dialogs, we only handle IDCANCEL here and
101                 // don't handle IDOK. This is because user can press OK button
102                 // when no file is selected, and the dialog is not closed. So
103                 // OK button is handled in the CDN_FILEOK notification handler
104                 // (see FileDialogHookProc below)
105                 jobject peer = (jobject)(::GetProp(hWnd, ModalDialogPeerProp));
106                 env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0);
107             }
108             break;
109         }
110         case WM_SETICON: {
111             return 0;
112         }
113     }
114 
115     WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hWnd, NativeDialogWndProcProp));
116     return ComCtl32Util::GetInstance().DefWindowProc(lpfnWndProc, hWnd, message, wParam, lParam);
117 }
118 
119 static UINT_PTR CALLBACK
FileDialogHookProc(HWND hdlg,UINT uiMsg,WPARAM wParam,LPARAM lParam)120 FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
121 {
122     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
123 
124     TRY;
125 
126     HWND parent = ::GetParent(hdlg);
127 
128     switch(uiMsg) {
129         case WM_INITDIALOG: {
130             OPENFILENAME *ofn = (OPENFILENAME *)lParam;
131             jobject peer = (jobject)(ofn->lCustData);
132             env->CallVoidMethod(peer, AwtFileDialog::setHWndMID,
133                                 (jlong)parent);
134             ::SetProp(parent, ModalDialogPeerProp, reinterpret_cast<HANDLE>(peer));
135 
136             // fix for 4508670 - disable CS_SAVEBITS
137             DWORD style = ::GetClassLong(hdlg,GCL_STYLE);
138             ::SetClassLong(hdlg,GCL_STYLE,style & ~CS_SAVEBITS);
139 
140             // set appropriate icon for parentless dialogs
141             jobject awtParent = env->GetObjectField(peer, AwtFileDialog::parentID);
142             if (awtParent == NULL) {
143                 ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_BIG,
144                               (LPARAM)AwtToolkit::GetInstance().GetAwtIcon());
145             } else {
146                 AwtWindow *awtWindow = (AwtWindow *)JNI_GET_PDATA(awtParent);
147                 ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_BIG,
148                                                (LPARAM)(awtWindow->GetHIcon()));
149                 ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_SMALL,
150                                              (LPARAM)(awtWindow->GetHIconSm()));
151                 env->DeleteLocalRef(awtParent);
152             }
153 
154             // subclass dialog's parent to receive additional messages
155             WNDPROC lpfnWndProc = ComCtl32Util::GetInstance().SubclassHWND(parent,
156                                                                            FileDialogWndProc);
157             ::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc));
158 
159             ::SetProp(parent, OpenFileNameProp, (void *)lParam);
160 
161             break;
162         }
163         case WM_DESTROY: {
164             HIMC hIMC = ::ImmGetContext(hdlg);
165             if (hIMC != NULL) {
166                 ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
167                 ::ImmReleaseContext(hdlg, hIMC);
168             }
169 
170             WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(parent, NativeDialogWndProcProp));
171             ComCtl32Util::GetInstance().UnsubclassHWND(parent,
172                                                        FileDialogWndProc,
173                                                        lpfnWndProc);
174             ::RemoveProp(parent, ModalDialogPeerProp);
175             ::RemoveProp(parent, NativeDialogWndProcProp);
176             ::RemoveProp(parent, OpenFileNameProp);
177             break;
178         }
179         case WM_NOTIFY: {
180             OFNOTIFYEX *notifyEx = (OFNOTIFYEX *)lParam;
181             if (notifyEx) {
182                 jobject peer = (jobject)(::GetProp(parent, ModalDialogPeerProp));
183                 if (notifyEx->hdr.code == CDN_INCLUDEITEM) {
184                     LPITEMIDLIST pidl = (LPITEMIDLIST)notifyEx->pidl;
185                     // Get the filename and directory
186                     TCHAR szPath[MAX_PATH];
187                     if (!::SHGetPathFromIDList(pidl, szPath)) {
188                         return TRUE;
189                     }
190                     jstring strPath = JNU_NewStringPlatform(env, szPath);
191                     if (strPath == NULL) {
192                         throw std::bad_alloc();
193                     }
194                     // Call FilenameFilter.accept with path and filename
195                     UINT uRes = (env->CallBooleanMethod(peer,
196                         AwtFileDialog::checkFilenameFilterMID, strPath) == JNI_TRUE);
197                     env->DeleteLocalRef(strPath);
198                     return uRes;
199                 } else if (notifyEx->hdr.code == CDN_FILEOK) {
200                     // This notification is sent when user selects some file and presses
201                     // OK button; it is not sent when no file is selected. So it's time
202                     // to unblock all the windows blocked by this dialog as it will
203                     // be closed soon
204                     env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0);
205                 } else if (notifyEx->hdr.code == CDN_SELCHANGE) {
206                     // reallocate the buffer if the buffer is too small
207                     LPOPENFILENAME lpofn = (LPOPENFILENAME)GetProp(parent, OpenFileNameProp);
208 
209                     UINT nLength = CommDlg_OpenSave_GetSpec(parent, NULL, 0) +
210                                    CommDlg_OpenSave_GetFolderPath(parent, NULL, 0);
211 
212                     if (lpofn->nMaxFile < nLength)
213                     {
214                         // allocate new buffer
215                         LPTSTR newBuffer = new TCHAR[nLength];
216 
217                         if (newBuffer) {
218                             memset(newBuffer, 0, nLength * sizeof(TCHAR));
219                             LPTSTR oldBuffer = lpofn->lpstrFile;
220                             lpofn->lpstrFile = newBuffer;
221                             lpofn->nMaxFile = nLength;
222                             // free the previously allocated buffer
223                             if (oldBuffer) {
224                                 delete[] oldBuffer;
225                             }
226 
227                         }
228                     }
229                 }
230             }
231             break;
232         }
233     }
234 
235     return FALSE;
236 
237     CATCH_BAD_ALLOC_RET(TRUE);
238 }
239 
240 void
Show(void * p)241 AwtFileDialog::Show(void *p)
242 {
243     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
244     jobject peer;
245     LPTSTR fileBuffer = NULL;
246     LPTSTR currentDirectory = NULL;
247     jint mode = 0;
248     BOOL result = FALSE;
249     DWORD dlgerr;
250     jstring directory = NULL;
251     jstring title = NULL;
252     jstring file = NULL;
253     jobject fileFilter = NULL;
254     jobject target = NULL;
255     jobject parent = NULL;
256     AwtComponent* awtParent = NULL;
257     jboolean multipleMode = JNI_FALSE;
258 
259     OPENFILENAME ofn;
260     memset(&ofn, 0, sizeof(ofn));
261 
262     peer = (jobject)p;
263 
264     try {
265         DASSERT(peer);
266         target = env->GetObjectField(peer, AwtObject::targetID);
267         parent = env->GetObjectField(peer, AwtFileDialog::parentID);
268         if (parent != NULL) {
269             awtParent = (AwtComponent *)JNI_GET_PDATA(parent);
270         }
271 //      DASSERT(awtParent);
272         title = (jstring)(env)->GetObjectField(target, AwtDialog::titleID);
273         HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL;
274 
275         if (title == NULL || env->GetStringLength(title)==0) {
276             title = JNU_NewStringPlatform(env, L" ");
277             if (title == NULL) {
278                 throw std::bad_alloc();
279             }
280         }
281 
282         JavaStringBuffer titleBuffer(env, title);
283         directory =
284             (jstring)env->GetObjectField(target, AwtFileDialog::dirID);
285         JavaStringBuffer directoryBuffer(env, directory);
286 
287         multipleMode = env->CallBooleanMethod(peer, AwtFileDialog::isMultipleModeMID);
288 
289         UINT bufferLimit;
290         if (multipleMode == JNI_TRUE) {
291             bufferLimit = MULTIPLE_MODE_BUFFER_LIMIT;
292         } else {
293             bufferLimit = SINGLE_MODE_BUFFER_LIMIT;
294         }
295         LPTSTR fileBuffer = new TCHAR[bufferLimit];
296         memset(fileBuffer, 0, bufferLimit * sizeof(TCHAR));
297 
298         file = (jstring)env->GetObjectField(target, AwtFileDialog::fileID);
299         if (file != NULL) {
300             LPCTSTR tmp = JNU_GetStringPlatformChars(env, file, NULL);
301             _tcsncpy(fileBuffer, tmp, bufferLimit - 2); // the fileBuffer is double null terminated string
302             JNU_ReleaseStringPlatformChars(env, file, tmp);
303         } else {
304             fileBuffer[0] = _T('\0');
305         }
306 
307         ofn.lStructSize = sizeof(ofn);
308         ofn.lpstrFilter = s_fileFilterString;
309         ofn.nFilterIndex = 1;
310         /*
311           Fix for 6488834.
312           To disable Win32 native parent modality we have to set
313           hwndOwner field to either NULL or some hidden window. For
314           parentless dialogs we use NULL to show them in the taskbar,
315           and for all other dialogs AwtToolkit's HWND is used.
316         */
317         if (awtParent != NULL)
318         {
319             ofn.hwndOwner = AwtToolkit::GetInstance().GetHWnd();
320         }
321         else
322         {
323             ofn.hwndOwner = NULL;
324         }
325         ofn.lpstrFile = fileBuffer;
326         ofn.nMaxFile = bufferLimit;
327         ofn.lpstrTitle = titleBuffer;
328         ofn.lpstrInitialDir = directoryBuffer;
329         ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
330                     OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING;
331         fileFilter = env->GetObjectField(peer,
332         AwtFileDialog::fileFilterID);
333         if (!JNU_IsNull(env,fileFilter)) {
334             ofn.Flags |= OFN_ENABLEINCLUDENOTIFY;
335         }
336         ofn.lCustData = (LPARAM)peer;
337         ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc;
338 
339         if (multipleMode == JNI_TRUE) {
340             ofn.Flags |= OFN_ALLOWMULTISELECT;
341         }
342 
343         // Save current directory, so we can reset if it changes.
344         currentDirectory = new TCHAR[MAX_PATH+1];
345 
346         VERIFY(::GetCurrentDirectory(MAX_PATH, currentDirectory) > 0);
347 
348         mode = env->GetIntField(target, AwtFileDialog::modeID);
349 
350         AwtDialog::CheckInstallModalHook();
351 
352         // show the Win32 file dialog
353         if (mode == java_awt_FileDialog_LOAD) {
354             result = ::GetOpenFileName(&ofn);
355         } else {
356             result = ::GetSaveFileName(&ofn);
357         }
358         // Fix for 4181310: FileDialog does not show up.
359         // If the dialog is not shown because of invalid file name
360         // replace the file name by empty string.
361         if (!result) {
362             dlgerr = ::CommDlgExtendedError();
363             if (dlgerr == FNERR_INVALIDFILENAME) {
364                 _tcscpy_s(fileBuffer, bufferLimit, TEXT(""));
365                 if (mode == java_awt_FileDialog_LOAD) {
366                     result = ::GetOpenFileName(&ofn);
367                 } else {
368                     result = ::GetSaveFileName(&ofn);
369                 }
370             }
371         }
372 
373         AwtDialog::CheckUninstallModalHook();
374 
375         DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L);
376 
377         AwtDialog::ModalActivateNextWindow(NULL, target, peer);
378 
379         VERIFY(::SetCurrentDirectory(currentDirectory));
380 
381         // Report result to peer.
382         if (result) {
383             jint length = multipleMode
384                     ? (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile)
385                     : (jint)_tcslen(ofn.lpstrFile);
386             jcharArray jnames = env->NewCharArray(length);
387             if (jnames == NULL) {
388                 throw std::bad_alloc();
389             }
390             env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile);
391 
392             env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames);
393             env->DeleteLocalRef(jnames);
394         } else {
395             env->CallVoidMethod(peer, AwtFileDialog::handleCancelMID);
396         }
397         DASSERT(!safe_ExceptionOccurred(env));
398     } catch (...) {
399 
400         env->DeleteLocalRef(target);
401         env->DeleteLocalRef(parent);
402         env->DeleteLocalRef(title);
403         env->DeleteLocalRef(directory);
404         env->DeleteLocalRef(file);
405         env->DeleteLocalRef(fileFilter);
406         env->DeleteGlobalRef(peer);
407 
408         delete[] currentDirectory;
409         if (ofn.lpstrFile)
410             delete[] ofn.lpstrFile;
411         throw;
412     }
413 
414     env->DeleteLocalRef(target);
415     env->DeleteLocalRef(parent);
416     env->DeleteLocalRef(title);
417     env->DeleteLocalRef(directory);
418     env->DeleteLocalRef(file);
419     env->DeleteLocalRef(fileFilter);
420     env->DeleteGlobalRef(peer);
421 
422     delete[] currentDirectory;
423     if (ofn.lpstrFile)
424         delete[] ofn.lpstrFile;
425 }
426 
InheritsNativeMouseWheelBehavior()427 BOOL AwtFileDialog::InheritsNativeMouseWheelBehavior() {return true;}
428 
_DisposeOrHide(void * param)429 void AwtFileDialog::_DisposeOrHide(void *param)
430 {
431     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
432 
433     jobject self = (jobject)param;
434 
435     HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID));
436     if (::IsWindow(hdlg))
437     {
438         ::SendMessage(hdlg, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0),
439                       (LPARAM)hdlg);
440     }
441 
442     env->DeleteGlobalRef(self);
443 }
444 
_ToFront(void * param)445 void AwtFileDialog::_ToFront(void *param)
446 {
447     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
448 
449     jobject self = (jobject)param;
450     HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID));
451     if (::IsWindow(hdlg))
452     {
453         ::SetWindowPos(hdlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
454     }
455 
456     env->DeleteGlobalRef(self);
457 }
458 
_ToBack(void * param)459 void AwtFileDialog::_ToBack(void *param)
460 {
461     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
462 
463     jobject self = (jobject)param;
464     HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID));
465     if (::IsWindow(hdlg))
466     {
467         ::SetWindowPos(hdlg, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
468     }
469 
470     env->DeleteGlobalRef(self);
471 }
472 
473 // Returns the length of the double null terminated output buffer
GetBufferLength(LPTSTR buffer,UINT limit)474 UINT AwtFileDialog::GetBufferLength(LPTSTR buffer, UINT limit)
475 {
476     UINT index = 0;
477     while ((index < limit) &&
478            (buffer[index] != NULL || buffer[index+1] != NULL))
479     {
480         index++;
481     }
482     return index;
483 }
484 
485 /************************************************************************
486  * WFileDialogPeer native methods
487  */
488 
489 extern "C" {
490 
491 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer_initIDs(JNIEnv * env,jclass cls)492 Java_sun_awt_windows_WFileDialogPeer_initIDs(JNIEnv *env, jclass cls)
493 {
494     TRY;
495 
496     AwtFileDialog::parentID =
497         env->GetFieldID(cls, "parent", "Lsun/awt/windows/WComponentPeer;");
498     DASSERT(AwtFileDialog::parentID != NULL);
499     CHECK_NULL(AwtFileDialog::parentID);
500 
501     AwtFileDialog::fileFilterID =
502         env->GetFieldID(cls, "fileFilter", "Ljava/io/FilenameFilter;");
503     DASSERT(AwtFileDialog::fileFilterID != NULL);
504     CHECK_NULL(AwtFileDialog::fileFilterID);
505 
506     AwtFileDialog::setHWndMID = env->GetMethodID(cls, "setHWnd", "(J)V");
507     DASSERT(AwtFileDialog::setHWndMID != NULL);
508     CHECK_NULL(AwtFileDialog::setHWndMID);
509 
510     AwtFileDialog::handleSelectedMID =
511         env->GetMethodID(cls, "handleSelected", "([C)V");
512     DASSERT(AwtFileDialog::handleSelectedMID != NULL);
513     CHECK_NULL(AwtFileDialog::handleSelectedMID);
514 
515     AwtFileDialog::handleCancelMID =
516         env->GetMethodID(cls, "handleCancel", "()V");
517     DASSERT(AwtFileDialog::handleCancelMID != NULL);
518     CHECK_NULL(AwtFileDialog::handleCancelMID);
519 
520     AwtFileDialog::checkFilenameFilterMID =
521         env->GetMethodID(cls, "checkFilenameFilter", "(Ljava/lang/String;)Z");
522     DASSERT(AwtFileDialog::checkFilenameFilterMID != NULL);
523     CHECK_NULL(AwtFileDialog::checkFilenameFilterMID);
524 
525     AwtFileDialog::isMultipleModeMID = env->GetMethodID(cls, "isMultipleMode", "()Z");
526     DASSERT(AwtFileDialog::isMultipleModeMID != NULL);
527     CHECK_NULL(AwtFileDialog::isMultipleModeMID);
528 
529     /* java.awt.FileDialog fields */
530     cls = env->FindClass("java/awt/FileDialog");
531     CHECK_NULL(cls);
532 
533     AwtFileDialog::modeID = env->GetFieldID(cls, "mode", "I");
534     DASSERT(AwtFileDialog::modeID != NULL);
535     CHECK_NULL(AwtFileDialog::modeID);
536 
537     AwtFileDialog::dirID = env->GetFieldID(cls, "dir", "Ljava/lang/String;");
538     DASSERT(AwtFileDialog::dirID != NULL);
539     CHECK_NULL(AwtFileDialog::dirID);
540 
541     AwtFileDialog::fileID = env->GetFieldID(cls, "file", "Ljava/lang/String;");
542     DASSERT(AwtFileDialog::fileID != NULL);
543     CHECK_NULL(AwtFileDialog::fileID);
544 
545     AwtFileDialog::filterID =
546         env->GetFieldID(cls, "filter", "Ljava/io/FilenameFilter;");
547     DASSERT(AwtFileDialog::filterID != NULL);
548 
549     CATCH_BAD_ALLOC;
550 }
551 
552 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer_setFilterString(JNIEnv * env,jclass cls,jstring filterDescription)553 Java_sun_awt_windows_WFileDialogPeer_setFilterString(JNIEnv *env, jclass cls,
554                                                      jstring filterDescription)
555 {
556     TRY;
557 
558     AwtFileDialog::Initialize(env, filterDescription);
559 
560     CATCH_BAD_ALLOC;
561 }
562 
563 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer__1show(JNIEnv * env,jobject peer)564 Java_sun_awt_windows_WFileDialogPeer__1show(JNIEnv *env, jobject peer)
565 {
566     TRY;
567 
568     /*
569      * Fix for 4906972.
570      * 'peer' reference has to be global as it's used further in another thread.
571      */
572     jobject peerGlobal = env->NewGlobalRef(peer);
573 
574     if (!AwtToolkit::GetInstance().PostMessage(WM_AWT_INVOKE_METHOD,
575                              (WPARAM)AwtFileDialog::Show, (LPARAM)peerGlobal)) {
576         env->DeleteGlobalRef(peerGlobal);
577     }
578 
579     CATCH_BAD_ALLOC;
580 }
581 
582 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer__1dispose(JNIEnv * env,jobject peer)583 Java_sun_awt_windows_WFileDialogPeer__1dispose(JNIEnv *env, jobject peer)
584 {
585     TRY_NO_VERIFY;
586 
587     jobject peerGlobal = env->NewGlobalRef(peer);
588 
589     AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide,
590         (void *)peerGlobal);
591     // peerGlobal ref is deleted in _DisposeOrHide
592 
593     CATCH_BAD_ALLOC;
594 }
595 
596 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer__1hide(JNIEnv * env,jobject peer)597 Java_sun_awt_windows_WFileDialogPeer__1hide(JNIEnv *env, jobject peer)
598 {
599     TRY;
600 
601     jobject peerGlobal = env->NewGlobalRef(peer);
602 
603     AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide,
604         (void *)peerGlobal);
605     // peerGlobal ref is deleted in _DisposeOrHide
606 
607     CATCH_BAD_ALLOC;
608 }
609 
610 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer_toFront(JNIEnv * env,jobject peer)611 Java_sun_awt_windows_WFileDialogPeer_toFront(JNIEnv *env, jobject peer)
612 {
613     TRY;
614 
615     AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToFront,
616                                        (void *)(env->NewGlobalRef(peer)));
617     // global ref is deleted in _ToFront
618 
619     CATCH_BAD_ALLOC;
620 }
621 
622 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer_toBack(JNIEnv * env,jobject peer)623 Java_sun_awt_windows_WFileDialogPeer_toBack(JNIEnv *env, jobject peer)
624 {
625     TRY;
626 
627     AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToBack,
628                                        (void *)(env->NewGlobalRef(peer)));
629     // global ref is deleted in _ToBack
630 
631     CATCH_BAD_ALLOC;
632 }
633 
ScaleDownX(int x,HWND hwnd)634 int ScaleDownX(int x, HWND hwnd) {
635     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(hwnd);
636     Devices::InstanceAccess devices;
637     AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
638     return device == NULL ? x : device->ScaleDownX(x);
639 }
640 
ScaleDownY(int y,HWND hwnd)641 int ScaleDownY(int y, HWND hwnd) {
642     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(hwnd);
643     Devices::InstanceAccess devices;
644     AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
645     return device == NULL ? y : device->ScaleDownY(y);
646 }
647 
_GetLocationOnScreen(void * param)648 jobject AwtFileDialog::_GetLocationOnScreen(void *param)
649 {
650     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
651 
652     jobject result = NULL;
653     HWND hwnd = (HWND)env->GetLongField((jobject)param, AwtComponent::hwndID);
654 
655     if (::IsWindow(hwnd))
656     {
657         RECT rect;
658         VERIFY(::GetWindowRect(hwnd, &rect));
659         result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
660                        ScaleDownX(rect.left, hwnd), ScaleDownY(rect.top, hwnd));
661     }
662 
663     if (result != NULL)
664     {
665         jobject resultRef = env->NewGlobalRef(result);
666         env->DeleteLocalRef(result);
667         return resultRef;
668     }
669     else
670     {
671         return NULL;
672     }
673 }
674 
675 /*
676  * Class:     sun_awt_windows_WFileDialogPeer
677  * Method:    getLocationOnScreen
678  * Signature: ()Ljava/awt/Point;
679  */
680 JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WFileDialogPeer_getLocationOnScreen(JNIEnv * env,jobject peer)681 Java_sun_awt_windows_WFileDialogPeer_getLocationOnScreen(JNIEnv *env,
682                                                                  jobject peer) {
683     TRY;
684 
685     jobject peerRef = env->NewGlobalRef(peer);
686     jobject resultRef = (jobject)AwtToolkit::GetInstance().SyncCall(
687         (void*(*)(void*))AwtFileDialog::_GetLocationOnScreen, (void *)peerRef);
688     env->DeleteGlobalRef(peerRef);
689 
690     if (resultRef != NULL)
691     {
692         jobject result = env->NewLocalRef(resultRef);
693         env->DeleteGlobalRef(resultRef);
694         return result;
695     }
696 
697     return NULL;
698 
699     CATCH_BAD_ALLOC_RET(NULL);
700 }
701 
702 } /* extern "C" */
703