Update my e-mail address for a new "corporate standard".
[official-gcc.git] / libjava / win32.cc
bloba0ae0f0f9cb52c1c7097f5d863fe26c5e36a22ac
1 // win32.cc - Helper functions for Microsoft-flavored OSs.
3 /* Copyright (C) 2002, 2003, 2006 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
9 details. */
11 #include <config.h>
12 #include <platform.h>
13 #include <sys/timeb.h>
14 #include <stdlib.h>
15 #include <fcntl.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>
23 static LONG CALLBACK
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;
30 else
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)
40 return exec_name;
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....
49 jstring
50 _Jv_Win32NewString (LPCTSTR pcsz)
52 return JvNewString ((jchar*) pcsz, _tcslen (pcsz));
55 #else
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)
67 jchar* buf = 0;
68 int len = 0;
69 if (jstr)
71 len = jstr->length();
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);
92 jstring
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);
99 return jstr;
102 #endif // MINGW_LIBGCJ_UNICODE
104 // class _Jv_Win32TempString
105 _Jv_Win32TempString::_Jv_Win32TempString(jstring jstr):
106 buf_(0)
108 if (jstr == 0)
109 return;
111 // We need space for the string length plus a null terminator.
112 // Determine whether to use our stack-allocated buffer or a heap-
113 // allocated one.
114 #ifdef MINGW_LIBGCJ_UNICODE
115 // A UNICODE character is a UNICODE character is a UNICODE character....
116 int len = jstr->length();
117 #else
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_))
124 buf_ = stackbuf_;
125 else
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);
131 #else
132 // Convert the UNICODE string to a native one.
133 unicodeToNative(jstr, buf_, len);
134 #endif // MINGW_LIBGCJ_UNICODE
136 buf_[len] = 0;
139 _Jv_Win32TempString::~_Jv_Win32TempString()
141 if (buf_ && buf_ != stackbuf_)
142 _Jv_Free (buf_);
145 // class WSAEventWrapper
146 WSAEventWrapper::WSAEventWrapper ():
147 m_hEvent(0),
148 m_fd(0),
149 m_dwSelFlags(0)
152 WSAEventWrapper::WSAEventWrapper (int fd, DWORD dwSelFlags):
153 m_hEvent(0),
154 m_fd(0),
155 m_dwSelFlags(0)
157 init(fd, dwSelFlags);
160 void WSAEventWrapper::init(int fd, DWORD dwSelFlags)
162 m_fd = fd;
163 m_dwSelFlags = dwSelFlags;
164 m_hEvent = WSACreateEvent ();
165 if (dwSelFlags)
166 WSAEventSelect(fd, m_hEvent, dwSelFlags);
169 WSAEventWrapper::~WSAEventWrapper ()
171 if (m_dwSelFlags)
173 WSAEventSelect(m_fd, m_hEvent, 0);
174 if (m_dwSelFlags & (FD_ACCEPT | FD_CONNECT))
176 // Set the socket back to non-blocking mode.
177 // Ignore any error since we're in a destructor.
178 unsigned long lSockOpt = 0L;
179 // blocking mode
180 ::ioctlsocket (m_fd, FIONBIO, &lSockOpt);
183 WSACloseEvent (m_hEvent);
186 // Error string text.
187 jstring
188 _Jv_WinStrError (LPCTSTR lpszPrologue, int nErrorCode)
190 LPTSTR lpMsgBuf = 0;
192 DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
193 FORMAT_MESSAGE_FROM_SYSTEM |
194 FORMAT_MESSAGE_IGNORE_INSERTS;
196 FormatMessage (dwFlags,
197 NULL,
198 (DWORD) nErrorCode,
199 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
200 (LPTSTR) &lpMsgBuf,
202 NULL);
204 jstring ret;
205 if (lpszPrologue)
207 LPTSTR lpszTemp =
208 (LPTSTR) _Jv_Malloc ((_tcslen (lpszPrologue) +
209 _tcslen (lpMsgBuf) + 3) * sizeof(TCHAR) );
210 _tcscpy (lpszTemp, lpszPrologue);
211 _tcscat (lpszTemp, _T(": "));
212 _tcscat (lpszTemp, lpMsgBuf);
213 ret = _Jv_Win32NewString (lpszTemp);
214 _Jv_Free (lpszTemp);
216 else
218 ret = _Jv_Win32NewString (lpMsgBuf);
221 LocalFree(lpMsgBuf);
222 return ret;
225 jstring
226 _Jv_WinStrError (int nErrorCode)
228 return _Jv_WinStrError (0, nErrorCode);
231 void _Jv_ThrowIOException (DWORD dwErrorCode)
233 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode));
236 void _Jv_ThrowIOException()
238 DWORD dwErrorCode = WSAGetLastError ();
239 _Jv_ThrowIOException (dwErrorCode);
242 void _Jv_ThrowSocketException (DWORD dwErrorCode)
244 throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode));
247 void _Jv_ThrowSocketException()
249 DWORD dwErrorCode = WSAGetLastError ();
250 _Jv_ThrowSocketException (dwErrorCode);
253 // Platform-specific VM initialization.
254 void
255 _Jv_platform_initialize (void)
257 // Initialise winsock for networking
258 WSADATA data;
259 if (WSAStartup (MAKEWORD (2, 2), &data))
260 MessageBox (NULL, _T("Error initialising winsock library."), _T("Error"),
261 MB_OK | MB_ICONEXCLAMATION);
263 // Install exception handler
264 SetUnhandledExceptionFilter (win32_exception_handler);
266 // Initialize our executable name.
267 // FIXME: We unconditionally use the ANSI function because
268 // _Jv_ThisExecutable returns a const char*. We should really
269 // change _Jv_ThisExecutable to return a jstring.
270 GetModuleFileNameA(NULL, exec_name, sizeof(exec_name));
273 // gettimeofday implementation.
274 jlong
275 _Jv_platform_gettimeofday ()
277 struct timeb t;
278 ftime (&t);
279 return t.time * 1000LL + t.millitm;
282 jlong
283 _Jv_platform_nanotime ()
285 return _Jv_platform_gettimeofday () * 1000LL;
288 // The following definitions "fake out" mingw to think that -mthreads
289 // was enabled and that mingwthr.dll was linked. GCJ-compiled
290 // applications don't need this helper library because we can safely
291 // detect thread death (return from Thread.run()).
293 int _CRT_MT = 1;
295 extern "C" int
296 __mingwthr_key_dtor (DWORD, void (*) (void *))
298 // FIXME: for now we do nothing; this causes a memory leak of
299 // approximately 24 bytes per thread created.
300 return 0;
303 static bool dirExists (LPCTSTR dir)
305 DWORD dwAttrs = ::GetFileAttributes (dir);
306 return dwAttrs != 0xFFFFFFFF &&
307 (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
310 static void getUserHome(LPTSTR userHome, LPCTSTR userId)
312 LPTSTR uh = _tgetenv (_T("USERPROFILE"));
313 if (uh)
315 _tcscpy(userHome, uh);
317 else
319 // Make a half-hearted attempt to support this
320 // legacy version of Windows. Try %WINDIR%\Profiles\%USERNAME%
321 // and failing this, use %WINDIR%.
323 // See:http://java.sun.com/docs/books/tutorial/security1.2/summary/files.html#UserPolicy
325 // To do this correctly, we'd have to factor in the
326 // Windows version, but if we did that, then this attempt
327 // wouldn't be half-hearted.
328 TCHAR userHomePath[MAX_PATH], winHome[MAX_PATH];
329 ::GetWindowsDirectory(winHome, MAX_PATH);
330 // assume this call always succeeds
332 _stprintf(userHomePath, _T("%s\\Profiles\\%s"), winHome, userId);
333 if (dirExists (userHomePath))
334 _tcscpy(userHome, userHomePath);
335 else
336 _tcscpy(userHome, winHome);
340 // Set platform-specific System properties.
341 void
342 _Jv_platform_initProperties (java::util::Properties* newprops)
344 // A convenience define.
345 #define SET(Prop,Val) \
346 newprops->put(JvNewStringLatin1 (Prop), _Jv_Win32NewString (Val))
348 SET ("file.separator", _T("\\"));
349 SET ("path.separator", _T(";"));
350 SET ("line.separator", _T("\r\n"));
352 // Use GetCurrentDirectory to set 'user.dir'.
353 DWORD buflen = MAX_PATH;
354 TCHAR buffer[buflen];
355 if (buffer != NULL)
357 if (GetCurrentDirectory (buflen, buffer))
358 SET ("user.dir", buffer);
360 if (GetTempPath (buflen, buffer))
361 SET ("java.io.tmpdir", buffer);
364 // Use GetUserName to set 'user.name'.
365 buflen = 257; // UNLEN + 1
366 TCHAR userName[buflen];
367 if (GetUserName (userName, &buflen))
368 SET ("user.name", userName);
370 // Set user.home
371 TCHAR userHome[MAX_PATH];
372 getUserHome(userHome, userName);
373 SET ("user.home", userHome);
375 // Get and set some OS info.
376 OSVERSIONINFO osvi;
377 ZeroMemory (&osvi, sizeof(OSVERSIONINFO));
378 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
379 if (GetVersionEx (&osvi))
381 if (buffer != NULL)
383 _stprintf (buffer, _T("%d.%d"), (int) osvi.dwMajorVersion,
384 (int) osvi.dwMinorVersion);
385 SET ("os.version", buffer);
388 switch (osvi.dwPlatformId)
390 case VER_PLATFORM_WIN32_WINDOWS:
391 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
392 SET ("os.name", _T("Windows 95"));
393 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
394 SET ("os.name", _T("Windows 98"));
395 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
396 SET ("os.name", _T("Windows Me"));
397 else
398 SET ("os.name", _T("Windows ??"));
399 break;
401 case VER_PLATFORM_WIN32_NT:
402 if (osvi.dwMajorVersion <= 4 )
403 SET ("os.name", _T("Windows NT"));
404 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
405 SET ("os.name", _T("Windows 2000"));
406 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
407 SET ("os.name", _T("Windows XP"));
408 else
409 SET ("os.name", _T("Windows NT ??"));
410 break;
412 default:
413 SET ("os.name", _T("Windows UNKNOWN"));
414 break;
418 // Set the OS architecture.
419 SYSTEM_INFO si;
420 GetSystemInfo (&si);
421 switch (si.wProcessorArchitecture)
423 case PROCESSOR_ARCHITECTURE_INTEL:
424 SET ("os.arch", _T("x86"));
425 break;
426 case PROCESSOR_ARCHITECTURE_MIPS:
427 SET ("os.arch", _T("mips"));
428 break;
429 case PROCESSOR_ARCHITECTURE_ALPHA:
430 SET ("os.arch", _T("alpha"));
431 break;
432 case PROCESSOR_ARCHITECTURE_PPC:
433 SET ("os.arch", _T("ppc"));
434 break;
435 case PROCESSOR_ARCHITECTURE_IA64:
436 SET ("os.arch", _T("ia64"));
437 break;
438 case PROCESSOR_ARCHITECTURE_UNKNOWN:
439 default:
440 SET ("os.arch", _T("unknown"));
441 break;
445 /* Store up to SIZE return address of the current program state in
446 ARRAY and return the exact number of values stored. */
448 backtrace (void **__array, int __size)
450 register void *_ebp __asm__ ("ebp");
451 register void *_esp __asm__ ("esp");
452 unsigned int *rfp;
454 int i=0;
455 for (rfp = *(unsigned int**)_ebp;
456 rfp && i < __size;
457 rfp = *(unsigned int **)rfp)
459 int diff = *rfp - (unsigned int)rfp;
460 if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0) break;
462 __array[i++] = (void*)(rfp[1]-4);
464 return i;
468 _Jv_pipe (int filedes[2])
470 return _pipe (filedes, 4096, _O_BINARY);
473 void
474 _Jv_platform_close_on_exec (HANDLE h)
476 // Mark the handle as non-inheritable. This has
477 // no effect under Win9X.
478 SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0);