1 /*
   2  * Copyright (c) 1999, 2016, 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 "mmsystem.h"
  28 #include "jlong.h"
  29 #include "awt_DesktopProperties.h"
  30 #include "awt_Toolkit.h"
  31 #include "sun_awt_windows_WDesktopProperties.h"
  32 #include "java_awt_Font.h"
  33 #include "awtmsg.h"
  34 #include "zmouse.h"
  35 #include <shellapi.h>
  36 #include <shlobj.h>
  37 
  38 #include "math.h"
  39 
  40 #if defined(_MSC_VER) && _MSC_VER >= 1800
  41 #  define ROUND_TO_INT(num)    ((int) round(num))
  42 #else
  43 #  define ROUND_TO_INT(num)    ((int) floor((num) + 0.5))
  44 #endif
  45 
  46 // WDesktopProperties fields
  47 jfieldID AwtDesktopProperties::pDataID = 0;
  48 jmethodID AwtDesktopProperties::setBooleanPropertyID = 0;
  49 jmethodID AwtDesktopProperties::setIntegerPropertyID = 0;
  50 jmethodID AwtDesktopProperties::setStringPropertyID = 0;
  51 jmethodID AwtDesktopProperties::setColorPropertyID = 0;
  52 jmethodID AwtDesktopProperties::setFontPropertyID = 0;
  53 jmethodID AwtDesktopProperties::setSoundPropertyID = 0;
  54 
  55 AwtDesktopProperties::AwtDesktopProperties(jobject self) {
  56     this->self = GetEnv()->NewGlobalRef(self);
  57     GetEnv()->SetLongField( self, AwtDesktopProperties::pDataID,
  58                             ptr_to_jlong(this) );
  59 }
  60 
  61 AwtDesktopProperties::~AwtDesktopProperties() {
  62     GetEnv()->DeleteGlobalRef(self);
  63 }
  64 
  65 //
  66 // Reads Windows parameters and sets the corresponding values
  67 // in WDesktopProperties
  68 //
  69 void AwtDesktopProperties::GetWindowsParameters() {
  70     if (GetEnv()->EnsureLocalCapacity(MAX_PROPERTIES) < 0) {
  71         DASSERT(0);
  72         return;
  73     }
  74     // this number defines the set of properties available, it is incremented
  75     // whenever more properties are added (in a public release of course)
  76     // for example, version 1 defines the properties available in Java SDK version 1.3.
  77     SetIntegerProperty( TEXT("win.properties.version"), AWT_DESKTOP_PROPERTIES_VERSION);
  78     GetNonClientParameters();
  79     GetIconParameters();
  80     GetColorParameters();
  81     GetCaretParameters();
  82     GetOtherParameters();
  83     GetSoundEvents();
  84     GetSystemProperties();
  85     if (IS_WINXP) {
  86         GetXPStyleProperties();
  87     }
  88 }
  89 
  90 void getInvScale(float &invScaleX, float &invScaleY) {
  91     HWND hWnd = ::GetDesktopWindow();
  92     HDC hDC = ::GetDC(hWnd);
  93     int dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX);
  94     int dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY);
  95     ::ReleaseDC(hWnd, hDC);
  96     invScaleX = (dpiX == 0.0f) ? 1.0f : 96.0f / dpiX;
  97     invScaleY = (dpiY == 0.0f) ? 1.0f : 96.0f / dpiY;
  98 }
  99 
 100 int rescale(int value, float invScale){
 101     return invScale == 1.0f ? value : ROUND_TO_INT(value * invScale);
 102 }
 103 
 104 void AwtDesktopProperties::GetSystemProperties() {
 105     HDC dc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
 106 
 107     if (dc != NULL) {
 108         try {
 109             float invScaleX;
 110             float invScaleY;
 111             getInvScale(invScaleX, invScaleY);
 112             SetFontProperty(dc, ANSI_FIXED_FONT, TEXT("win.ansiFixed.font"), 1.0f);
 113             SetFontProperty(dc, ANSI_VAR_FONT, TEXT("win.ansiVar.font"), 1.0f);
 114             SetFontProperty(dc, DEVICE_DEFAULT_FONT, TEXT("win.deviceDefault.font"), 1.0f);
 115             SetFontProperty(dc, DEFAULT_GUI_FONT, TEXT("win.defaultGUI.font"), invScaleY);
 116             SetFontProperty(dc, OEM_FIXED_FONT, TEXT("win.oemFixed.font"), 1.0f);
 117             SetFontProperty(dc, SYSTEM_FONT, TEXT("win.system.font"), 1.0f);
 118             SetFontProperty(dc, SYSTEM_FIXED_FONT, TEXT("win.systemFixed.font"), 1.0f);
 119         }
 120         catch (std::bad_alloc&) {
 121             DeleteDC(dc);
 122             throw;
 123         }
 124         DeleteDC(dc);
 125     }
 126 }
 127 
 128 
 129 // Does the actual lookup for shell dialog font (MS Shell Dlg).  fontName
 130 // contains the name to lookup (either MS Shell Dlg or MS Shell Dlg 2) and
 131 // handle contains a reference toe the registry entry to look in.
 132 // This will return NULL or a pointer to the resolved name.
 133 // Note that it uses malloc() and returns the pointer to allocated
 134 // memory, so remember to use free() when you are done with its
 135 // result.
 136 static LPTSTR resolveShellDialogFont(LPTSTR fontName, HKEY handle) {
 137     DWORD valueType, valueSize;
 138     if (RegQueryValueEx((HKEY)handle, fontName, NULL,
 139                         &valueType, NULL, &valueSize) != 0) {
 140         // Couldn't find it
 141         return NULL;
 142     }
 143     if (valueType != REG_SZ) {
 144         // Not the expected type
 145         return NULL;
 146     }
 147     LPTSTR buffer = (LPTSTR)safe_Malloc(valueSize);
 148     if (RegQueryValueEx((HKEY)handle, fontName, NULL,
 149                         &valueType, (unsigned char *)buffer, &valueSize) != 0) {
 150         // Error fetching
 151         free(buffer);
 152         return NULL;
 153     }
 154     return buffer;
 155 }
 156 
 157 // Determines what the font MS Shell Dlg maps to.
 158 // Note that it uses malloc() and returns the pointer to allocated
 159 // memory, so remember to use free() when you are done with its
 160 // result.
 161 static LPTSTR resolveShellDialogFont() {
 162     LPTSTR subKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
 163 
 164     HKEY handle;
 165     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &handle) != 0) {
 166         return NULL;
 167     }
 168     // Prefer MS Shell Dlg 2.
 169     LPTSTR font = resolveShellDialogFont(TEXT("MS Shell Dlg 2"), handle);
 170     if (font == NULL) {
 171         font = resolveShellDialogFont(TEXT("MS Shell Dlg"), handle);
 172     }
 173     RegCloseKey(handle);
 174     return font;
 175 }
 176 
 177 // Local function for getting values from the Windows registry
 178 // Note that it uses malloc() and returns the pointer to allocated
 179 // memory, so remember to use free() when you are done with its
 180 // result.
 181 static LPTSTR getWindowsPropFromReg(LPTSTR subKey, LPTSTR valueName, DWORD *valueType) {
 182     HKEY handle;
 183     if (RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_READ, &handle) != 0) {
 184         return NULL;
 185     }
 186     // valueSize is in bytes, while valueChar is in characters.
 187     DWORD valueSize, valueChar;
 188     if (RegQueryValueEx((HKEY)handle, valueName, NULL,
 189                         valueType, NULL, &valueSize) != 0) {
 190         RegCloseKey(handle);
 191         return NULL;
 192     }
 193     LPTSTR buffer = (LPTSTR)safe_Malloc(valueSize);
 194     if (RegQueryValueEx((HKEY)handle, valueName, NULL,
 195                         valueType, (unsigned char *)buffer, &valueSize) != 0) {
 196         free(buffer);
 197         RegCloseKey(handle);
 198         return NULL;
 199     }
 200     RegCloseKey(handle);
 201 
 202     if (*valueType == REG_EXPAND_SZ) {
 203         // Pending: buffer must be null-terminated at this point
 204         valueChar = ExpandEnvironmentStrings(buffer, NULL, 0);
 205         LPTSTR buffer2 = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, valueChar, sizeof(TCHAR));
 206         ExpandEnvironmentStrings(buffer, buffer2, valueChar);
 207         free(buffer);
 208         return buffer2;
 209     } else if (*valueType == REG_SZ) {
 210         return buffer;
 211     } else if (*valueType == REG_DWORD) {
 212         return buffer;
 213     } else {
 214         free(buffer);
 215         return NULL;
 216     }
 217 }
 218 
 219 static LPTSTR getXPStylePropFromReg(LPTSTR valueName) {
 220     DWORD valueType;
 221     return getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager"),
 222                                  valueName, &valueType);
 223 }
 224 
 225 
 226 // Used in AwtMenuItem to determine the color of top menus,
 227 // since they depend on XP style. ThemeActive property is
 228 // '1' for XP Style, '0' for Windows classic style.
 229 BOOL AwtDesktopProperties::IsXPStyle() {
 230     LPTSTR style = getXPStylePropFromReg(TEXT("ThemeActive"));
 231     BOOL result = (style != NULL && *style == _T('1'));
 232     free(style);
 233     return result;
 234 }
 235 
 236 void AwtDesktopProperties::GetXPStyleProperties() {
 237     LPTSTR value;
 238 
 239     value = getXPStylePropFromReg(TEXT("ThemeActive"));
 240     try {
 241         SetBooleanProperty(TEXT("win.xpstyle.themeActive"), (value != NULL && *value == _T('1')));
 242         if (value != NULL) {
 243             free(value);
 244             value = NULL;
 245         }
 246         value = getXPStylePropFromReg(TEXT("DllName"));
 247         if (value != NULL) {
 248             SetStringProperty(TEXT("win.xpstyle.dllName"), value);
 249             free(value);
 250             value = NULL;
 251         }
 252         value = getXPStylePropFromReg(TEXT("SizeName"));
 253         if (value != NULL) {
 254             SetStringProperty(TEXT("win.xpstyle.sizeName"), value);
 255             free(value);
 256             value = NULL;
 257         }
 258         value = getXPStylePropFromReg(TEXT("ColorName"));
 259         if (value != NULL) {
 260             SetStringProperty(TEXT("win.xpstyle.colorName"), value);
 261             free(value);
 262         }
 263     }
 264     catch (std::bad_alloc&) {
 265         if (value != NULL) {
 266             free(value);
 267         }
 268         throw;
 269     }
 270 }
 271 
 272 
 273 void AwtDesktopProperties::GetNonClientParameters() {
 274     //
 275     // general window properties
 276     //
 277     NONCLIENTMETRICS    ncmetrics;
 278 
 279     // Fix for 6944516: specify correct size for ncmetrics on WIN2K/XP
 280     // Microsoft recommend to subtract the size of  'iPaddedBorderWidth' field
 281     // when running on XP. However this can't be referenced at compile time
 282     // with the older SDK, so there use 'lfMessageFont' plus its size.
 283     if (!IS_WINVISTA) {
 284 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
 285         ncmetrics.cbSize = offsetof(NONCLIENTMETRICS, iPaddedBorderWidth);
 286 #else
 287         ncmetrics.cbSize = offsetof(NONCLIENTMETRICS,lfMessageFont) + sizeof(LOGFONT);
 288 #endif
 289     } else {
 290         ncmetrics.cbSize = sizeof(ncmetrics);
 291     }
 292     VERIFY( SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncmetrics.cbSize, &ncmetrics, FALSE) );
 293 
 294     float invScaleX;
 295     float invScaleY;
 296     getInvScale(invScaleX, invScaleY);
 297 
 298     SetFontProperty(TEXT("win.frame.captionFont"), ncmetrics.lfCaptionFont, invScaleY);
 299     SetIntegerProperty(TEXT("win.frame.captionHeight"), rescale(ncmetrics.iCaptionHeight, invScaleY));
 300     SetIntegerProperty(TEXT("win.frame.captionButtonWidth"), rescale(ncmetrics.iCaptionWidth, invScaleX));
 301     SetIntegerProperty(TEXT("win.frame.captionButtonHeight"), rescale(ncmetrics.iCaptionHeight, invScaleY));
 302     SetFontProperty(TEXT("win.frame.smallCaptionFont"), ncmetrics.lfSmCaptionFont, invScaleY);
 303     SetIntegerProperty(TEXT("win.frame.smallCaptionHeight"), rescale(ncmetrics.iSmCaptionHeight, invScaleY));
 304     SetIntegerProperty(TEXT("win.frame.smallCaptionButtonWidth"), rescale(ncmetrics.iSmCaptionWidth, invScaleX));
 305     SetIntegerProperty(TEXT("win.frame.smallCaptionButtonHeight"), rescale(ncmetrics.iSmCaptionHeight, invScaleY));
 306     SetIntegerProperty(TEXT("win.frame.sizingBorderWidth"), rescale(ncmetrics.iBorderWidth, invScaleX));
 307 
 308     // menu properties
 309     SetFontProperty(TEXT("win.menu.font"), ncmetrics.lfMenuFont, invScaleY);
 310     SetIntegerProperty(TEXT("win.menu.height"), rescale(ncmetrics.iMenuHeight, invScaleY));
 311     SetIntegerProperty(TEXT("win.menu.buttonWidth"), rescale(ncmetrics.iMenuWidth, invScaleX));
 312 
 313     // scrollbar properties
 314     SetIntegerProperty(TEXT("win.scrollbar.width"), rescale(ncmetrics.iScrollWidth, invScaleX));
 315     SetIntegerProperty(TEXT("win.scrollbar.height"), rescale(ncmetrics.iScrollHeight, invScaleY));
 316 
 317     // status bar and tooltip properties
 318     SetFontProperty(TEXT("win.status.font"), ncmetrics.lfStatusFont, invScaleY);
 319     SetFontProperty(TEXT("win.tooltip.font"), ncmetrics.lfStatusFont, invScaleY);
 320 
 321     // message box properties
 322     SetFontProperty(TEXT("win.messagebox.font"), ncmetrics.lfMessageFont, invScaleY);
 323 }
 324 
 325 void AwtDesktopProperties::GetIconParameters() {
 326     //
 327     // icon properties
 328     //
 329     ICONMETRICS iconmetrics;
 330 
 331     iconmetrics.cbSize = sizeof(iconmetrics);
 332     VERIFY( SystemParametersInfo(SPI_GETICONMETRICS, iconmetrics.cbSize, &iconmetrics, FALSE) );
 333 
 334     float invScaleX;
 335     float invScaleY;
 336     getInvScale(invScaleX, invScaleY);
 337     SetIntegerProperty(TEXT("win.icon.hspacing"), rescale(iconmetrics.iHorzSpacing, invScaleX));
 338     SetIntegerProperty(TEXT("win.icon.vspacing"), rescale(iconmetrics.iVertSpacing, invScaleY));
 339     SetBooleanProperty(TEXT("win.icon.titleWrappingOn"), iconmetrics.iTitleWrap != 0);
 340     SetFontProperty(TEXT("win.icon.font"), iconmetrics.lfFont, invScaleY);
 341 }
 342 /*
 343  Windows settings for these are also in the registry
 344  They exist as system wide HKLM: HKEY_LOCAL_MACHINE and
 345  HKCU: HKEY_CURRENT_USER.
 346  HKCU\Control Panel\Desktop\FontSmoothing :  "0=OFF",  "2=ON"
 347  HKCU\Control Panel\Desktop\FontSmoothingType: 1=Standard, 2=LCD
 348  HKCU\Control Panel\Desktop\FontSmoothingGamma: 1000->2200
 349  HKCU\Control Panel\Desktop\FontSmoothingOrientation: 0=BGR, 1=RGB
 350 
 351  SystemParametersInfo supplies the first three of these but does not
 352  however expose the Orientation. That has to come from the registry.
 353 
 354  We go to some small lengths in here to not make queries we don't need.
 355  Eg if we previously were using standard font smoothing and we still are
 356  then its unlikely that any change in gamma will have occurred except
 357  by a program which changed it, and even if it did, we don't need to pick
 358  it up until someone turns on the LCD option.
 359  To do: this loop is called once per top-level window so an app with
 360  N windows will get notified N times. It would save us a small amount of
 361  redundant work if I could identify the message as being one already processed
 362  for another window.
 363  Also presumably a repaint that specifies only a partially damaged window
 364  isn't one that needs this checking.
 365 */
 366 
 367 #define FONTSMOOTHING_OFF 0
 368 #define FONTSMOOTHING_ON  1
 369 #define FONTSMOOTHING_STANDARD 1
 370 #define FONTSMOOTHING_LCD 2
 371 #define LCD_RGB_ORDER 1
 372 #define LCD_BGR_ORDER 0
 373 
 374 
 375 int GetLCDSubPixelOrder() {
 376     LONG order=99;
 377     LONG bufferSize = 4;
 378     HKEY hkeyDesktop;
 379     static LPCTSTR DESKTOPKEY = TEXT("Control Panel\\Desktop");
 380     LONG ret = RegOpenKeyEx(HKEY_CURRENT_USER,
 381                             DESKTOPKEY, 0L, KEY_READ, &hkeyDesktop);
 382     if (ret != ERROR_SUCCESS) {
 383         return LCD_RGB_ORDER;
 384     }
 385     ret = RegQueryValueEx(hkeyDesktop, TEXT("FontSmoothingOrientation"),
 386                           NULL, NULL, (LPBYTE)&order, (LPDWORD)&bufferSize);
 387     RegCloseKey(hkeyDesktop);
 388     if (ret != ERROR_SUCCESS) {
 389         return LCD_RGB_ORDER;
 390     } else {
 391         return (int)order;
 392     }
 393 }
 394 
 395 void CheckFontSmoothingSettings(HWND hWnd) {
 396     static BOOL firstTime = TRUE;
 397     static BOOL lastFontSmoothing = FALSE;
 398     static UINT lastFontSmoothingType = FONTSMOOTHING_ON;
 399     static UINT lastFontSmoothingContrast = 1400;
 400     static UINT lastSubpixelOrder = LCD_RGB_ORDER;
 401 
 402     /* If we are called with a window handle it is because there is a
 403      * message to repaint at least some part of the window which typically
 404      * is not because of the desktop font settings change. Much more likely
 405      * its a normal repaint event. If it is because of the rare settings
 406      * change in that case the update region will be the entire window.
 407      * Try to as cheaply as possible determine if this is not a call
 408      * to repaint the whole window by assuming that all such calls will
 409      * have an update region whose origin is 0,0. Only in that case will
 410      * we take the hit of checking the settings.
 411      * Thus we avoid taking the hit of the other calls for most partial
 412      * expose events, which will never be the result of changes to desktop
 413      * font settings.
 414      */
 415     if (hWnd != NULL) {
 416         RECT r;
 417         if (!::GetUpdateRect(hWnd, &r, FALSE) || r.top != 0 || r.left != 0) {
 418             return;
 419         }
 420     }
 421 
 422     BOOL fontSmoothing = FALSE, settingsChanged;
 423     UINT fontSmoothingType=0, fontSmoothingContrast=0, subPixelOrder=0;
 424 
 425     if (firstTime) {
 426         SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothing, 0);
 427         if (IS_WINXP) {
 428             SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0,
 429                                  &fontSmoothingType, 0);
 430             SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0,
 431                                  &fontSmoothingContrast, 0);
 432         }
 433         lastFontSmoothing = fontSmoothing;
 434         lastFontSmoothingType = fontSmoothingType;
 435         lastFontSmoothingContrast = fontSmoothingContrast;
 436         firstTime = FALSE;
 437         return;
 438     } else {
 439         SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothing, 0);
 440         settingsChanged = fontSmoothing != lastFontSmoothing;
 441         if (!settingsChanged && fontSmoothing == FONTSMOOTHING_OFF) {
 442             /* no need to check the other settings in this case. */
 443             return;
 444         }
 445         if (IS_WINXP) {
 446             SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0,
 447                                  &fontSmoothingType, 0);
 448             settingsChanged |= fontSmoothingType != lastFontSmoothingType;
 449             if (!settingsChanged &&
 450                 fontSmoothingType == FONTSMOOTHING_STANDARD) {
 451                 /* No need to check any LCD specific settings */
 452                 return;
 453             } else {
 454                 SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0,
 455                                      &fontSmoothingContrast, 0);
 456                 settingsChanged |=
 457                     fontSmoothingContrast != lastFontSmoothingContrast;
 458                 if (fontSmoothingType == FONTSMOOTHING_LCD) {
 459                     // Order is a registry entry so more expensive to check.x
 460                     subPixelOrder = GetLCDSubPixelOrder();
 461                     settingsChanged |= subPixelOrder != lastSubpixelOrder;
 462                 }
 463             }
 464         } else {
 465             if (settingsChanged && fontSmoothing == FONTSMOOTHING_ON) {
 466                 fontSmoothingType = FONTSMOOTHING_STANDARD;
 467             }
 468         }
 469     }
 470     if (settingsChanged) {
 471         /* Some of these values may not have been queried, but it shouldn't
 472          * matter as what's important is to track changes in values we are
 473          * actually using. The up-call we make here will cause the actual
 474          * values for everything to get queried and set into the desktop
 475          * properties.
 476          */
 477         lastFontSmoothing = fontSmoothing;
 478         lastFontSmoothingType = fontSmoothingType;
 479         lastFontSmoothingContrast = fontSmoothingContrast;
 480         lastSubpixelOrder = subPixelOrder;
 481 
 482         jobject peer = AwtToolkit::GetInstance().GetPeer();
 483         if (peer != NULL) {
 484             AwtToolkit::GetEnv()->CallVoidMethod(peer,
 485                                      AwtToolkit::windowsSettingChangeMID);
 486         }
 487     }
 488 }
 489 
 490 void AwtDesktopProperties::GetColorParameters() {
 491 
 492     SetColorProperty(TEXT("win.frame.activeCaptionGradientColor"),
 493                      GetSysColor(COLOR_GRADIENTACTIVECAPTION));
 494     SetColorProperty(TEXT("win.frame.inactiveCaptionGradientColor"),
 495                      GetSysColor(COLOR_GRADIENTINACTIVECAPTION));
 496     SetColorProperty(TEXT("win.item.hotTrackedColor"),
 497                      GetSysColor(COLOR_HOTLIGHT));
 498     SetColorProperty(TEXT("win.3d.darkShadowColor"), GetSysColor(COLOR_3DDKSHADOW));
 499     SetColorProperty(TEXT("win.3d.backgroundColor"), GetSysColor(COLOR_3DFACE));
 500     SetColorProperty(TEXT("win.3d.highlightColor"), GetSysColor(COLOR_3DHIGHLIGHT));
 501     SetColorProperty(TEXT("win.3d.lightColor"), GetSysColor(COLOR_3DLIGHT));
 502     SetColorProperty(TEXT("win.3d.shadowColor"), GetSysColor(COLOR_3DSHADOW));
 503     SetColorProperty(TEXT("win.button.textColor"), GetSysColor(COLOR_BTNTEXT));
 504     SetColorProperty(TEXT("win.desktop.backgroundColor"), GetSysColor(COLOR_DESKTOP));
 505     SetColorProperty(TEXT("win.frame.activeCaptionColor"), GetSysColor(COLOR_ACTIVECAPTION));
 506     SetColorProperty(TEXT("win.frame.activeBorderColor"), GetSysColor(COLOR_ACTIVEBORDER));
 507 
 508     // ?? ?? ??
 509     SetColorProperty(TEXT("win.frame.color"), GetSysColor(COLOR_WINDOWFRAME)); // ?? WHAT THE HECK DOES THIS MEAN ??
 510     // ?? ?? ??
 511 
 512     SetColorProperty(TEXT("win.frame.backgroundColor"), GetSysColor(COLOR_WINDOW));
 513     SetColorProperty(TEXT("win.frame.captionTextColor"), GetSysColor(COLOR_CAPTIONTEXT));
 514     SetColorProperty(TEXT("win.frame.inactiveBorderColor"), GetSysColor(COLOR_INACTIVEBORDER));
 515     SetColorProperty(TEXT("win.frame.inactiveCaptionColor"), GetSysColor(COLOR_INACTIVECAPTION));
 516     SetColorProperty(TEXT("win.frame.inactiveCaptionTextColor"), GetSysColor(COLOR_INACTIVECAPTIONTEXT));
 517     SetColorProperty(TEXT("win.frame.textColor"), GetSysColor(COLOR_WINDOWTEXT));
 518     SetColorProperty(TEXT("win.item.highlightColor"), GetSysColor(COLOR_HIGHLIGHT));
 519     SetColorProperty(TEXT("win.item.highlightTextColor"), GetSysColor(COLOR_HIGHLIGHTTEXT));
 520     SetColorProperty(TEXT("win.mdi.backgroundColor"), GetSysColor(COLOR_APPWORKSPACE));
 521     SetColorProperty(TEXT("win.menu.backgroundColor"), GetSysColor(COLOR_MENU));
 522     SetColorProperty(TEXT("win.menu.textColor"), GetSysColor(COLOR_MENUTEXT));
 523     // COLOR_MENUBAR is only defined on WindowsXP. Our binaries are
 524     // built on NT, hence the below ifdef.
 525 #ifndef COLOR_MENUBAR
 526 #define COLOR_MENUBAR 30
 527 #endif
 528     SetColorProperty(TEXT("win.menubar.backgroundColor"),
 529                                 GetSysColor(IS_WINXP ? COLOR_MENUBAR : COLOR_MENU));
 530     SetColorProperty(TEXT("win.scrollbar.backgroundColor"), GetSysColor(COLOR_SCROLLBAR));
 531     SetColorProperty(TEXT("win.text.grayedTextColor"), GetSysColor(COLOR_GRAYTEXT));
 532     SetColorProperty(TEXT("win.tooltip.backgroundColor"), GetSysColor(COLOR_INFOBK));
 533     SetColorProperty(TEXT("win.tooltip.textColor"), GetSysColor(COLOR_INFOTEXT));
 534 }
 535 
 536 void AwtDesktopProperties::GetOtherParameters() {
 537     // TODO BEGIN: On NT4, some setttings don't trigger WM_SETTINGCHANGE --
 538     // check whether this has been fixed on Windows 2000 and Windows 98
 539     // ECH 10/6/2000 seems to be fixed on NT4 SP5, but not on 98
 540     SetBooleanProperty(TEXT("win.frame.fullWindowDragsOn"), GetBooleanParameter(SPI_GETDRAGFULLWINDOWS));
 541     SetBooleanProperty(TEXT("win.text.fontSmoothingOn"), GetBooleanParameter(SPI_GETFONTSMOOTHING));
 542     // TODO END
 543 
 544     if (IS_WINXP) {
 545         SetIntegerProperty(TEXT("win.text.fontSmoothingType"),
 546                            GetIntegerParameter(SPI_GETFONTSMOOTHINGTYPE));
 547         SetIntegerProperty(TEXT("win.text.fontSmoothingContrast"),
 548                            GetIntegerParameter(SPI_GETFONTSMOOTHINGCONTRAST));
 549         SetIntegerProperty(TEXT("win.text.fontSmoothingOrientation"),
 550                            GetLCDSubPixelOrder());
 551     }
 552 
 553     int cxdrag = GetSystemMetrics(SM_CXDRAG);
 554     int cydrag = GetSystemMetrics(SM_CYDRAG);
 555     SetIntegerProperty(TEXT("win.drag.width"), cxdrag);
 556     SetIntegerProperty(TEXT("win.drag.height"), cydrag);
 557     SetIntegerProperty(TEXT("DnD.gestureMotionThreshold"), max(cxdrag, cydrag)/2);
 558     SetIntegerProperty(TEXT("awt.mouse.numButtons"), AwtToolkit::GetNumberOfButtons());
 559 
 560     SetIntegerProperty(TEXT("awt.multiClickInterval"), GetDoubleClickTime());
 561 
 562     // BEGIN cross-platform properties
 563     // Note that these are cross-platform properties, but are being stuck into
 564     // WDesktopProperties.  WToolkit.lazilyLoadDesktopProperty() can find them,
 565     // but if a Toolkit subclass uses the desktopProperties
 566     // member, these properties won't be there. -bchristi, echawkes
 567     // This property is called "win.frame.fullWindowDragsOn" above
 568     // This is one of the properties that don't trigger WM_SETTINGCHANGE
 569     SetBooleanProperty(TEXT("awt.dynamicLayoutSupported"), GetBooleanParameter(SPI_GETDRAGFULLWINDOWS));
 570     SetBooleanProperty(TEXT("awt.wheelMousePresent"),
 571                        ::GetSystemMetrics(SM_MOUSEWHEELPRESENT));
 572 
 573     // END cross-platform properties
 574 
 575     //DWORD   menuShowDelay;
 576     //SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &menuShowDelay, 0);
 577     // SetIntegerProperty(TEXT("win.menu.showDelay"), menuShowDelay);
 578     SetBooleanProperty(TEXT("win.frame.captionGradientsOn"), GetBooleanParameter(SPI_GETGRADIENTCAPTIONS));
 579     SetBooleanProperty(TEXT("win.item.hotTrackingOn"), GetBooleanParameter(SPI_GETHOTTRACKING));
 580 
 581     SetBooleanProperty(TEXT("win.menu.keyboardCuesOn"), GetBooleanParameter(SPI_GETKEYBOARDCUES));
 582 
 583     // High contrast accessibility property
 584     HIGHCONTRAST contrast;
 585     contrast.cbSize = sizeof(HIGHCONTRAST);
 586     if (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST),
 587                              &contrast, 0) != 0 &&
 588               (contrast.dwFlags & HCF_HIGHCONTRASTON) == HCF_HIGHCONTRASTON) {
 589       SetBooleanProperty(TEXT("win.highContrast.on"), TRUE);
 590     }
 591     else {
 592       SetBooleanProperty(TEXT("win.highContrast.on"), FALSE);
 593     }
 594 
 595     SHELLFLAGSTATE sfs;
 596     ::SHGetSettings(&sfs, SSF_SHOWALLOBJECTS | SSF_SHOWATTRIBCOL);
 597     if (sfs.fShowAllObjects) {
 598         SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), TRUE);
 599     }
 600     else {
 601         SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), FALSE);
 602     }
 603     if (sfs.fShowAttribCol) {
 604         SetBooleanProperty(TEXT("awt.file.showAttribCol"), TRUE);
 605     }
 606     else {
 607         SetBooleanProperty(TEXT("awt.file.showAttribCol"), FALSE);
 608     }
 609 
 610     LPTSTR value;
 611     DWORD valueType;
 612 
 613     // Shell Icon BPP - only honored on platforms before XP
 614     value = getWindowsPropFromReg(TEXT("Control Panel\\Desktop\\WindowMetrics"),
 615                                   TEXT("Shell Icon BPP"), &valueType);
 616 
 617     try {
 618         if (value != NULL) {
 619             if (valueType == REG_SZ) {
 620                 SetStringProperty(TEXT("win.icon.shellIconBPP"), value);
 621             }
 622             free(value);
 623             value = NULL;
 624         }
 625 
 626 
 627         // The following registry settings control the file chooser places bar
 628         // under the Windows L&F. These settings are not present by default, but
 629         // can be enabled using the TweakUI tool from Microsoft. For more info,
 630         // see http://msdn.microsoft.com/msdnmag/issues/1100/Registry/
 631 
 632         // NoPlacesBar is a REG_DWORD, with values 0 or 1
 633         value = getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32"),
 634                                       TEXT("NoPlacesBar"), &valueType);
 635         if (value != NULL) {
 636             if (valueType == REG_DWORD) {
 637                 SetBooleanProperty(TEXT("win.comdlg.noPlacesBar"), (BOOL)((int)*value != 0));
 638             }
 639             free(value);
 640         }
 641     }
 642     catch (std::bad_alloc&) {
 643         if (value != NULL) {
 644             free(value);
 645         }
 646         throw;
 647     }
 648 
 649     LPTSTR valueName = TEXT("PlaceN");
 650     LPTSTR valueNameBuf = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (lstrlen(valueName) + 1), sizeof(TCHAR));
 651     lstrcpy(valueNameBuf, valueName);
 652 
 653     LPTSTR propKey = TEXT("win.comdlg.placesBarPlaceN");
 654 
 655     LPTSTR propKeyBuf;
 656     try {
 657         propKeyBuf = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (lstrlen(propKey) + 1), sizeof(TCHAR));
 658     }
 659     catch (std::bad_alloc&) {
 660         free(valueNameBuf);
 661         throw;
 662     }
 663     lstrcpy(propKeyBuf, propKey);
 664 
 665     int i = 0;
 666     do {
 667         valueNameBuf[5] = _T('0' + i++);
 668         propKeyBuf[25] = valueNameBuf[5];
 669 
 670         LPTSTR key = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32\\PlacesBar");
 671         try {
 672             value = NULL;
 673             if ((value = getWindowsPropFromReg(key, valueNameBuf, &valueType)) != NULL) {
 674                 if (valueType == REG_DWORD) {
 675                     // Value is a CSIDL
 676                     SetIntegerProperty(propKeyBuf, (int)*value);
 677                 } else {
 678                     // Value is a path
 679                     SetStringProperty(propKeyBuf, value);
 680                 }
 681                 free(value);
 682             }
 683         }
 684         catch (std::bad_alloc&) {
 685             if (value != NULL) {
 686                 free(value);
 687             }
 688             free(propKeyBuf);
 689             free(valueNameBuf);
 690             throw;
 691         }
 692     } while (value != NULL);
 693 
 694     free(propKeyBuf);
 695     free(valueNameBuf);
 696 }
 697 
 698 void AwtDesktopProperties::GetSoundEvents() {
 699     /////
 700     SetSoundProperty(TEXT("win.sound.default"), TEXT(".Default"));
 701     SetSoundProperty(TEXT("win.sound.close"), TEXT("Close"));
 702     SetSoundProperty(TEXT("win.sound.maximize"), TEXT("Maximize"));
 703     SetSoundProperty(TEXT("win.sound.minimize"), TEXT("Minimize"));
 704     SetSoundProperty(TEXT("win.sound.menuCommand"), TEXT("MenuCommand"));
 705     SetSoundProperty(TEXT("win.sound.menuPopup"), TEXT("MenuPopup"));
 706     SetSoundProperty(TEXT("win.sound.open"), TEXT("Open"));
 707     SetSoundProperty(TEXT("win.sound.restoreDown"), TEXT("RestoreDown"));
 708     SetSoundProperty(TEXT("win.sound.restoreUp"), TEXT("RestoreUp"));
 709     /////
 710     SetSoundProperty(TEXT("win.sound.asterisk"), TEXT("SystemAsterisk"));
 711     SetSoundProperty(TEXT("win.sound.exclamation"), TEXT("SystemExclamation"));
 712     SetSoundProperty(TEXT("win.sound.exit"), TEXT("SystemExit"));
 713     SetSoundProperty(TEXT("win.sound.hand"), TEXT("SystemHand"));
 714     SetSoundProperty(TEXT("win.sound.question"), TEXT("SystemQuestion"));
 715     SetSoundProperty(TEXT("win.sound.start"), TEXT("SystemStart"));
 716 }
 717 
 718 void AwtDesktopProperties::GetCaretParameters() {
 719     SetIntegerProperty(TEXT("win.caret.width"), GetIntegerParameter(SPI_GETCARETWIDTH));
 720 }
 721 
 722 BOOL AwtDesktopProperties::GetBooleanParameter(UINT spi) {
 723     BOOL        flag;
 724     SystemParametersInfo(spi, 0, &flag, 0);
 725     DASSERT(flag == TRUE || flag == FALSE); // should be simple boolean value
 726     return flag;
 727 }
 728 
 729 UINT AwtDesktopProperties::GetIntegerParameter(UINT spi) {
 730     UINT retValue;
 731     SystemParametersInfo(spi, 0, &retValue, 0);
 732     return retValue;
 733 }
 734 
 735 void AwtDesktopProperties::SetStringProperty(LPCTSTR propName, LPTSTR value) {
 736     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 737     if (key == NULL) {
 738         throw std::bad_alloc();
 739     }
 740     jstring jValue = JNU_NewStringPlatform(GetEnv(), value);
 741     if (jValue == NULL) {
 742         GetEnv()->DeleteLocalRef(key);
 743         throw std::bad_alloc();
 744     }
 745     GetEnv()->CallVoidMethod(self,
 746                              AwtDesktopProperties::setStringPropertyID,
 747                              key, jValue);
 748     GetEnv()->DeleteLocalRef(jValue);
 749     GetEnv()->DeleteLocalRef(key);
 750 }
 751 
 752 void AwtDesktopProperties::SetIntegerProperty(LPCTSTR propName, int value) {
 753 
 754     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 755     if (key == NULL) {
 756         throw std::bad_alloc();
 757     }
 758     GetEnv()->CallVoidMethod(self,
 759                              AwtDesktopProperties::setIntegerPropertyID,
 760                              key, (jint)value);
 761     GetEnv()->DeleteLocalRef(key);
 762 }
 763 
 764 void AwtDesktopProperties::SetBooleanProperty(LPCTSTR propName, BOOL value) {
 765     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 766     if (key == NULL) {
 767         throw std::bad_alloc();
 768     }
 769     GetEnv()->CallVoidMethod(self,
 770                              AwtDesktopProperties::setBooleanPropertyID,
 771                              key, value ? JNI_TRUE : JNI_FALSE);
 772     GetEnv()->DeleteLocalRef(key);
 773 }
 774 
 775 void AwtDesktopProperties::SetColorProperty(LPCTSTR propName, DWORD value) {
 776     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 777     if (key == NULL) {
 778         throw std::bad_alloc();
 779     }
 780     GetEnv()->CallVoidMethod(self,
 781                              AwtDesktopProperties::setColorPropertyID,
 782                              key, GetRValue(value), GetGValue(value),
 783                              GetBValue(value));
 784     GetEnv()->DeleteLocalRef(key);
 785 }
 786 
 787 void AwtDesktopProperties::SetFontProperty(HDC dc, int fontID,
 788     LPCTSTR propName, float invScale) {
 789         HGDIOBJ font = GetStockObject(fontID);
 790     if (font != NULL && SelectObject(dc, font) != NULL) {
 791         int length = GetTextFace(dc, 0, NULL);
 792 
 793         if (length > 0) {
 794             LPTSTR face = new TCHAR[length];
 795 
 796             if (GetTextFace(dc, length, face) > 0) {
 797                 TEXTMETRIC metrics;
 798 
 799                 if (GetTextMetrics(dc, &metrics) > 0) {
 800                     jstring fontName = NULL;
 801                     if (!wcscmp(face, L"MS Shell Dlg")) {
 802                         // MS Shell Dlg is an indirect font name, find the
 803                         // real face name from the registry.
 804                         LPTSTR shellDialogFace = resolveShellDialogFont();
 805                         if (shellDialogFace != NULL) {
 806                             fontName = JNU_NewStringPlatform(GetEnv(),
 807                                                              shellDialogFace);
 808                             free(shellDialogFace);
 809                         }
 810                         else {
 811                             // Couldn't determine mapping for MS Shell Dlg,
 812                             // fall back to Microsoft Sans Serif
 813                             fontName = JNU_NewStringPlatform(GetEnv(),
 814                                                     L"Microsoft Sans Serif");
 815                         }
 816                     }
 817                     else {
 818                         fontName = JNU_NewStringPlatform(GetEnv(), face);
 819                     }
 820                     if (fontName == NULL) {
 821                         delete[] face;
 822                         throw std::bad_alloc();
 823                     }
 824 
 825                     jint pointSize = rescale(metrics.tmHeight -
 826                                      metrics.tmInternalLeading, invScale);
 827                     jint style = java_awt_Font_PLAIN;
 828 
 829                     if (metrics.tmWeight >= FW_BOLD) {
 830                         style =  java_awt_Font_BOLD;
 831                     }
 832                     if (metrics.tmItalic ) {
 833                         style |= java_awt_Font_ITALIC;
 834                     }
 835 
 836                     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 837                     if (key == NULL) {
 838                         GetEnv()->DeleteLocalRef(fontName);
 839                         delete[] face;
 840                         throw std::bad_alloc();
 841                     }
 842                     GetEnv()->CallVoidMethod(self,
 843                               AwtDesktopProperties::setFontPropertyID,
 844                               key, fontName, style, pointSize);
 845                     GetEnv()->DeleteLocalRef(key);
 846                     GetEnv()->DeleteLocalRef(fontName);
 847                 }
 848             }
 849             delete[] face;
 850         }
 851     }
 852 }
 853 
 854 void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & font,
 855     float invScale) {
 856     jstring fontName;
 857     jint pointSize;
 858     jint style;
 859 
 860     fontName = JNU_NewStringPlatform(GetEnv(), font.lfFaceName);
 861     if (fontName == NULL) {
 862         throw std::bad_alloc();
 863     }
 864 #if 0
 865     HDC         hdc;
 866     int         pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
 867     // convert font size specified in pixels to font size in points
 868     hdc = GetDC(NULL);
 869     pointSize = (-font.lfHeight)*72/pixelsPerInch;
 870     ReleaseDC(NULL, hdc);
 871 #endif
 872     // Java uses point sizes, but assumes 1 pixel = 1 point
 873     pointSize = rescale(-font.lfHeight, invScale);
 874 
 875     // convert Windows font style to Java style
 876     style = java_awt_Font_PLAIN;
 877     DTRACE_PRINTLN1("weight=%d", font.lfWeight);
 878     if ( font.lfWeight >= FW_BOLD ) {
 879         style =  java_awt_Font_BOLD;
 880     }
 881     if ( font.lfItalic ) {
 882         style |= java_awt_Font_ITALIC;
 883     }
 884 
 885     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 886     if (key == NULL) {
 887         GetEnv()->DeleteLocalRef(fontName);
 888         throw std::bad_alloc();
 889     }
 890     GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID,
 891                              key, fontName, style, pointSize);
 892     GetEnv()->DeleteLocalRef(key);
 893     GetEnv()->DeleteLocalRef(fontName);
 894 }
 895 
 896 void AwtDesktopProperties::SetSoundProperty(LPCTSTR propName, LPCTSTR winEventName) {
 897     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 898     if (key == NULL) {
 899         throw std::bad_alloc();
 900     }
 901     jstring event = JNU_NewStringPlatform(GetEnv(), winEventName);
 902     if (event == NULL) {
 903         GetEnv()->DeleteLocalRef(key);
 904         throw std::bad_alloc();
 905     }
 906     GetEnv()->CallVoidMethod(self,
 907                              AwtDesktopProperties::setSoundPropertyID,
 908                              key, event);
 909     GetEnv()->DeleteLocalRef(event);
 910     GetEnv()->DeleteLocalRef(key);
 911 }
 912 
 913 void AwtDesktopProperties::PlayWindowsSound(LPCTSTR event) {
 914     // stop any currently playing sounds
 915     ::PlaySound(NULL, NULL, SND_PURGE);
 916     // play the sound for the given event name
 917     ::PlaySound(event, NULL, SND_ASYNC|SND_ALIAS|SND_NODEFAULT);
 918 }
 919 
 920 ///////////////////////////////////////////////////////////////////////////////////////////////////
 921 
 922 static AwtDesktopProperties * GetCppThis(JNIEnv *env, jobject self) {
 923     jlong longProps = env->GetLongField(self, AwtDesktopProperties::pDataID);
 924     AwtDesktopProperties * props =
 925         (AwtDesktopProperties *)jlong_to_ptr(longProps);
 926     DASSERT( !IsBadReadPtr(props, sizeof(*props)) );
 927     return props;
 928 }
 929 
 930 JNIEXPORT void JNICALL
 931 Java_sun_awt_windows_WDesktopProperties_initIDs(JNIEnv *env, jclass cls) {
 932     TRY;
 933 
 934     AwtDesktopProperties::pDataID = env->GetFieldID(cls, "pData", "J");
 935     DASSERT(AwtDesktopProperties::pDataID != 0);
 936     CHECK_NULL(AwtDesktopProperties::pDataID);
 937 
 938     AwtDesktopProperties::setBooleanPropertyID =
 939         env->GetMethodID(cls, "setBooleanProperty", "(Ljava/lang/String;Z)V");
 940     DASSERT(AwtDesktopProperties::setBooleanPropertyID != 0);
 941     CHECK_NULL(AwtDesktopProperties::setBooleanPropertyID);
 942 
 943     AwtDesktopProperties::setIntegerPropertyID =
 944         env->GetMethodID(cls, "setIntegerProperty", "(Ljava/lang/String;I)V");
 945     DASSERT(AwtDesktopProperties::setIntegerPropertyID != 0);
 946     CHECK_NULL(AwtDesktopProperties::setIntegerPropertyID);
 947 
 948     AwtDesktopProperties::setStringPropertyID =
 949         env->GetMethodID(cls, "setStringProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
 950     DASSERT(AwtDesktopProperties::setStringPropertyID != 0);
 951     CHECK_NULL(AwtDesktopProperties::setStringPropertyID);
 952 
 953     AwtDesktopProperties::setColorPropertyID =
 954         env->GetMethodID(cls, "setColorProperty", "(Ljava/lang/String;III)V");
 955     DASSERT(AwtDesktopProperties::setColorPropertyID != 0);
 956     CHECK_NULL(AwtDesktopProperties::setColorPropertyID);
 957 
 958     AwtDesktopProperties::setFontPropertyID =
 959         env->GetMethodID(cls, "setFontProperty", "(Ljava/lang/String;Ljava/lang/String;II)V");
 960     DASSERT(AwtDesktopProperties::setFontPropertyID != 0);
 961     CHECK_NULL(AwtDesktopProperties::setFontPropertyID);
 962 
 963     AwtDesktopProperties::setSoundPropertyID =
 964         env->GetMethodID(cls, "setSoundProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
 965     DASSERT(AwtDesktopProperties::setSoundPropertyID != 0);
 966     CHECK_NULL(AwtDesktopProperties::setSoundPropertyID);
 967 
 968     CATCH_BAD_ALLOC;
 969 }
 970 
 971 JNIEXPORT void JNICALL
 972 Java_sun_awt_windows_WDesktopProperties_init(JNIEnv *env, jobject self) {
 973     TRY;
 974 
 975     new AwtDesktopProperties(self);
 976 
 977     CATCH_BAD_ALLOC;
 978 }
 979 
 980 JNIEXPORT void JNICALL
 981 Java_sun_awt_windows_WDesktopProperties_getWindowsParameters(JNIEnv *env, jobject self) {
 982     TRY;
 983 
 984     GetCppThis(env, self)->GetWindowsParameters();
 985 
 986     CATCH_BAD_ALLOC;
 987 }
 988 
 989 JNIEXPORT void JNICALL
 990 Java_sun_awt_windows_WDesktopProperties_playWindowsSound(JNIEnv *env, jobject self, jstring event) {
 991     TRY;
 992 
 993     LPCTSTR winEventName;
 994     winEventName = JNU_GetStringPlatformChars(env, event, NULL);
 995     if ( winEventName == NULL ) {
 996         return;
 997     }
 998     GetCppThis(env, self)->PlayWindowsSound(winEventName);
 999     JNU_ReleaseStringPlatformChars(env, event, winEventName);
1000 
1001     CATCH_BAD_ALLOC;
1002 }