1 /*
   2  * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #ifndef _AWT_H_
  27 #define _AWT_H_
  28 
  29 #ifndef _WIN32_WINNT
  30 #define _WIN32_WINNT 0x0600
  31 #endif
  32 
  33 #ifndef _WIN32_IE
  34 #define _WIN32_IE 0x0600
  35 #endif
  36 
  37 //#ifndef NTDDI_VERSION
  38 //#define NTDDI_VERSION NTDDI_LONGHORN
  39 //#endif
  40 
  41 #include "stdhdrs.h"
  42 #include "alloc.h"
  43 #include "awt_Debug.h"
  44 
  45 extern COLORREF DesktopColor2RGB(int colorIndex);
  46 
  47 class AwtObject;
  48 typedef AwtObject* PDATA;
  49 
  50 #define JNI_IS_TRUE(obj) ((obj) ? JNI_TRUE : JNI_FALSE)
  51 
  52 #define JNI_CHECK_NULL_GOTO(obj, msg, where) {                            \
  53     if (obj == NULL) {                                                    \
  54         env->ExceptionClear();                                            \
  55         JNU_ThrowNullPointerException(env, msg);                          \
  56         goto where;                                                       \
  57     }                                                                     \
  58 }
  59 
  60 #define JNI_CHECK_PEER_GOTO(peer, where) {                                \
  61     JNI_CHECK_NULL_GOTO(peer, "peer", where);                             \
  62     pData = JNI_GET_PDATA(peer);                                          \
  63     if (pData == NULL) {                                                  \
  64         THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
  65         goto where;                                                       \
  66     }                                                                     \
  67 }
  68 
  69 #define JNI_CHECK_NULL_RETURN(obj, msg) {                                 \
  70     if (obj == NULL) {                                                    \
  71         env->ExceptionClear();                                            \
  72         JNU_ThrowNullPointerException(env, msg);                          \
  73         return;                                                           \
  74     }                                                                     \
  75 }
  76 
  77 #define JNI_CHECK_PEER_RETURN(peer) {                                     \
  78     JNI_CHECK_NULL_RETURN(peer, "peer");                                  \
  79     pData = JNI_GET_PDATA(peer);                                          \
  80     if (pData == NULL) {                                                  \
  81         THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
  82         return;                                                           \
  83     }                                                                     \
  84 }
  85 
  86 #define JNI_CHECK_PEER_CREATION_RETURN(peer) {                            \
  87     if (peer == NULL ) {                                                  \
  88         return;                                                           \
  89     }                                                                     \
  90     pData = JNI_GET_PDATA(peer);                                          \
  91     if (pData == NULL) {                                                  \
  92         return;                                                           \
  93     }                                                                     \
  94 }
  95 
  96 #define JNI_CHECK_NULL_RETURN_NULL(obj, msg) {                            \
  97     if (obj == NULL) {                                                    \
  98         env->ExceptionClear();                                            \
  99         JNU_ThrowNullPointerException(env, msg);                          \
 100         return 0;                                                         \
 101     }                                                                     \
 102 }
 103 
 104 #define JNI_CHECK_NULL_RETURN_VAL(obj, msg, val) {                        \
 105     if (obj == NULL) {                                                    \
 106         env->ExceptionClear();                                            \
 107         JNU_ThrowNullPointerException(env, msg);                          \
 108         return val;                                                       \
 109     }                                                                     \
 110 }
 111 
 112 #define JNI_CHECK_PEER_RETURN_NULL(peer) {                                \
 113     JNI_CHECK_NULL_RETURN_NULL(peer, "peer");                             \
 114     pData = JNI_GET_PDATA(peer);                                          \
 115     if (pData == NULL) {                                                  \
 116         THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
 117         return 0;                                                         \
 118     }                                                                     \
 119 }
 120 
 121 #define JNI_CHECK_PEER_RETURN_VAL(peer, val) {                            \
 122     JNI_CHECK_NULL_RETURN_VAL(peer, "peer", val);                         \
 123     pData = JNI_GET_PDATA(peer);                                          \
 124     if (pData == NULL) {                                                  \
 125         THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
 126         return val;                                                       \
 127     }                                                                     \
 128 }
 129 
 130 #define THROW_NULL_PDATA_IF_NOT_DESTROYED(peer) {                         \
 131     jboolean destroyed = JNI_GET_DESTROYED(peer);                         \
 132     if (destroyed != JNI_TRUE) {                                          \
 133         env->ExceptionClear();                                            \
 134         JNU_ThrowNullPointerException(env, "null pData");                 \
 135     }                                                                     \
 136 }
 137 
 138 #define JNI_GET_PDATA(peer) (PDATA) env->GetLongField(peer, AwtObject::pDataID)
 139 #define JNI_GET_DESTROYED(peer) env->GetBooleanField(peer, AwtObject::destroyedID)
 140 
 141 #define JNI_SET_PDATA(peer, data) env->SetLongField(peer,                  \
 142                                                     AwtObject::pDataID,    \
 143                                                     (jlong)data)
 144 #define JNI_SET_DESTROYED(peer) env->SetBooleanField(peer,                   \
 145                                                      AwtObject::destroyedID, \
 146                                                      JNI_TRUE)
 147 /*  /NEW JNI */
 148 
 149 /*
 150  * IS_WIN64 returns TRUE on 64-bit Itanium
 151  */
 152 #if defined (_WIN64)
 153     #define IS_WIN64 TRUE
 154 #else
 155     #define IS_WIN64 FALSE
 156 #endif
 157 
 158 /*
 159  * IS_WIN2000 returns TRUE on 2000, XP and Vista
 160  * IS_WINXP returns TRUE on XP and Vista
 161  * IS_WINVISTA returns TRUE on Vista
 162  */
 163 #define IS_WIN2000 (LOBYTE(LOWORD(::GetVersion())) >= 5)
 164 #define IS_WINXP ((IS_WIN2000 && HIBYTE(LOWORD(::GetVersion())) >= 1) || LOBYTE(LOWORD(::GetVersion())) > 5)
 165 #define IS_WINVISTA (LOBYTE(LOWORD(::GetVersion())) >= 6)
 166 #define IS_WIN8 (                                                              \
 167     (IS_WINVISTA && (HIBYTE(LOWORD(::GetVersion())) >= 2)) ||                  \
 168     (LOBYTE(LOWORD(::GetVersion())) > 6))
 169 
 170 #define IS_WINVER_ATLEAST(maj, min) \
 171                    ((maj) < LOBYTE(LOWORD(::GetVersion())) || \
 172                       (maj) == LOBYTE(LOWORD(::GetVersion())) && \
 173                       (min) <= HIBYTE(LOWORD(::GetVersion())))
 174 
 175 /*
 176  * macros to crack a LPARAM into two ints -- used for signed coordinates,
 177  * such as with mouse messages.
 178  */
 179 #define LO_INT(l)           ((int)(short)(l))
 180 #define HI_INT(l)           ((int)(short)(((DWORD)(l) >> 16) & 0xFFFF))
 181 
 182 extern JavaVM *jvm;
 183 
 184 // Platform encoding is Unicode (UTF-16), re-define JNU_ functions
 185 // to proper JNI functions.
 186 #define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast<const jchar*>(x), static_cast<jsize>(_tcslen(x)))
 187 #define JNU_GetStringPlatformChars(env, x, y) reinterpret_cast<LPCWSTR>(env->GetStringChars(x, y))
 188 #define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, reinterpret_cast<const jchar*>(y))
 189 
 190 /*
 191  * Itanium symbols needed for 64-bit compilation.
 192  * These are defined in winuser.h in the August 2001 MSDN update.
 193  */
 194 #ifndef GCLP_HBRBACKGROUND
 195     #ifdef _WIN64
 196         #error Macros for GetClassLongPtr, etc. are for 32-bit windows only
 197     #endif /* !_WIN64 */
 198     #define GetClassLongPtr GetClassLong
 199     #define SetClassLongPtr SetClassLong
 200     #define GCLP_HBRBACKGROUND GCL_HBRBACKGROUND
 201     #define GCLP_HCURSOR GCL_HCURSOR
 202     #define GCLP_HICON GCL_HICON
 203     #define GCLP_HICONSM GCL_HICONSM
 204     #define GCLP_HMODULE GCL_HMODULE
 205     #define GCLP_MENUNAME GCL_MENUNAME
 206     #define GCLP_WNDPROC GCL_WNDPROC
 207     #define GetWindowLongPtr GetWindowLong
 208     #define SetWindowLongPtr SetWindowLong
 209     #define GWLP_WNDPROC GWL_WNDPROC
 210     #define GWLP_HINSTANCE GWL_HINSTANCE
 211     #define GWLP_HWNDPARENT GWL_HWNDPARENT
 212     #define GWLP_ID GWL_ID
 213     #define GWLP_USERDATA GWL_USERDATA
 214     #define DWLP_DLGPROC DWL_DLGPROC
 215     #define DWLP_MSGRESULT DWL_MSGRESULT
 216     #define DWLP_USER DWL_USER
 217 #endif /* !GCLP_HBRBACKGROUND */
 218 
 219 /*
 220  * macros for saving and restoring FPU control word
 221  * NOTE: float.h must be defined if using these macros
 222  */
 223 #define SAVE_CONTROLWORD  \
 224   unsigned int fpu_cw = _control87(0, 0);
 225 
 226 #define RESTORE_CONTROLWORD  \
 227   if (_control87(0, 0) != fpu_cw) {  \
 228     _control87(fpu_cw, 0xffffffff);  \
 229   }
 230 
 231 /*
 232  * checks if the current thread is/isn't the toolkit thread
 233  */
 234 #if defined(DEBUG) || defined(INTERNAL_BUILD)
 235 #define CHECK_IS_TOOLKIT_THREAD() \
 236   if (GetCurrentThreadId() != AwtToolkit::MainThread())  \
 237   { JNU_ThrowInternalError(env,"Operation is not permitted on non-toolkit thread!\n"); }
 238 #define CHECK_ISNOT_TOOLKIT_THREAD()  \
 239   if (GetCurrentThreadId() == AwtToolkit::MainThread())  \
 240   { JNU_ThrowInternalError(env,"Operation is not permitted on toolkit thread!\n"); }
 241 #else
 242 #define CHECK_IS_TOOLKIT_THREAD()
 243 #define CHECK_ISNOT_TOOLKIT_THREAD()
 244 #endif
 245 
 246 
 247 struct EnvHolder
 248 {
 249     JavaVM *m_pVM;
 250     JNIEnv *m_env;
 251     bool    m_isOwner;
 252     EnvHolder(
 253         JavaVM *pVM,
 254         LPCSTR name = "COM holder",
 255         jint ver = JNI_VERSION_1_2)
 256     : m_pVM(pVM),
 257       m_env((JNIEnv *)JNU_GetEnv(pVM, ver)),
 258       m_isOwner(false)
 259     {
 260         if (NULL == m_env) {
 261             JavaVMAttachArgs attachArgs;
 262             attachArgs.version  = ver;
 263             attachArgs.name     = const_cast<char *>(name);
 264             attachArgs.group    = NULL;
 265             jint status = m_pVM->AttachCurrentThread(
 266                 (void**)&m_env,
 267                 &attachArgs);
 268             m_isOwner = (NULL!=m_env);
 269         }
 270     }
 271     ~EnvHolder() {
 272         if (m_isOwner) {
 273             m_pVM->DetachCurrentThread();
 274         }
 275     }
 276     operator bool()  const { return NULL!=m_env; }
 277     bool operator !()  const { return NULL==m_env; }
 278     operator JNIEnv*() const { return m_env; }
 279     JNIEnv* operator ->() const { return m_env; }
 280 };
 281 
 282 template <class T>
 283 class JLocalRef {
 284     JNIEnv* m_env;
 285     T m_localJRef;
 286 
 287 public:
 288     JLocalRef(JNIEnv* env, T localJRef = NULL)
 289     : m_env(env),
 290     m_localJRef(localJRef)
 291     {}
 292     T Detach() {
 293         T ret = m_localJRef;
 294         m_localJRef = NULL;
 295         return ret;
 296     }
 297     void Attach(T newValue) {
 298         if (m_localJRef) {
 299             m_env->DeleteLocalRef((jobject)m_localJRef);
 300         }
 301         m_localJRef = newValue;
 302     }
 303 
 304     operator T() { return m_localJRef; }
 305     operator bool() { return NULL!=m_localJRef; }
 306     bool operator !() { return NULL==m_localJRef; }
 307 
 308     ~JLocalRef() {
 309         if (m_localJRef) {
 310             m_env->DeleteLocalRef((jobject)m_localJRef);
 311         }
 312     }
 313 };
 314 
 315 typedef JLocalRef<jobject> JLObject;
 316 typedef JLocalRef<jstring> JLString;
 317 typedef JLocalRef<jclass>  JLClass;
 318 
 319 /*
 320  * Class to encapsulate the extraction of the java string contents
 321  * into a buffer and the cleanup of the buffer
 322  */
 323 class JavaStringBuffer
 324 {
 325 protected:
 326     LPWSTR m_pStr;
 327     jsize  m_dwSize;
 328     LPWSTR getNonEmptyString() {
 329         return (NULL==m_pStr)
 330                 ? L""
 331                 : m_pStr;
 332     }
 333 
 334 public:
 335     JavaStringBuffer(jsize cbTCharCount) {
 336         m_dwSize = cbTCharCount;
 337         m_pStr = (0 == m_dwSize)
 338             ? NULL
 339             : (LPWSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (m_dwSize+1), sizeof(WCHAR) );
 340     }
 341 
 342     JavaStringBuffer(JNIEnv *env, jstring text) {
 343         m_dwSize = (NULL == text)
 344             ? 0
 345             : env->GetStringLength(text);
 346         if (0 == m_dwSize) {
 347             m_pStr = NULL;
 348         } else {
 349             m_pStr = (LPWSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (m_dwSize+1), sizeof(WCHAR) );
 350             env->GetStringRegion(text, 0, m_dwSize, reinterpret_cast<jchar *>(m_pStr));
 351             m_pStr[m_dwSize] = 0;
 352         }
 353     }
 354 
 355 
 356     ~JavaStringBuffer() {
 357         free(m_pStr);
 358     }
 359 
 360     void Resize(jsize cbTCharCount) {
 361         m_dwSize = cbTCharCount;
 362         //It is ok to have non-null terminated string here.
 363         //The function is used only for space reservation in staff buffer for
 364         //followed data copying process. And that is the reason why we ignore
 365         //the special case m_dwSize==0 here.
 366         m_pStr = (LPWSTR)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, m_pStr, m_dwSize+1, sizeof(WCHAR) );
 367     }
 368     //we are in UNICODE now, so LPWSTR:=:LPTSTR
 369     operator LPWSTR() { return getNonEmptyString(); }
 370     operator LPARAM() { return (LPARAM)getNonEmptyString(); }
 371     void *GetData() { return (void *)getNonEmptyString(); }
 372     jsize  GetSize() { return m_dwSize; }
 373 };
 374 
 375 
 376 #endif  /* _AWT_H_ */