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