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
13 #include <sys/timeb.h>
18 #include <java-stack.h>
20 #include <java/lang/ArithmeticException.h>
21 #include <java/lang/UnsupportedOperationException.h>
22 #include <java/io/IOException.h>
23 #include <java/net/SocketException.h>
24 #include <java/util/Properties.h>
27 win32_exception_handler (LPEXCEPTION_POINTERS e
)
29 if (e
->ExceptionRecord
->ExceptionCode
== EXCEPTION_ACCESS_VIOLATION
)
30 _Jv_ThrowNullPointerException();
31 else if (e
->ExceptionRecord
->ExceptionCode
== EXCEPTION_INT_DIVIDE_BY_ZERO
)
32 throw new java::lang::ArithmeticException
;
34 return EXCEPTION_CONTINUE_SEARCH
;
37 // Platform-specific executable name
38 static char exec_name
[MAX_PATH
];
39 // initialized in _Jv_platform_initialize()
41 const char *_Jv_ThisExecutable (void)
46 // Helper classes and methods implementation
48 #ifdef MINGW_LIBGCJ_UNICODE
50 // We're using the OS W (UNICODE) API, which means that we're speaking
51 // the same language....
53 _Jv_Win32NewString (LPCTSTR pcsz
)
55 return JvNewString ((jchar
*) pcsz
, _tcslen (pcsz
));
60 // We're using the OS A functions, which means we need to translate between
61 // UNICODE and the native character set.
63 // First, let's set up some helper translation functions....
65 // Converts the native string to any specified jstring, returning the
66 // length of the jstring. If the specified jstring is null, we simply
67 // compute and return the length.
68 static int nativeToUnicode(LPCSTR pcsz
, jstring jstr
= 0)
75 buf
= JvGetStringChars(jstr
);
77 return ::MultiByteToWideChar(GetACP(), 0, pcsz
,
78 strlen(pcsz
), (LPWSTR
) buf
, len
);
81 // Does the inverse of nativeToUnicode, with the same calling semantics.
82 static int unicodeToNative(jstring jstr
, LPSTR buf
, int buflen
)
84 return ::WideCharToMultiByte(GetACP(), 0, (LPWSTR
) JvGetStringChars(jstr
),
85 jstr
->length(), buf
, buflen
, NULL
, NULL
);
88 // Convenience function when the caller only wants to compute the length
89 // of the native string.
90 static int unicodeToNative(jstring jstr
)
92 return unicodeToNative(jstr
, 0, 0);
96 _Jv_Win32NewString (LPCTSTR pcsz
)
98 // Compute the length, allocate the jstring, then perform the conversion.
99 int len
= nativeToUnicode(pcsz
);
100 jstring jstr
= JvAllocString(len
);
101 nativeToUnicode(pcsz
, jstr
);
105 #endif // MINGW_LIBGCJ_UNICODE
107 // class _Jv_Win32TempString
108 _Jv_Win32TempString::_Jv_Win32TempString(jstring jstr
):
114 // We need space for the string length plus a null terminator.
115 // Determine whether to use our stack-allocated buffer or a heap-
117 #ifdef MINGW_LIBGCJ_UNICODE
118 // A UNICODE character is a UNICODE character is a UNICODE character....
119 int len
= jstr
->length();
121 // Compute the length of the native character string.
122 int len
= unicodeToNative(jstr
);
123 #endif // MINGW_LIBGCJ_UNICODE
125 int bytesNeeded
= (len
+ 1) * sizeof(TCHAR
);
126 if (bytesNeeded
<= (int) sizeof(stackbuf_
))
129 buf_
= (LPTSTR
) _Jv_Malloc(bytesNeeded
);
131 #ifdef MINGW_LIBGCJ_UNICODE
132 // Copy the UNICODE characters to our buffer.
133 _tcsncpy(buf_
, (LPCTSTR
) JvGetStringChars (jstr
), len
);
135 // Convert the UNICODE string to a native one.
136 unicodeToNative(jstr
, buf_
, len
);
137 #endif // MINGW_LIBGCJ_UNICODE
142 _Jv_Win32TempString::~_Jv_Win32TempString()
144 if (buf_
&& buf_
!= stackbuf_
)
148 // class WSAEventWrapper
149 WSAEventWrapper::WSAEventWrapper ():
155 WSAEventWrapper::WSAEventWrapper (int fd
, DWORD dwSelFlags
):
160 init(fd
, dwSelFlags
);
163 void WSAEventWrapper::init(int fd
, DWORD dwSelFlags
)
166 m_dwSelFlags
= dwSelFlags
;
167 m_hEvent
= WSACreateEvent ();
169 WSAEventSelect(fd
, m_hEvent
, dwSelFlags
);
172 WSAEventWrapper::~WSAEventWrapper ()
176 WSAEventSelect(m_fd
, m_hEvent
, 0);
177 if (m_dwSelFlags
& (FD_ACCEPT
| FD_CONNECT
))
179 // Set the socket back to non-blocking mode.
180 // Ignore any error since we're in a destructor.
181 unsigned long lSockOpt
= 0L;
183 ::ioctlsocket (m_fd
, FIONBIO
, &lSockOpt
);
186 WSACloseEvent (m_hEvent
);
189 // Error string text.
191 _Jv_WinStrError (LPCTSTR lpszPrologue
, int nErrorCode
)
195 DWORD dwFlags
= FORMAT_MESSAGE_ALLOCATE_BUFFER
|
196 FORMAT_MESSAGE_FROM_SYSTEM
|
197 FORMAT_MESSAGE_IGNORE_INSERTS
;
199 FormatMessage (dwFlags
,
202 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
211 (LPTSTR
) _Jv_Malloc ((_tcslen (lpszPrologue
) +
212 _tcslen (lpMsgBuf
) + 3) * sizeof(TCHAR
) );
213 _tcscpy (lpszTemp
, lpszPrologue
);
214 _tcscat (lpszTemp
, _T(": "));
215 _tcscat (lpszTemp
, lpMsgBuf
);
216 ret
= _Jv_Win32NewString (lpszTemp
);
221 ret
= _Jv_Win32NewString (lpMsgBuf
);
229 _Jv_WinStrError (int nErrorCode
)
231 return _Jv_WinStrError (0, nErrorCode
);
234 void _Jv_ThrowIOException (DWORD dwErrorCode
)
236 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode
));
239 void _Jv_ThrowIOException()
241 DWORD dwErrorCode
= WSAGetLastError ();
242 _Jv_ThrowIOException (dwErrorCode
);
245 void _Jv_ThrowSocketException (DWORD dwErrorCode
)
247 throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode
));
250 void _Jv_ThrowSocketException()
252 DWORD dwErrorCode
= WSAGetLastError ();
253 _Jv_ThrowSocketException (dwErrorCode
);
256 // Platform-specific VM initialization.
258 _Jv_platform_initialize (void)
260 // Initialise winsock for networking
262 if (WSAStartup (MAKEWORD (2, 2), &data
))
263 MessageBox (NULL
, _T("Error initialising winsock library."), _T("Error"),
264 MB_OK
| MB_ICONEXCLAMATION
);
266 // Install exception handler
267 SetUnhandledExceptionFilter (win32_exception_handler
);
269 // Initialize our executable name.
270 // FIXME: We unconditionally use the ANSI function because
271 // _Jv_ThisExecutable returns a const char*. We should really
272 // change _Jv_ThisExecutable to return a jstring.
273 GetModuleFileNameA(NULL
, exec_name
, sizeof(exec_name
));
276 // gettimeofday implementation.
278 _Jv_platform_gettimeofday ()
282 return t
.time
* 1000LL + t
.millitm
;
286 _Jv_platform_nanotime ()
288 return _Jv_platform_gettimeofday () * 1000LL;
291 static bool dirExists (LPCTSTR dir
)
293 DWORD dwAttrs
= ::GetFileAttributes (dir
);
294 return dwAttrs
!= 0xFFFFFFFF &&
295 (dwAttrs
& FILE_ATTRIBUTE_DIRECTORY
) != 0;
298 static void getUserHome(LPTSTR userHome
, LPCTSTR userId
)
300 LPTSTR uh
= _tgetenv (_T("USERPROFILE"));
303 _tcscpy(userHome
, uh
);
307 // Make a half-hearted attempt to support this
308 // legacy version of Windows. Try %WINDIR%\Profiles\%USERNAME%
309 // and failing this, use %WINDIR%.
311 // See:http://java.sun.com/docs/books/tutorial/security1.2/summary/files.html#UserPolicy
313 // To do this correctly, we'd have to factor in the
314 // Windows version, but if we did that, then this attempt
315 // wouldn't be half-hearted.
316 TCHAR userHomePath
[MAX_PATH
], winHome
[MAX_PATH
];
317 ::GetWindowsDirectory(winHome
, MAX_PATH
);
318 // assume this call always succeeds
320 _stprintf(userHomePath
, _T("%s\\Profiles\\%s"), winHome
, userId
);
321 if (dirExists (userHomePath
))
322 _tcscpy(userHome
, userHomePath
);
324 _tcscpy(userHome
, winHome
);
328 // Set platform-specific System properties.
330 _Jv_platform_initProperties (java::util::Properties
* newprops
)
332 // A convenience define.
333 #define SET(Prop,Val) \
334 newprops->put(JvNewStringLatin1 (Prop), _Jv_Win32NewString (Val))
336 SET ("file.separator", _T("\\"));
337 SET ("path.separator", _T(";"));
338 SET ("line.separator", _T("\r\n"));
340 // Use GetCurrentDirectory to set 'user.dir'.
341 DWORD buflen
= MAX_PATH
;
342 TCHAR buffer
[buflen
];
345 if (GetCurrentDirectory (buflen
, buffer
))
346 SET ("user.dir", buffer
);
348 if (GetTempPath (buflen
, buffer
))
349 SET ("java.io.tmpdir", buffer
);
352 // Use GetUserName to set 'user.name'.
353 buflen
= 257; // UNLEN + 1
354 TCHAR userName
[buflen
];
355 if (GetUserName (userName
, &buflen
))
356 SET ("user.name", userName
);
359 TCHAR userHome
[MAX_PATH
];
360 getUserHome(userHome
, userName
);
361 SET ("user.home", userHome
);
363 // Get and set some OS info.
365 ZeroMemory (&osvi
, sizeof(OSVERSIONINFO
));
366 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
367 if (GetVersionEx (&osvi
))
371 _stprintf (buffer
, _T("%d.%d"), (int) osvi
.dwMajorVersion
,
372 (int) osvi
.dwMinorVersion
);
373 SET ("os.version", buffer
);
376 switch (osvi
.dwPlatformId
)
378 case VER_PLATFORM_WIN32_WINDOWS
:
379 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 0)
380 SET ("os.name", _T("Windows 95"));
381 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 10)
382 SET ("os.name", _T("Windows 98"));
383 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 90)
384 SET ("os.name", _T("Windows Me"));
386 SET ("os.name", _T("Windows ??"));
389 case VER_PLATFORM_WIN32_NT
:
390 if (osvi
.dwMajorVersion
<= 4 )
391 SET ("os.name", _T("Windows NT"));
392 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
393 SET ("os.name", _T("Windows 2000"));
394 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
395 SET ("os.name", _T("Windows XP"));
397 SET ("os.name", _T("Windows NT ??"));
401 SET ("os.name", _T("Windows UNKNOWN"));
406 // Set the OS architecture.
409 switch (si
.wProcessorArchitecture
)
411 case PROCESSOR_ARCHITECTURE_INTEL
:
412 SET ("os.arch", _T("x86"));
414 case PROCESSOR_ARCHITECTURE_MIPS
:
415 SET ("os.arch", _T("mips"));
417 case PROCESSOR_ARCHITECTURE_ALPHA
:
418 SET ("os.arch", _T("alpha"));
420 case PROCESSOR_ARCHITECTURE_PPC
:
421 SET ("os.arch", _T("ppc"));
423 case PROCESSOR_ARCHITECTURE_IA64
:
424 SET ("os.arch", _T("ia64"));
426 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
428 SET ("os.arch", _T("unknown"));
434 _Jv_pipe (int filedes
[2])
436 return _pipe (filedes
, 4096, _O_BINARY
);
440 _Jv_platform_close_on_exec (HANDLE h
)
442 // Mark the handle as non-inheritable. This has
443 // no effect under Win9X.
444 SetHandleInformation (h
, HANDLE_FLAG_INHERIT
, 0);
447 // Given an address, find the object that defines it and the nearest
448 // defined symbol to that address. Returns 0 if no object defines this
451 _Jv_platform_dladdr (void *addr
, _Jv_AddrInfo
*info
)
453 // Since we do not have dladdr() on Windows, we use a trick involving
454 // VirtualQuery() to find the module (EXE or DLL) that contains a given
455 // address. This was taken from Matt Pietrek's "Under the Hood" column
456 // for the April 1997 issue of Microsoft Systems Journal.
458 MEMORY_BASIC_INFORMATION mbi
;
459 if (!VirtualQuery (addr
, &mbi
, sizeof (mbi
)))
464 HMODULE hMod
= (HMODULE
) mbi
.AllocationBase
;
466 char moduleName
[MAX_PATH
];
468 // FIXME: We explicitly use the ANSI variant of the function here.
469 if (!GetModuleFileNameA (hMod
, moduleName
, sizeof (moduleName
)))
474 char *file_name
= (char *)(malloc (strlen (moduleName
) + 1));
475 strcpy (file_name
, moduleName
);
476 info
->file_name
= file_name
;
480 info
->sym_name
= NULL
;
481 info
->sym_addr
= NULL
;