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_NULL_RETURN(obj, msg) {                                 \
  61     if (obj == NULL) {                                                    \
  62         env->ExceptionClear();                                            \
  63         JNU_ThrowNullPointerException(env, msg);                          \
  64         return;                                                           \
  65     }                                                                     \
  66 }
  67 
  68 #define JNI_CHECK_PEER_CREATION_RETURN(peer) {                            \
  69     if (peer == NULL ) {                                                  \
  70         return;                                                           \
  71     }                                                                     \
  72     pData = JNI_GET_PDATA(peer);                                          \
  73     if (pData == NULL) {                                                  \
  74         return;                                                           \
  75     }                                                                     \
  76 }
  77 
  78 #define JNI_CHECK_NULL_RETURN_NULL(obj, msg) {                            \
  79     if (obj == NULL) {                                                    \
  80         env->ExceptionClear();                                            \
  81         JNU_ThrowNullPointerException(env, msg);                          \
  82         return 0;                                                         \
  83     }                                                                     \
  84 }
  85 
  86 #define JNI_CHECK_NULL_RETURN_VAL(obj, msg, val) {                        \
  87     if (obj == NULL) {                                                    \
  88         env->ExceptionClear();                                            \
  89         JNU_ThrowNullPointerException(env, msg);                          \
  90         return val;                                                       \
  91     }                                                                     \
  92 }
  93 
  94 /**
  95  * This macros must be used under SyncCall or on the Toolkit thread.
  96  */
  97 #define JNI_CHECK_PEER_GOTO(peer, where) {                                \
  98     JNI_CHECK_NULL_GOTO(peer, "peer", where);                             \
  99     pData = JNI_GET_PDATA(peer);                                          \
 100     if (pData == NULL) {                                                  \
 101         THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
 102         goto where;                                                       \
 103     }                                                                     \
 104 }
 105 
 106 /**
 107  * This macros must be used under SyncCall or on the Toolkit thread.
 108  */
 109 #define JNI_CHECK_PEER_RETURN(peer) {                                     \
 110     JNI_CHECK_NULL_RETURN(peer, "peer");                                  \
 111     pData = JNI_GET_PDATA(peer);                                          \
 112     if (pData == NULL) {                                                  \
 113         THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
 114         return;                                                           \
 115     }                                                                     \
 116 }
 117 
 118 /**
 119  * This macros must be used under SyncCall or on the Toolkit thread.
 120  */
 121 #define JNI_CHECK_PEER_RETURN_NULL(peer) {                                \
 122     JNI_CHECK_NULL_RETURN_NULL(peer, "peer");                             \
 123     pData = JNI_GET_PDATA(peer);                                          \
 124     if (pData == NULL) {                                                  \
 125         THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
 126         return 0;                                                         \
 127     }                                                                     \
 128 }
 129 
 130 /**
 131  * This macros must be used under SyncCall or on the Toolkit thread.
 132  */
 133 #define JNI_CHECK_PEER_RETURN_VAL(peer, val) {                            \
 134     JNI_CHECK_NULL_RETURN_VAL(peer, "peer", val);                         \
 135     pData = JNI_GET_PDATA(peer);                                          \
 136     if (pData == NULL) {                                                  \
 137         THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
 138         return val;                                                       \
 139     }                                                                     \
 140 }
 141 
 142 #define THROW_NULL_PDATA_IF_NOT_DESTROYED(peer) {                         \
 143     jboolean destroyed = JNI_GET_DESTROYED(peer);                         \
 144     if (destroyed != JNI_TRUE) {                                          \
 145         env->ExceptionClear();                                            \
 146         JNU_ThrowNullPointerException(env, "null pData");                 \
 147     }                                                                     \
 148 }
 149 
 150 #define JNI_GET_PDATA(peer) (PDATA) env->GetLongField(peer, AwtObject::pDataID)
 151 #define JNI_GET_DESTROYED(peer) env->GetBooleanField(peer, AwtObject::destroyedID)
 152 
 153 #define JNI_SET_PDATA(peer, data) env->SetLongField(peer,                  \
 154                                                     AwtObject::pDataID,    \
 155                                                     (jlong)data)
 156 #define JNI_SET_DESTROYED(peer) env->SetBooleanField(peer,                   \
 157                                                      AwtObject::destroyedID, \
 158                                                      JNI_TRUE)
 159 /*  /NEW JNI */
 160 
 161 /*
 162  * IS_WIN64 returns TRUE on 64-bit Itanium
 163  */
 164 #if defined (_WIN64)
 165     #define IS_WIN64 TRUE
 166 #else
 167     #define IS_WIN64 FALSE
 168 #endif
 169 
 170 /*
 171  * IS_WIN2000 returns TRUE on 2000, XP and Vista
 172  * IS_WINXP returns TRUE on XP and Vista
 173  * IS_WINVISTA returns TRUE on Vista
 174  */
 175 #define IS_WIN2000 (LOBYTE(LOWORD(::GetVersion())) >= 5)
 176 #define IS_WINXP ((IS_WIN2000 && HIBYTE(LOWORD(::GetVersion())) >= 1) || LOBYTE(LOWORD(::GetVersion())) > 5)
 177 #define IS_WINVISTA (LOBYTE(LOWORD(::GetVersion())) >= 6)
 178 #define IS_WIN8 (                                                              \
 179     (IS_WINVISTA && (HIBYTE(LOWORD(::GetVersion())) >= 2)) ||                  \
 180     (LOBYTE(LOWORD(::GetVersion())) > 6))
 181 
 182 #define IS_WINVER_ATLEAST(maj, min) \
 183                    ((maj) < LOBYTE(LOWORD(::GetVersion())) || \
 184                       (maj) == LOBYTE(LOWORD(::GetVersion())) && \
 185                       (min) <= HIBYTE(LOWORD(::GetVersion())))
 186 
 187 /*
 188  * macros to crack a LPARAM into two ints -- used for signed coordinates,
 189  * such as with mouse messages.
 190  */
 191 #define LO_INT(l)           ((int)(short)(l))
 192 #define HI_INT(l)           ((int)(short)(((DWORD)(l) >> 16) & 0xFFFF))
 193 
 194 extern JavaVM *jvm;
 195 
 196 // Platform encoding is Unicode (UTF-16), re-define JNU_ functions
 197 // to proper JNI functions.
 198 #define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast<const jchar*>(x), static_cast<jsize>(_tcslen(x)))
 199 #define JNU_GetStringPlatformChars(env, x, y) reinterpret_cast<LPCWSTR>(env->GetStringChars(x, y))
 200 #define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, reinterpret_cast<const jchar*>(y))
 201 
 202 /*
 203  * Itanium symbols needed for 64-bit compilation.
 204  * These are defined in winuser.h in the August 2001 MSDN update.
 205  */
 206 #ifndef GCLP_HBRBACKGROUND
 207     #ifdef _WIN64
 208         #error Macros for GetClassLongPtr, etc. are for 32-bit windows only
 209     #endif /* !_WIN64 */
 210     #define GetClassLongPtr GetClassLong
 211     #define SetClassLongPtr SetClassLong
 212     #define GCLP_HBRBACKGROUND GCL_HBRBACKGROUND
 213     #define GCLP_HCURSOR GCL_HCURSOR
 214     #define GCLP_HICON GCL_HICON
 215     #define GCLP_HICONSM GCL_HICONSM
 216     #define GCLP_HMODULE GCL_HMODULE
 217     #define GCLP_MENUNAME GCL_MENUNAME
 218     #define GCLP_WNDPROC GCL_WNDPROC
 219     #define GetWindowLongPtr GetWindowLong
 220     #define SetWindowLongPtr SetWindowLong
 221     #define GWLP_WNDPROC GWL_WNDPROC
 222     #define GWLP_HINSTANCE GWL_HINSTANCE
 223     #define GWLP_HWNDPARENT GWL_HWNDPARENT
 224     #define GWLP_ID GWL_ID
 225     #define GWLP_USERDATA GWL_USERDATA
 226     #define DWLP_DLGPROC DWL_DLGPROC
 227     #define DWLP_MSGRESULT DWL_MSGRESULT
 228     #define DWLP_USER DWL_USER
 229 #endif /* !GCLP_HBRBACKGROUND */
 230 
 231 /*
 232  * macros for saving and restoring FPU control word
 233  * NOTE: float.h must be defined if using these macros
 234  */
 235 #define SAVE_CONTROLWORD  \
 236   unsigned int fpu_cw = _control87(0, 0);
 237 
 238 #define RESTORE_CONTROLWORD  \
 239   if (_control87(0, 0) != fpu_cw) {  \
 240     _control87(fpu_cw, 0xffffffff);  \
 241   }
 242 
 243 /*
 244  * checks if the current thread is/isn't the toolkit thread
 245  */
 246 #if defined(DEBUG)
 247 #define CHECK_IS_TOOLKIT_THREAD() \
 248   if (GetCurrentThreadId() != AwtToolkit::MainThread())  \
 249   { JNU_ThrowInternalError(env,"Operation is not permitted on non-toolkit thread!\n"); }
 250 #define CHECK_ISNOT_TOOLKIT_THREAD()  \
 251   if (GetCurrentThreadId() == AwtToolkit::MainThread())  \
 252   { JNU_ThrowInternalError(env,"Operation is not permitted on toolkit thread!\n"); }
 253 #else
 254 #define CHECK_IS_TOOLKIT_THREAD()
 255 #define CHECK_ISNOT_TOOLKIT_THREAD()
 256 #endif
 257 
 258 
 259 struct EnvHolder
 260 {
 261     JavaVM *m_pVM;
 262     JNIEnv *m_env;
 263     bool    m_isOwner;
 264     EnvHolder(
 265         JavaVM *pVM,
 266         LPCSTR name = "COM holder",
 267         jint ver = JNI_VERSION_1_2)
 268     : m_pVM(pVM),
 269       m_env((JNIEnv *)JNU_GetEnv(pVM, ver)),
 270       m_isOwner(false)
 271     {
 272         if (NULL == m_env) {
 273             JavaVMAttachArgs attachArgs;
 274             attachArgs.version  = ver;
 275             attachArgs.name     = const_cast<char *>(name);
 276             attachArgs.group    = NULL;
 277             jint status = m_pVM->AttachCurrentThread(
 278                 (void**)&m_env,
 279                 &attachArgs);
 280             m_isOwner = (NULL!=m_env);
 281         }
 282     }
 283     ~EnvHolder() {
 284         if (m_isOwner) {
 285             m_pVM->DetachCurrentThread();
 286         }
 287     }
 288     operator bool()  const { return NULL!=m_env; }
 289     bool operator !()  const { return NULL==m_env; }
 290     operator JNIEnv*() const { return m_env; }
 291     JNIEnv* operator ->() const { return m_env; }
 292 };
 293 
 294 template <class T>
 295 class JLocalRef {
 296     JNIEnv* m_env;
 297     T m_localJRef;
 298 
 299 public:
 300     JLocalRef(JNIEnv* env, T localJRef = NULL)
 301     : m_env(env),
 302     m_localJRef(localJRef)
 303     {}
 304     T Detach() {
 305         T ret = m_localJRef;
 306         m_localJRef = NULL;
 307         return ret;
 308     }
 309     void Attach(T newValue) {
 310         if (m_localJRef) {
 311             m_env->DeleteLocalRef((jobject)m_localJRef);
 312         }
 313         m_localJRef = newValue;
 314     }
 315 
 316     operator T() { return m_localJRef; }
 317     operator bool() { return NULL!=m_localJRef; }
 318     bool operator !() { return NULL==m_localJRef; }
 319 
 320     ~JLocalRef() {
 321         if (m_localJRef) {
 322             m_env->DeleteLocalRef((jobject)m_localJRef);
 323         }
 324     }
 325 };
 326 
 327 typedef JLocalRef<jobject> JLObject;
 328 typedef JLocalRef<jstring> JLString;
 329 typedef JLocalRef<jclass>  JLClass;
 330 
 331 /*
 332  * Class to encapsulate the extraction of the java string contents
 333  * into a buffer and the cleanup of the buffer
 334  */
 335 class JavaStringBuffer
 336 {
 337 protected:
 338     LPWSTR m_pStr;
 339     jsize  m_dwSize;
 340     LPWSTR getNonEmptyString() {
 341         return (NULL==m_pStr)
 342                 ? L""
 343                 : m_pStr;
 344     }
 345 
 346 public:
 347     JavaStringBuffer(jsize cbTCharCount) {
 348         m_dwSize = cbTCharCount;
 349         m_pStr = (0 == m_dwSize)
 350             ? NULL
 351             : (LPWSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (m_dwSize+1), sizeof(WCHAR) );
 352     }
 353 
 354     JavaStringBuffer(JNIEnv *env, jstring text) {
 355         m_dwSize = (NULL == text)
 356             ? 0
 357             : env->GetStringLength(text);
 358         if (0 == m_dwSize) {
 359             m_pStr = NULL;
 360         } else {
 361             m_pStr = (LPWSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (m_dwSize+1), sizeof(WCHAR) );
 362             env->GetStringRegion(text, 0, m_dwSize, reinterpret_cast<jchar *>(m_pStr));
 363             m_pStr[m_dwSize] = 0;
 364         }
 365     }
 366 
 367 
 368     ~JavaStringBuffer() {
 369         free(m_pStr);
 370     }
 371 
 372     void Resize(jsize cbTCharCount) {
 373         m_dwSize = cbTCharCount;
 374         //It is ok to have non-null terminated string here.
 375         //The function is used only for space reservation in staff buffer for
 376         //followed data copying process. And that is the reason why we ignore
 377         //the special case m_dwSize==0 here.
 378         m_pStr = (LPWSTR)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, m_pStr, m_dwSize+1, sizeof(WCHAR) );
 379     }
 380     //we are in UNICODE now, so LPWSTR:=:LPTSTR
 381     operator LPWSTR() { return getNonEmptyString(); }
 382     operator LPARAM() { return (LPARAM)getNonEmptyString(); }
 383     void *GetData() { return (void *)getNonEmptyString(); }
 384     jsize  GetSize() { return m_dwSize; }
 385 };
 386 
 387 
 388 #endif  /* _AWT_H_ */