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