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