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