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) || defined(INTERNAL_BUILD)
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)
m_pVMEnvHolder268     : 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     }
~EnvHolderEnvHolder283     ~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)
m_env(env)301     : m_env(env),
302     m_localJRef(localJRef)
303     {}
Detach()304     T Detach() {
305         T ret = m_localJRef;
306         m_localJRef = NULL;
307         return ret;
308     }
Attach(T newValue)309     void Attach(T newValue) {
310         if (m_localJRef) {
311             m_env->DeleteLocalRef((jobject)m_localJRef);
312         }
313         m_localJRef = newValue;
314     }
315 
T()316     operator T() { return m_localJRef; }
317     operator bool() { return NULL!=m_localJRef; }
318     bool operator !() { return NULL==m_localJRef; }
319 
~JLocalRef()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;
getNonEmptyString()340     LPWSTR getNonEmptyString() {
341         return (NULL==m_pStr)
342                 ? L""
343                 : m_pStr;
344     }
345 
346 public:
JavaStringBuffer(jsize cbTCharCount)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 
JavaStringBuffer(JNIEnv * env,jstring text)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 
~JavaStringBuffer()368     ~JavaStringBuffer() {
369         free(m_pStr);
370     }
371 
Resize(jsize cbTCharCount)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
LPWSTR()381     operator LPWSTR() { return getNonEmptyString(); }
LPARAM()382     operator LPARAM() { return (LPARAM)getNonEmptyString(); }
GetData()383     void *GetData() { return (void *)getNonEmptyString(); }
GetSize()384     jsize  GetSize() { return m_dwSize; }
385 };
386 
387 
388 #endif  /* _AWT_H_ */
389