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 // class WSAEventWrapper
46 WSAEventWrapper::WSAEventWrapper (int fd
, DWORD dwSelFlags
):
49 m_dwSelFlags(dwSelFlags
)
51 m_hEvent
= WSACreateEvent ();
53 WSAEventSelect(fd
, m_hEvent
, dwSelFlags
);
56 WSAEventWrapper::~WSAEventWrapper ()
60 WSAEventSelect(m_fd
, m_hEvent
, 0);
61 if (m_dwSelFlags
& (FD_ACCEPT
| FD_CONNECT
))
63 // Set the socket back to non-blocking mode.
64 // Ignore any error since we're in a destructor.
65 unsigned long lSockOpt
= 0L;
67 ::ioctlsocket (m_fd
, FIONBIO
, &lSockOpt
);
70 WSACloseEvent (m_hEvent
);
75 _Jv_WinStrError (LPCTSTR lpszPrologue
, int nErrorCode
)
79 DWORD dwFlags
= FORMAT_MESSAGE_ALLOCATE_BUFFER
|
80 FORMAT_MESSAGE_FROM_SYSTEM
|
81 FORMAT_MESSAGE_IGNORE_INSERTS
;
83 FormatMessage (dwFlags
,
86 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
95 (LPTSTR
) _Jv_Malloc (strlen (lpszPrologue
) +
96 strlen (lpMsgBuf
) + 3);
97 strcpy (lpszTemp
, lpszPrologue
);
98 strcat (lpszTemp
, ": ");
99 strcat (lpszTemp
, lpMsgBuf
);
100 ret
= JvNewStringLatin1 (lpszTemp
);
104 ret
= JvNewStringLatin1 (lpMsgBuf
);
112 _Jv_WinStrError (int nErrorCode
)
114 return _Jv_WinStrError (0, nErrorCode
);
117 void _Jv_ThrowIOException (DWORD dwErrorCode
)
119 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode
));
122 void _Jv_ThrowIOException()
124 DWORD dwErrorCode
= WSAGetLastError ();
125 _Jv_ThrowIOException (dwErrorCode
);
128 void _Jv_ThrowSocketException (DWORD dwErrorCode
)
130 throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode
));
133 void _Jv_ThrowSocketException()
135 DWORD dwErrorCode
= WSAGetLastError ();
136 _Jv_ThrowSocketException (dwErrorCode
);
139 // Platform-specific VM initialization.
141 _Jv_platform_initialize (void)
143 // Initialise winsock for networking
145 if (WSAStartup (MAKEWORD (1, 1), &data
))
146 MessageBox (NULL
, "Error initialising winsock library.", "Error",
147 MB_OK
| MB_ICONEXCLAMATION
);
149 // Install exception handler
150 SetUnhandledExceptionFilter (win32_exception_handler
);
152 // Initialize our executable name
153 GetModuleFileName(NULL
, exec_name
, sizeof(exec_name
));
156 // gettimeofday implementation.
158 _Jv_platform_gettimeofday ()
162 return t
.time
* 1000LL + t
.millitm
;
165 // The following definitions "fake out" mingw to think that -mthreads
166 // was enabled and that mingwthr.dll was linked. GCJ-compiled
167 // applications don't need this helper library because we can safely
168 // detect thread death (return from Thread.run()).
173 __mingwthr_key_dtor (DWORD
, void (*) (void *))
175 // FIXME: for now we do nothing; this causes a memory leak of
176 // approximately 24 bytes per thread created.
180 static bool dirExists (const char* dir
)
182 DWORD dwAttrs
= ::GetFileAttributes (dir
);
183 return dwAttrs
!= 0xFFFFFFFF &&
184 (dwAttrs
& FILE_ATTRIBUTE_DIRECTORY
) != 0;
187 static void getUserHome(char* userHome
, const char* userId
)
189 char* uh
= ::getenv ("USERPROFILE");
192 strcpy(userHome
, uh
);
196 // Make a half-hearted attempt to support this
197 // legacy version of Windows. Try %WINDIR%\Profiles\%USERNAME%
198 // and failing this, use %WINDIR%.
200 // See:http://java.sun.com/docs/books/tutorial/security1.2/summary/files.html#UserPolicy
202 // To do this correctly, we'd have to factor in the
203 // Windows version, but if we did that, then this attempt
204 // wouldn't be half-hearted.
205 char userHomePath
[MAX_PATH
], winHome
[MAX_PATH
];
206 ::GetWindowsDirectory(winHome
, MAX_PATH
);
207 // assume this call always succeeds
209 sprintf(userHomePath
, "%s\\Profiles\\%s", winHome
, userId
);
210 if (dirExists (userHomePath
))
211 strcpy(userHome
, userHomePath
);
213 strcpy(userHome
, winHome
);
217 // Set platform-specific System properties.
219 _Jv_platform_initProperties (java::util::Properties
* newprops
)
221 // A convenience define.
222 #define SET(Prop,Val) \
223 newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
225 SET ("file.separator", "\\");
226 SET ("path.separator", ";");
227 SET ("line.separator", "\r\n");
229 // Use GetCurrentDirectory to set 'user.dir'.
230 DWORD buflen
= MAX_PATH
;
231 char *buffer
= (char *) _Jv_MallocUnchecked (buflen
);
234 if (GetCurrentDirectory (buflen
, buffer
))
235 SET ("user.dir", buffer
);
237 if (GetTempPath (buflen
, buffer
))
238 SET ("java.io.tmpdir", buffer
);
243 // Use GetUserName to set 'user.name'.
244 buflen
= 257; // UNLEN + 1
245 char userName
[buflen
];
246 if (GetUserName (userName
, &buflen
))
247 SET ("user.name", userName
);
250 char userHome
[MAX_PATH
];
251 getUserHome(userHome
, userName
);
252 SET ("user.home", userHome
);
254 // Get and set some OS info.
256 ZeroMemory (&osvi
, sizeof(OSVERSIONINFO
));
257 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
258 if (GetVersionEx (&osvi
))
260 char *buffer
= (char *) _Jv_MallocUnchecked (30);
263 sprintf (buffer
, "%d.%d", (int) osvi
.dwMajorVersion
,
264 (int) osvi
.dwMinorVersion
);
265 SET ("os.version", buffer
);
269 switch (osvi
.dwPlatformId
)
271 case VER_PLATFORM_WIN32_WINDOWS
:
272 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 0)
273 SET ("os.name", "Windows 95");
274 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 10)
275 SET ("os.name", "Windows 98");
276 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 90)
277 SET ("os.name", "Windows Me");
279 SET ("os.name", "Windows ??");
282 case VER_PLATFORM_WIN32_NT
:
283 if (osvi
.dwMajorVersion
<= 4 )
284 SET ("os.name", "Windows NT");
285 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
286 SET ("os.name", "Windows 2000");
287 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
288 SET ("os.name", "Windows XP");
290 SET ("os.name", "Windows NT ??");
294 SET ("os.name", "Windows UNKNOWN");
299 // Set the OS architecture.
302 switch (si
.wProcessorArchitecture
)
304 case PROCESSOR_ARCHITECTURE_INTEL
:
305 SET ("os.arch", "x86");
307 case PROCESSOR_ARCHITECTURE_MIPS
:
308 SET ("os.arch", "mips");
310 case PROCESSOR_ARCHITECTURE_ALPHA
:
311 SET ("os.arch", "alpha");
313 case PROCESSOR_ARCHITECTURE_PPC
:
314 SET ("os.arch", "ppc");
316 case PROCESSOR_ARCHITECTURE_IA64
:
317 SET ("os.arch", "ia64");
319 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
321 SET ("os.arch", "unknown");
326 /* Store up to SIZE return address of the current program state in
327 ARRAY and return the exact number of values stored. */
329 backtrace (void **__array
, int __size
)
331 register void *_ebp
__asm__ ("ebp");
332 register void *_esp
__asm__ ("esp");
336 for (rfp
= *(unsigned int**)_ebp
;
338 rfp
= *(unsigned int **)rfp
)
340 int diff
= *rfp
- (unsigned int)rfp
;
341 if ((void*)rfp
< _esp
|| diff
> 4 * 1024 || diff
< 0) break;
343 __array
[i
++] = (void*)(rfp
[1]-4);
349 _Jv_select (int n
, fd_set
*readfds
, fd_set
*writefds
,
350 fd_set
*exceptfds
, struct timeval
*timeout
)
352 int r
= ::select (n
, readfds
, writefds
, exceptfds
, timeout
);
353 if (r
== SOCKET_ERROR
)
355 DWORD dwErrorCode
= WSAGetLastError ();
356 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode
));
362 _Jv_pipe (int filedes
[2])
364 return _pipe (filedes
, 4096, _O_BINARY
);