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