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