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