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