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 
 179 #define IS_WINVER_ATLEAST(maj, min) \
 180                    ((maj) < LOBYTE(LOWORD(::GetVersion())) || \
 181                       (maj) == LOBYTE(LOWORD(::GetVersion())) && \
 182                       (min) <= HIBYTE(LOWORD(::GetVersion())))
 183 
 184 /*
 185  * macros to crack a LPARAM into two ints -- used for signed coordinates,
 186  * such as with mouse messages.
 187  */
 188 #define LO_INT(l)           ((int)(short)(l))
 189 #define HI_INT(l)           ((int)(short)(((DWORD)(l) >> 16) & 0xFFFF))
 190 
 191 extern JavaVM *jvm;
 192 
 193 // Platform encoding is Unicode (UTF-16), re-define JNU_ functions
 194 // to proper JNI functions.
 195 #define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast<const jchar*>(x), static_cast<jsize>(_tcslen(x)))
 196 #define JNU_GetStringPlatformChars(env, x, y) reinterpret_cast<LPCWSTR>(env->GetStringChars(x, y))
 197 #define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, reinterpret_cast<const jchar*>(y))
 198 
 199 /*
 200  * Itanium symbols needed for 64-bit compilation.
 201  * These are defined in winuser.h in the August 2001 MSDN update.
 202  */
 203 #ifndef GCLP_HBRBACKGROUND
 204     #ifdef _WIN64
 205         #error Macros for GetClassLongPtr, etc. are for 32-bit windows only
 206     #endif /* !_WIN64 */
 207     #define GetClassLongPtr GetClassLong
 208     #define SetClassLongPtr SetClassLong
 209     #define GCLP_HBRBACKGROUND GCL_HBRBACKGROUND
 210     #define GCLP_HCURSOR GCL_HCURSOR
 211     #define GCLP_HICON GCL_HICON
 212     #define GCLP_HICONSM GCL_HICONSM
 213     #define GCLP_HMODULE GCL_HMODULE
 214     #define GCLP_MENUNAME GCL_MENUNAME
 215     #define GCLP_WNDPROC GCL_WNDPROC
 216     #define GetWindowLongPtr GetWindowLong
 217     #define SetWindowLongPtr SetWindowLong
 218     #define GWLP_WNDPROC GWL_WNDPROC
 219     #define GWLP_HINSTANCE GWL_HINSTANCE
 220     #define GWLP_HWNDPARENT GWL_HWNDPARENT
 221     #define GWLP_ID GWL_ID
 222     #define GWLP_USERDATA GWL_USERDATA
 223     #define DWLP_DLGPROC DWL_DLGPROC
 224     #define DWLP_MSGRESULT DWL_MSGRESULT
 225     #define DWLP_USER DWL_USER
 226 #endif /* !GCLP_HBRBACKGROUND */
 227 
 228 /*
 229  * macros for saving and restoring FPU control word
 230  * NOTE: float.h must be defined if using these macros
 231  */
 232 #define SAVE_CONTROLWORD  \
 233   unsigned int fpu_cw = _control87(0, 0);
 234 
 235 #define RESTORE_CONTROLWORD  \
 236   if (_control87(0, 0) != fpu_cw) {  \
 237     _control87(fpu_cw, 0xffffffff);  \
 238   }
 239 
 240 /*
 241  * checks if the current thread is/isn't the toolkit thread
 242  */
 243 #if defined(DEBUG) || defined(INTERNAL_BUILD)
 244 #define CHECK_IS_TOOLKIT_THREAD() \
 245   if (GetCurrentThreadId() != AwtToolkit::MainThread())  \
 246   { JNU_ThrowInternalError(env,"Operation is not permitted on non-toolkit thread!\n"); }
 247 #define CHECK_ISNOT_TOOLKIT_THREAD()  \
 248   if (GetCurrentThreadId() == AwtToolkit::MainThread())  \
 249   { JNU_ThrowInternalError(env,"Operation is not permitted on toolkit thread!\n"); }
 250 #else
 251 #define CHECK_IS_TOOLKIT_THREAD()
 252 #define CHECK_ISNOT_TOOLKIT_THREAD()
 253 #endif
 254 
 255 
 256 struct EnvHolder
 257 {
 258     JavaVM *m_pVM;
 259     JNIEnv *m_env;
 260     bool    m_isOwner;
 261     EnvHolder(
 262         JavaVM *pVM,
 263         LPCSTR name = "COM holder",
 264         jint ver = JNI_VERSION_1_2)
 265     : m_pVM(pVM),
 266       m_env((JNIEnv *)JNU_GetEnv(pVM, ver)),
 267       m_isOwner(false)
 268     {
 269         if (NULL == m_env) {
 270             JavaVMAttachArgs attachArgs;
 271             attachArgs.version  = ver;
 272             attachArgs.name     = const_cast<char *>(name);
 273             attachArgs.group    = NULL;
 274             jint status = m_pVM->AttachCurrentThread(
 275                 (void**)&m_env,
 276                 &attachArgs);
 277             m_isOwner = (NULL!=m_env);
 278         }
 279     }
 280     ~EnvHolder() {
 281         if (m_isOwner) {
 282             m_pVM->DetachCurrentThread();
 283         }
 284     }
 285     operator bool()  const { return NULL!=m_env; }
 286     bool operator !()  const { return NULL==m_env; }
 287     operator JNIEnv*() const { return m_env; }
 288     JNIEnv* operator ->() const { return m_env; }
 289 };
 290 
 291 template <class T>
 292 class JLocalRef {
 293     JNIEnv* m_env;
 294     T m_localJRef;
 295 
 296 public:
 297     JLocalRef(JNIEnv* env, T localJRef = NULL)
 298     : m_env(env),
 299     m_localJRef(localJRef)
 300     {}
 301     T Detach() {
 302         T ret = m_localJRef;
 303         m_localJRef = NULL;
 304         return ret;
 305     }
 306     void Attach(T newValue) {
 307         if (m_localJRef) {
 308             m_env->DeleteLocalRef((jobject)m_localJRef);
 309         }
 310         m_localJRef = newValue;
 311     }
 312 
 313     operator T() { return m_localJRef; }
 314     operator bool() { return NULL!=m_localJRef; }
 315     bool operator !() { return NULL==m_localJRef; }
 316 
 317     ~JLocalRef() {
 318         if (m_localJRef) {
 319             m_env->DeleteLocalRef((jobject)m_localJRef);
 320         }
 321     }
 322 };
 323 
 324 typedef JLocalRef<jobject> JLObject;
 325 typedef JLocalRef<jstring> JLString;
 326 typedef JLocalRef<jclass>  JLClass;
 327 
 328 /*
 329  * Class to encapsulate the extraction of the java string contents
 330  * into a buffer and the cleanup of the buffer
 331  */
 332 class JavaStringBuffer
 333 {
 334 protected:
 335     LPWSTR m_pStr;
 336     jsize  m_dwSize;
 337     LPWSTR getNonEmptyString() {
 338         return (NULL==m_pStr)
 339                 ? L""
 340                 : m_pStr;
 341     }
 342 
 343 public:
 344     JavaStringBuffer(jsize cbTCharCount) {
 345         m_dwSize = cbTCharCount;
 346         m_pStr = (0 == m_dwSize)
 347             ? NULL
 348             : (LPWSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (m_dwSize+1), sizeof(WCHAR) );
 349     }
 350 
 351     JavaStringBuffer(JNIEnv *env, jstring text) {
 352         m_dwSize = (NULL == text)
 353             ? 0
 354             : env->GetStringLength(text);
 355         if (0 == m_dwSize) {
 356             m_pStr = NULL;
 357         } else {
 358             m_pStr = (LPWSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (m_dwSize+1), sizeof(WCHAR) );
 359             env->GetStringRegion(text, 0, m_dwSize, reinterpret_cast<jchar *>(m_pStr));
 360             m_pStr[m_dwSize] = 0;
 361         }
 362     }
 363 
 364 
 365     ~JavaStringBuffer() {
 366         free(m_pStr);
 367     }
 368 
 369     void Resize(jsize cbTCharCount) {
 370         m_dwSize = cbTCharCount;
 371         //It is ok to have non-null terminated string here.
 372         //The function is used only for space reservation in staff buffer for
 373         //followed data copying process. And that is the reason why we ignore
 374         //the special case m_dwSize==0 here.
 375         m_pStr = (LPWSTR)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, m_pStr, m_dwSize+1, sizeof(WCHAR) );
 376     }
 377     //we are in UNICODE now, so LPWSTR:=:LPTSTR
 378     operator LPWSTR() { return getNonEmptyString(); }
 379     operator LPARAM() { return (LPARAM)getNonEmptyString(); }
 380     void *GetData() { return (void *)getNonEmptyString(); }
 381     jsize  GetSize() { return m_dwSize; }
 382 };
 383 
 384 
 385 #endif  /* _AWT_H_ */