1 /*
   2  * Copyright (c) 1996, 2014, 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
  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 
  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     }
 111 
 112     WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hWnd, NativeDialogWndProcProp));
 113     return ComCtl32Util::GetInstance().DefWindowProc(lpfnWndProc, hWnd, message, wParam, lParam);
 114 }
 115 
 116 static UINT_PTR CALLBACK
 117 FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
 118 {
 119     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 120 
 121     TRY;
 122 
 123     HWND parent = ::GetParent(hdlg);
 124 
 125     switch(uiMsg) {
 126         case WM_INITDIALOG: {
 127             OPENFILENAME *ofn = (OPENFILENAME *)lParam;
 128             jobject peer = (jobject)(ofn->lCustData);
 129             env->CallVoidMethod(peer, AwtFileDialog::setHWndMID,
 130                                 (jlong)parent);
 131             ::SetProp(parent, ModalDialogPeerProp, reinterpret_cast<HANDLE>(peer));
 132 
 133             // fix for 4508670 - disable CS_SAVEBITS
 134             DWORD style = ::GetClassLong(hdlg,GCL_STYLE);
 135             ::SetClassLong(hdlg,GCL_STYLE,style & ~CS_SAVEBITS);
 136 
 137             // set appropriate icon for parentless dialogs
 138             jobject awtParent = env->GetObjectField(peer, AwtFileDialog::parentID);
 139             if (awtParent == NULL) {
 140                 ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_BIG,
 141                               (LPARAM)AwtToolkit::GetInstance().GetAwtIcon());
 142             } else {
 143                 env->DeleteLocalRef(awtParent);
 144             }
 145 
 146             // subclass dialog's parent to receive additional messages
 147             WNDPROC lpfnWndProc = ComCtl32Util::GetInstance().SubclassHWND(parent,
 148                                                                            FileDialogWndProc);
 149             ::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc));
 150 
 151             ::SetProp(parent, OpenFileNameProp, (void *)lParam);
 152 
 153             break;
 154         }
 155         case WM_DESTROY: {
 156             HIMC hIMC = ::ImmGetContext(hdlg);
 157             if (hIMC != NULL) {
 158                 ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
 159                 ::ImmReleaseContext(hdlg, hIMC);
 160             }
 161 
 162             WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(parent, NativeDialogWndProcProp));
 163             ComCtl32Util::GetInstance().UnsubclassHWND(parent,
 164                                                        FileDialogWndProc,
 165                                                        lpfnWndProc);
 166             ::RemoveProp(parent, ModalDialogPeerProp);
 167             ::RemoveProp(parent, NativeDialogWndProcProp);
 168             ::RemoveProp(parent, OpenFileNameProp);
 169             break;
 170         }
 171         case WM_NOTIFY: {
 172             OFNOTIFYEX *notifyEx = (OFNOTIFYEX *)lParam;
 173             if (notifyEx) {
 174                 jobject peer = (jobject)(::GetProp(parent, ModalDialogPeerProp));
 175                 if (notifyEx->hdr.code == CDN_INCLUDEITEM) {
 176                     LPITEMIDLIST pidl = (LPITEMIDLIST)notifyEx->pidl;
 177                     // Get the filename and directory
 178                     TCHAR szPath[MAX_PATH];
 179                     if (!::SHGetPathFromIDList(pidl, szPath)) {
 180                         return TRUE;
 181                     }
 182                     jstring strPath = JNU_NewStringPlatform(env, szPath);
 183                     if (strPath == NULL) {
 184                         throw std::bad_alloc();
 185                     }
 186                     // Call FilenameFilter.accept with path and filename
 187                     UINT uRes = (env->CallBooleanMethod(peer,
 188                         AwtFileDialog::checkFilenameFilterMID, strPath) == JNI_TRUE);
 189                     env->DeleteLocalRef(strPath);
 190                     return uRes;
 191                 } else if (notifyEx->hdr.code == CDN_FILEOK) {
 192                     // This notification is sent when user selects some file and presses
 193                     // OK button; it is not sent when no file is selected. So it's time
 194                     // to unblock all the windows blocked by this dialog as it will
 195                     // be closed soon
 196                     env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0);
 197                 } else if (notifyEx->hdr.code == CDN_SELCHANGE) {
 198                     // reallocate the buffer if the buffer is too small
 199                     LPOPENFILENAME lpofn = (LPOPENFILENAME)GetProp(parent, OpenFileNameProp);
 200 
 201                     UINT nLength = CommDlg_OpenSave_GetSpec(parent, NULL, 0) +
 202                                    CommDlg_OpenSave_GetFolderPath(parent, NULL, 0);
 203 
 204                     if (lpofn->nMaxFile < nLength)
 205                     {
 206                         // allocate new buffer
 207                         LPTSTR newBuffer = new TCHAR[nLength];
 208 
 209                         if (newBuffer) {
 210                             memset(newBuffer, 0, nLength * sizeof(TCHAR));
 211                             LPTSTR oldBuffer = lpofn->lpstrFile;
 212                             lpofn->lpstrFile = newBuffer;
 213                             lpofn->nMaxFile = nLength;
 214                             // free the previously allocated buffer
 215                             if (oldBuffer) {
 216                                 delete[] oldBuffer;
 217                             }
 218 
 219                         }
 220                     }
 221                 }
 222             }
 223             break;
 224         }
 225     }
 226 
 227     return FALSE;
 228 
 229     CATCH_BAD_ALLOC_RET(TRUE);
 230 }
 231 
 232 void
 233 AwtFileDialog::Show(void *p)
 234 {
 235     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 236     jobject peer;
 237     LPTSTR fileBuffer = NULL;
 238     LPTSTR currentDirectory = NULL;
 239     jint mode = 0;
 240     BOOL result = FALSE;
 241     DWORD dlgerr;
 242     jstring directory = NULL;
 243     jstring title = NULL;
 244     jstring file = NULL;
 245     jobject fileFilter = NULL;
 246     jobject target = NULL;
 247     jobject parent = NULL;
 248     AwtComponent* awtParent = NULL;
 249     jboolean multipleMode = JNI_FALSE;
 250 
 251     OPENFILENAME ofn;
 252     memset(&ofn, 0, sizeof(ofn));
 253 
 254     /*
 255      * There's a situation (see bug 4906972) when InvokeFunction (by which this method is called)
 256      * returnes earlier than this method returnes. Probably it's caused due to ReplyMessage system call.
 257      * So for the avoidance of this mistiming we need to make new global reference here
 258      * (not local as it's used by the hook) and then manage it independently of the calling thread.
 259      */
 260     peer = env->NewGlobalRef((jobject)p);
 261 
 262     try {
 263         DASSERT(peer);
 264         target = env->GetObjectField(peer, AwtObject::targetID);
 265         parent = env->GetObjectField(peer, AwtFileDialog::parentID);
 266         if (parent != NULL) {
 267             awtParent = (AwtComponent *)JNI_GET_PDATA(parent);
 268         }
 269 //      DASSERT(awtParent);
 270         title = (jstring)(env)->GetObjectField(target, AwtDialog::titleID);
 271         HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL;
 272 
 273         if (title == NULL || env->GetStringLength(title)==0) {
 274             title = JNU_NewStringPlatform(env, L" ");
 275             if (title == NULL) {
 276                 throw std::bad_alloc();
 277             }
 278         }
 279 
 280         JavaStringBuffer titleBuffer(env, title);
 281         directory =
 282             (jstring)env->GetObjectField(target, AwtFileDialog::dirID);
 283         JavaStringBuffer directoryBuffer(env, directory);
 284 
 285         multipleMode = env->CallBooleanMethod(peer, AwtFileDialog::isMultipleModeMID);
 286 
 287         UINT bufferLimit;
 288         if (multipleMode == JNI_TRUE) {
 289             bufferLimit = MULTIPLE_MODE_BUFFER_LIMIT;
 290         } else {
 291             bufferLimit = SINGLE_MODE_BUFFER_LIMIT;
 292         }
 293         LPTSTR fileBuffer = new TCHAR[bufferLimit];
 294         memset(fileBuffer, 0, bufferLimit * sizeof(TCHAR));
 295 
 296         file = (jstring)env->GetObjectField(target, AwtFileDialog::fileID);
 297         if (file != NULL) {
 298             LPCTSTR tmp = JNU_GetStringPlatformChars(env, file, NULL);
 299             _tcsncpy(fileBuffer, tmp, bufferLimit - 2); // the fileBuffer is double null terminated string
 300             JNU_ReleaseStringPlatformChars(env, file, tmp);
 301         } else {
 302             fileBuffer[0] = _T('\0');
 303         }
 304 
 305         ofn.lStructSize = sizeof(ofn);
 306         ofn.lpstrFilter = s_fileFilterString;
 307         ofn.nFilterIndex = 1;
 308         /*
 309           Fix for 6488834.
 310           To disable Win32 native parent modality we have to set
 311           hwndOwner field to either NULL or some hidden window. For
 312           parentless dialogs we use NULL to show them in the taskbar,
 313           and for all other dialogs AwtToolkit's HWND is used.
 314         */
 315         if (awtParent != NULL)
 316         {
 317             ofn.hwndOwner = AwtToolkit::GetInstance().GetHWnd();
 318         }
 319         else
 320         {
 321             ofn.hwndOwner = NULL;
 322         }
 323         ofn.lpstrFile = fileBuffer;
 324         ofn.nMaxFile = bufferLimit;
 325         ofn.lpstrTitle = titleBuffer;
 326         ofn.lpstrInitialDir = directoryBuffer;
 327         ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
 328                     OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING;
 329         fileFilter = env->GetObjectField(peer,
 330         AwtFileDialog::fileFilterID);
 331         if (!JNU_IsNull(env,fileFilter)) {
 332             ofn.Flags |= OFN_ENABLEINCLUDENOTIFY;
 333         }
 334         ofn.lCustData = (LPARAM)peer;
 335         ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc;
 336 
 337         if (multipleMode == JNI_TRUE) {
 338             ofn.Flags |= OFN_ALLOWMULTISELECT;
 339         }
 340 
 341         // Save current directory, so we can reset if it changes.
 342         currentDirectory = new TCHAR[MAX_PATH+1];
 343 
 344         VERIFY(::GetCurrentDirectory(MAX_PATH, currentDirectory) > 0);
 345 
 346         mode = env->GetIntField(target, AwtFileDialog::modeID);
 347 
 348         AwtDialog::CheckInstallModalHook();
 349 
 350         // show the Win32 file dialog
 351         if (mode == java_awt_FileDialog_LOAD) {
 352             result = AwtFileDialog::GetOpenFileName(&ofn);
 353         } else {
 354             result = AwtFileDialog::GetSaveFileName(&ofn);
 355         }
 356         // Fix for 4181310: FileDialog does not show up.
 357         // If the dialog is not shown because of invalid file name
 358         // replace the file name by empty string.
 359         if (!result) {
 360             dlgerr = ::CommDlgExtendedError();
 361             if (dlgerr == FNERR_INVALIDFILENAME) {
 362                 _tcscpy_s(fileBuffer, bufferLimit, TEXT(""));
 363                 if (mode == java_awt_FileDialog_LOAD) {
 364                     result = AwtFileDialog::GetOpenFileName(&ofn);
 365                 } else {
 366                     result = AwtFileDialog::GetSaveFileName(&ofn);
 367                 }
 368             }
 369         }
 370 
 371         AwtDialog::CheckUninstallModalHook();
 372 
 373         DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L);
 374 
 375         AwtDialog::ModalActivateNextWindow(NULL, target, peer);
 376 
 377         VERIFY(::SetCurrentDirectory(currentDirectory));
 378 
 379         // Report result to peer.
 380         if (result) {
 381             jint length = multipleMode
 382                     ? (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile)
 383                     : (jint)_tcslen(ofn.lpstrFile);
 384             jcharArray jnames = env->NewCharArray(length);
 385             if (jnames == NULL) {
 386                 throw std::bad_alloc();
 387             }
 388             env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile);
 389 
 390             env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames);
 391             env->DeleteLocalRef(jnames);
 392         } else {
 393             env->CallVoidMethod(peer, AwtFileDialog::handleCancelMID);
 394         }
 395         DASSERT(!safe_ExceptionOccurred(env));
 396     } catch (...) {
 397 
 398         env->DeleteLocalRef(target);
 399         env->DeleteLocalRef(parent);
 400         env->DeleteLocalRef(title);
 401         env->DeleteLocalRef(directory);
 402         env->DeleteLocalRef(file);
 403         env->DeleteLocalRef(fileFilter);
 404         env->DeleteGlobalRef(peer);
 405 
 406         delete[] currentDirectory;
 407         if (ofn.lpstrFile)
 408             delete[] ofn.lpstrFile;
 409         throw;
 410     }
 411 
 412     env->DeleteLocalRef(target);
 413     env->DeleteLocalRef(parent);
 414     env->DeleteLocalRef(title);
 415     env->DeleteLocalRef(directory);
 416     env->DeleteLocalRef(file);
 417     env->DeleteLocalRef(fileFilter);
 418     env->DeleteGlobalRef(peer);
 419 
 420     delete[] currentDirectory;
 421     if (ofn.lpstrFile)
 422         delete[] ofn.lpstrFile;
 423 }
 424 
 425 BOOL
 426 AwtFileDialog::GetOpenFileName(LPOPENFILENAME data) {
 427     return static_cast<BOOL>(reinterpret_cast<INT_PTR>(
 428         AwtToolkit::GetInstance().InvokeFunction((void*(*)(void*))
 429                      ::GetOpenFileName, data)));
 430 
 431 }
 432 
 433 BOOL
 434 AwtFileDialog::GetSaveFileName(LPOPENFILENAME data) {
 435     return static_cast<BOOL>(reinterpret_cast<INT_PTR>(
 436         AwtToolkit::GetInstance().InvokeFunction((void *(*)(void *))
 437                      ::GetSaveFileName, data)));
 438 
 439 }
 440 
 441 BOOL AwtFileDialog::InheritsNativeMouseWheelBehavior() {return true;}
 442 
 443 void AwtFileDialog::_DisposeOrHide(void *param)
 444 {
 445     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 446 
 447     jobject self = (jobject)param;
 448 
 449     HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID));
 450     if (::IsWindow(hdlg))
 451     {
 452         ::SendMessage(hdlg, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0),
 453                       (LPARAM)hdlg);
 454     }
 455 
 456     env->DeleteGlobalRef(self);
 457 }
 458 
 459 void AwtFileDialog::_ToFront(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_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 468     }
 469 
 470     env->DeleteGlobalRef(self);
 471 }
 472 
 473 void AwtFileDialog::_ToBack(void *param)
 474 {
 475     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 476 
 477     jobject self = (jobject)param;
 478     HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID));
 479     if (::IsWindow(hdlg))
 480     {
 481         ::SetWindowPos(hdlg, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
 482     }
 483 
 484     env->DeleteGlobalRef(self);
 485 }
 486 
 487 // Returns the length of the double null terminated output buffer
 488 UINT AwtFileDialog::GetBufferLength(LPTSTR buffer, UINT limit)
 489 {
 490     UINT index = 0;
 491     while ((index < limit) &&
 492            (buffer[index] != NULL || buffer[index+1] != NULL))
 493     {
 494         index++;
 495     }
 496     return index;
 497 }
 498 
 499 /************************************************************************
 500  * WFileDialogPeer native methods
 501  */
 502 
 503 extern "C" {
 504 
 505 JNIEXPORT void JNICALL
 506 Java_sun_awt_windows_WFileDialogPeer_initIDs(JNIEnv *env, jclass cls)
 507 {
 508     TRY;
 509 
 510     AwtFileDialog::parentID =
 511         env->GetFieldID(cls, "parent", "Lsun/awt/windows/WComponentPeer;");
 512     DASSERT(AwtFileDialog::parentID != NULL);
 513     CHECK_NULL(AwtFileDialog::parentID);
 514 
 515     AwtFileDialog::fileFilterID =
 516         env->GetFieldID(cls, "fileFilter", "Ljava/io/FilenameFilter;");
 517     DASSERT(AwtFileDialog::fileFilterID != NULL);
 518     CHECK_NULL(AwtFileDialog::fileFilterID);
 519 
 520     AwtFileDialog::setHWndMID = env->GetMethodID(cls, "setHWnd", "(J)V");
 521     DASSERT(AwtFileDialog::setHWndMID != NULL);
 522     CHECK_NULL(AwtFileDialog::setHWndMID);
 523 
 524     AwtFileDialog::handleSelectedMID =
 525         env->GetMethodID(cls, "handleSelected", "([C)V");
 526     DASSERT(AwtFileDialog::handleSelectedMID != NULL);
 527     CHECK_NULL(AwtFileDialog::handleSelectedMID);
 528 
 529     AwtFileDialog::handleCancelMID =
 530         env->GetMethodID(cls, "handleCancel", "()V");
 531     DASSERT(AwtFileDialog::handleCancelMID != NULL);
 532     CHECK_NULL(AwtFileDialog::handleCancelMID);
 533 
 534     AwtFileDialog::checkFilenameFilterMID =
 535         env->GetMethodID(cls, "checkFilenameFilter", "(Ljava/lang/String;)Z");
 536     DASSERT(AwtFileDialog::checkFilenameFilterMID != NULL);
 537     CHECK_NULL(AwtFileDialog::checkFilenameFilterMID);
 538 
 539     AwtFileDialog::isMultipleModeMID = env->GetMethodID(cls, "isMultipleMode", "()Z");
 540     DASSERT(AwtFileDialog::isMultipleModeMID != NULL);
 541     CHECK_NULL(AwtFileDialog::isMultipleModeMID);
 542 
 543     /* java.awt.FileDialog fields */
 544     cls = env->FindClass("java/awt/FileDialog");
 545     CHECK_NULL(cls);
 546 
 547     AwtFileDialog::modeID = env->GetFieldID(cls, "mode", "I");
 548     DASSERT(AwtFileDialog::modeID != NULL);
 549     CHECK_NULL(AwtFileDialog::modeID);
 550 
 551     AwtFileDialog::dirID = env->GetFieldID(cls, "dir", "Ljava/lang/String;");
 552     DASSERT(AwtFileDialog::dirID != NULL);
 553     CHECK_NULL(AwtFileDialog::dirID);
 554 
 555     AwtFileDialog::fileID = env->GetFieldID(cls, "file", "Ljava/lang/String;");
 556     DASSERT(AwtFileDialog::fileID != NULL);
 557     CHECK_NULL(AwtFileDialog::fileID);
 558 
 559     AwtFileDialog::filterID =
 560         env->GetFieldID(cls, "filter", "Ljava/io/FilenameFilter;");
 561     DASSERT(AwtFileDialog::filterID != NULL);
 562 
 563     CATCH_BAD_ALLOC;
 564 }
 565 
 566 JNIEXPORT void JNICALL
 567 Java_sun_awt_windows_WFileDialogPeer_setFilterString(JNIEnv *env, jclass cls,
 568                                                      jstring filterDescription)
 569 {
 570     TRY;
 571 
 572     AwtFileDialog::Initialize(env, filterDescription);
 573 
 574     CATCH_BAD_ALLOC;
 575 }
 576 
 577 JNIEXPORT void JNICALL
 578 Java_sun_awt_windows_WFileDialogPeer__1show(JNIEnv *env, jobject peer)
 579 {
 580     TRY;
 581 
 582     /*
 583      * Fix for 4906972.
 584      * 'peer' reference has to be global as it's used further in another thread.
 585      */
 586     jobject peerGlobal = env->NewGlobalRef(peer);
 587 
 588     AwtToolkit::GetInstance().InvokeFunction(AwtFileDialog::Show, peerGlobal);
 589 
 590     env->DeleteGlobalRef(peerGlobal);
 591 
 592     CATCH_BAD_ALLOC;
 593 }
 594 
 595 JNIEXPORT void JNICALL
 596 Java_sun_awt_windows_WFileDialogPeer__1dispose(JNIEnv *env, jobject peer)
 597 {
 598     TRY_NO_VERIFY;
 599 
 600     jobject peerGlobal = env->NewGlobalRef(peer);
 601 
 602     AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide,
 603         (void *)peerGlobal);
 604     // peerGlobal ref is deleted in _DisposeOrHide
 605 
 606     CATCH_BAD_ALLOC;
 607 }
 608 
 609 JNIEXPORT void JNICALL
 610 Java_sun_awt_windows_WFileDialogPeer__1hide(JNIEnv *env, jobject peer)
 611 {
 612     TRY;
 613 
 614     jobject peerGlobal = env->NewGlobalRef(peer);
 615 
 616     AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide,
 617         (void *)peerGlobal);
 618     // peerGlobal ref is deleted in _DisposeOrHide
 619 
 620     CATCH_BAD_ALLOC;
 621 }
 622 
 623 JNIEXPORT void JNICALL
 624 Java_sun_awt_windows_WFileDialogPeer_toFront(JNIEnv *env, jobject peer)
 625 {
 626     TRY;
 627 
 628     AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToFront,
 629                                        (void *)(env->NewGlobalRef(peer)));
 630     // global ref is deleted in _ToFront
 631 
 632     CATCH_BAD_ALLOC;
 633 }
 634 
 635 JNIEXPORT void JNICALL
 636 Java_sun_awt_windows_WFileDialogPeer_toBack(JNIEnv *env, jobject peer)
 637 {
 638     TRY;
 639 
 640     AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToBack,
 641                                        (void *)(env->NewGlobalRef(peer)));
 642     // global ref is deleted in _ToBack
 643 
 644     CATCH_BAD_ALLOC;
 645 }
 646 
 647 } /* extern "C" */