1 // win32.cc - Helper functions for Microsoft-flavored OSs.
3 /* Copyright (C) 2002, 2003 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
13 #include <sys/timeb.h>
17 #include <java/lang/ArithmeticException.h>
18 #include <java/lang/UnsupportedOperationException.h>
19 #include <java/io/IOException.h>
20 #include <java/net/SocketException.h>
21 #include <java/util/Properties.h>
24 win32_exception_handler (LPEXCEPTION_POINTERS e
)
26 if (e
->ExceptionRecord
->ExceptionCode
== EXCEPTION_ACCESS_VIOLATION
)
27 _Jv_ThrowNullPointerException();
28 else if (e
->ExceptionRecord
->ExceptionCode
== EXCEPTION_INT_DIVIDE_BY_ZERO
)
29 throw new java::lang::ArithmeticException
;
31 return EXCEPTION_CONTINUE_SEARCH
;
34 // Platform-specific executable name
35 static char exec_name
[MAX_PATH
];
36 // initialized in _Jv_platform_initialize()
38 const char *_Jv_ThisExecutable (void)
43 // Helper classes and methods implementation
45 #ifdef MINGW_LIBGCJ_UNICODE
47 // We're using the OS W (UNICODE) API, which means that we're speaking
48 // the same language....
50 _Jv_Win32NewString (LPCTSTR pcsz
)
52 return JvNewString ((jchar
*) pcsz
, _tcslen (pcsz
));
57 // We're using the OS A functions, which means we need to translate between
58 // UNICODE and the native character set.
60 // First, let's set up some helper translation functions....
62 // Converts the native string to any specified jstring, returning the
63 // length of the jstring. If the specified jstring is null, we simply
64 // compute and return the length.
65 static int nativeToUnicode(LPCSTR pcsz
, jstring jstr
= 0)
72 buf
= JvGetStringChars(jstr
);
74 return ::MultiByteToWideChar(GetACP(), 0, pcsz
,
75 strlen(pcsz
), (LPWSTR
) buf
, len
);
78 // Does the inverse of nativeToUnicode, with the same calling semantics.
79 static int unicodeToNative(jstring jstr
, LPSTR buf
, int buflen
)
81 return ::WideCharToMultiByte(GetACP(), 0, (LPWSTR
) JvGetStringChars(jstr
),
82 jstr
->length(), buf
, buflen
, NULL
, NULL
);
85 // Convenience function when the caller only wants to compute the length
86 // of the native string.
87 static int unicodeToNative(jstring jstr
)
89 return unicodeToNative(jstr
, 0, 0);
93 _Jv_Win32NewString (LPCTSTR pcsz
)
95 // Compute the length, allocate the jstring, then perform the conversion.
96 int len
= nativeToUnicode(pcsz
);
97 jstring jstr
= JvAllocString(len
);
98 nativeToUnicode(pcsz
, jstr
);
102 #endif // MINGW_LIBGCJ_UNICODE
104 // class _Jv_Win32TempString
105 _Jv_Win32TempString::_Jv_Win32TempString(jstring jstr
):
111 // We need space for the string length plus a null terminator.
112 // Determine whether to use our stack-allocated buffer or a heap-
114 #ifdef MINGW_LIBGCJ_UNICODE
115 // A UNICODE character is a UNICODE character is a UNICODE character....
116 int len
= jstr
->length();
118 // Compute the length of the native character string.
119 int len
= unicodeToNative(jstr
);
120 #endif // MINGW_LIBGCJ_UNICODE
122 int bytesNeeded
= (len
+ 1) * sizeof(TCHAR
);
123 if (bytesNeeded
<= (int) sizeof(stackbuf_
))
126 buf_
= (LPTSTR
) _Jv_Malloc(bytesNeeded
);
128 #ifdef MINGW_LIBGCJ_UNICODE
129 // Copy the UNICODE characters to our buffer.
130 _tcsncpy(buf_
, (LPCTSTR
) JvGetStringChars (jstr
), len
);
132 // Convert the UNICODE string to a native one.
133 unicodeToNative(jstr
, buf_
, len
);
134 #endif // MINGW_LIBGCJ_UNICODE
139 _Jv_Win32TempString::~_Jv_Win32TempString()
141 if (buf_
&& buf_
!= stackbuf_
)
145 // class WSAEventWrapper
146 WSAEventWrapper::WSAEventWrapper (int fd
, DWORD dwSelFlags
):
149 m_dwSelFlags(dwSelFlags
)
151 m_hEvent
= WSACreateEvent ();
153 WSAEventSelect(fd
, m_hEvent
, dwSelFlags
);
156 WSAEventWrapper::~WSAEventWrapper ()
160 WSAEventSelect(m_fd
, m_hEvent
, 0);
161 if (m_dwSelFlags
& (FD_ACCEPT
| FD_CONNECT
))
163 // Set the socket back to non-blocking mode.
164 // Ignore any error since we're in a destructor.
165 unsigned long lSockOpt
= 0L;
167 ::ioctlsocket (m_fd
, FIONBIO
, &lSockOpt
);
170 WSACloseEvent (m_hEvent
);
173 // Error string text.
175 _Jv_WinStrError (LPCTSTR lpszPrologue
, int nErrorCode
)
179 DWORD dwFlags
= FORMAT_MESSAGE_ALLOCATE_BUFFER
|
180 FORMAT_MESSAGE_FROM_SYSTEM
|
181 FORMAT_MESSAGE_IGNORE_INSERTS
;
183 FormatMessage (dwFlags
,
186 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
195 (LPTSTR
) _Jv_Malloc ((_tcslen (lpszPrologue
) +
196 _tcslen (lpMsgBuf
) + 3) * sizeof(TCHAR
) );
197 _tcscpy (lpszTemp
, lpszPrologue
);
198 _tcscat (lpszTemp
, _T(": "));
199 _tcscat (lpszTemp
, lpMsgBuf
);
200 ret
= _Jv_Win32NewString (lpszTemp
);
205 ret
= _Jv_Win32NewString (lpMsgBuf
);
213 _Jv_WinStrError (int nErrorCode
)
215 return _Jv_WinStrError (0, nErrorCode
);
218 void _Jv_ThrowIOException (DWORD dwErrorCode
)
220 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode
));
223 void _Jv_ThrowIOException()
225 DWORD dwErrorCode
= WSAGetLastError ();
226 _Jv_ThrowIOException (dwErrorCode
);
229 void _Jv_ThrowSocketException (DWORD dwErrorCode
)
231 throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode
));
234 void _Jv_ThrowSocketException()
236 DWORD dwErrorCode
= WSAGetLastError ();
237 _Jv_ThrowSocketException (dwErrorCode
);
240 // Platform-specific VM initialization.
242 _Jv_platform_initialize (void)
244 // Initialise winsock for networking
246 if (WSAStartup (MAKEWORD (1, 1), &data
))
247 MessageBox (NULL
, _T("Error initialising winsock library."), _T("Error"),
248 MB_OK
| MB_ICONEXCLAMATION
);
250 // Install exception handler
251 SetUnhandledExceptionFilter (win32_exception_handler
);
253 // Initialize our executable name.
254 // FIXME: We unconditionally use the ANSI function because
255 // _Jv_ThisExecutable returns a const char*. We should really
256 // change _Jv_ThisExecutable to return a jstring.
257 GetModuleFileNameA(NULL
, exec_name
, sizeof(exec_name
));
260 // gettimeofday implementation.
262 _Jv_platform_gettimeofday ()
266 return t
.time
* 1000LL + t
.millitm
;
269 // The following definitions "fake out" mingw to think that -mthreads
270 // was enabled and that mingwthr.dll was linked. GCJ-compiled
271 // applications don't need this helper library because we can safely
272 // detect thread death (return from Thread.run()).
277 __mingwthr_key_dtor (DWORD
, void (*) (void *))
279 // FIXME: for now we do nothing; this causes a memory leak of
280 // approximately 24 bytes per thread created.
284 static bool dirExists (LPCTSTR dir
)
286 DWORD dwAttrs
= ::GetFileAttributes (dir
);
287 return dwAttrs
!= 0xFFFFFFFF &&
288 (dwAttrs
& FILE_ATTRIBUTE_DIRECTORY
) != 0;
291 static void getUserHome(LPTSTR userHome
, LPCTSTR userId
)
293 LPTSTR uh
= _tgetenv (_T("USERPROFILE"));
296 _tcscpy(userHome
, uh
);
300 // Make a half-hearted attempt to support this
301 // legacy version of Windows. Try %WINDIR%\Profiles\%USERNAME%
302 // and failing this, use %WINDIR%.
304 // See:http://java.sun.com/docs/books/tutorial/security1.2/summary/files.html#UserPolicy
306 // To do this correctly, we'd have to factor in the
307 // Windows version, but if we did that, then this attempt
308 // wouldn't be half-hearted.
309 TCHAR userHomePath
[MAX_PATH
], winHome
[MAX_PATH
];
310 ::GetWindowsDirectory(winHome
, MAX_PATH
);
311 // assume this call always succeeds
313 _stprintf(userHomePath
, _T("%s\\Profiles\\%s"), winHome
, userId
);
314 if (dirExists (userHomePath
))
315 _tcscpy(userHome
, userHomePath
);
317 _tcscpy(userHome
, winHome
);
321 // Set platform-specific System properties.
323 _Jv_platform_initProperties (java::util::Properties
* newprops
)
325 // A convenience define.
326 #define SET(Prop,Val) \
327 newprops->put(JvNewStringLatin1 (Prop), _Jv_Win32NewString (Val))
329 SET ("file.separator", _T("\\"));
330 SET ("path.separator", _T(";"));
331 SET ("line.separator", _T("\r\n"));
333 // Use GetCurrentDirectory to set 'user.dir'.
334 DWORD buflen
= MAX_PATH
;
335 TCHAR buffer
[buflen
];
338 if (GetCurrentDirectory (buflen
, buffer
))
339 SET ("user.dir", buffer
);
341 if (GetTempPath (buflen
, buffer
))
342 SET ("java.io.tmpdir", buffer
);
345 // Use GetUserName to set 'user.name'.
346 buflen
= 257; // UNLEN + 1
347 TCHAR userName
[buflen
];
348 if (GetUserName (userName
, &buflen
))
349 SET ("user.name", userName
);
352 TCHAR userHome
[MAX_PATH
];
353 getUserHome(userHome
, userName
);
354 SET ("user.home", userHome
);
356 // Get and set some OS info.
358 ZeroMemory (&osvi
, sizeof(OSVERSIONINFO
));
359 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
360 if (GetVersionEx (&osvi
))
364 _stprintf (buffer
, _T("%d.%d"), (int) osvi
.dwMajorVersion
,
365 (int) osvi
.dwMinorVersion
);
366 SET ("os.version", buffer
);
369 switch (osvi
.dwPlatformId
)
371 case VER_PLATFORM_WIN32_WINDOWS
:
372 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 0)
373 SET ("os.name", _T("Windows 95"));
374 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 10)
375 SET ("os.name", _T("Windows 98"));
376 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 90)
377 SET ("os.name", _T("Windows Me"));
379 SET ("os.name", _T("Windows ??"));
382 case VER_PLATFORM_WIN32_NT
:
383 if (osvi
.dwMajorVersion
<= 4 )
384 SET ("os.name", _T("Windows NT"));
385 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
386 SET ("os.name", _T("Windows 2000"));
387 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
388 SET ("os.name", _T("Windows XP"));
390 SET ("os.name", _T("Windows NT ??"));
394 SET ("os.name", _T("Windows UNKNOWN"));
399 // Set the OS architecture.
402 switch (si
.wProcessorArchitecture
)
404 case PROCESSOR_ARCHITECTURE_INTEL
:
405 SET ("os.arch", _T("x86"));
407 case PROCESSOR_ARCHITECTURE_MIPS
:
408 SET ("os.arch", _T("mips"));
410 case PROCESSOR_ARCHITECTURE_ALPHA
:
411 SET ("os.arch", _T("alpha"));
413 case PROCESSOR_ARCHITECTURE_PPC
:
414 SET ("os.arch", _T("ppc"));
416 case PROCESSOR_ARCHITECTURE_IA64
:
417 SET ("os.arch", _T("ia64"));
419 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
421 SET ("os.arch", _T("unknown"));
426 /* Store up to SIZE return address of the current program state in
427 ARRAY and return the exact number of values stored. */
429 backtrace (void **__array
, int __size
)
431 register void *_ebp
__asm__ ("ebp");
432 register void *_esp
__asm__ ("esp");
436 for (rfp
= *(unsigned int**)_ebp
;
438 rfp
= *(unsigned int **)rfp
)
440 int diff
= *rfp
- (unsigned int)rfp
;
441 if ((void*)rfp
< _esp
|| diff
> 4 * 1024 || diff
< 0) break;
443 __array
[i
++] = (void*)(rfp
[1]-4);
449 _Jv_select (int n
, fd_set
*readfds
, fd_set
*writefds
,
450 fd_set
*exceptfds
, struct timeval
*timeout
)
452 int r
= ::select (n
, readfds
, writefds
, exceptfds
, timeout
);
453 if (r
== SOCKET_ERROR
)
455 DWORD dwErrorCode
= WSAGetLastError ();
456 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode
));
462 _Jv_pipe (int filedes
[2])
464 return _pipe (filedes
, 4096, _O_BINARY
);
468 _Jv_platform_close_on_exec (HANDLE h
)
470 // Mark the handle as non-inheritable. This has
471 // no effect under Win9X.
472 SetHandleInformation (h
, HANDLE_FLAG_INHERIT
, 0);