+jlong
+_Jv_platform_nanotime ()
+{
+ return _Jv_platform_gettimeofday () * 1000LL;
+}
+
+static bool dirExists (LPCTSTR dir)
+{
+ DWORD dwAttrs = ::GetFileAttributes (dir);
+ return dwAttrs != 0xFFFFFFFF &&
+ (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
+}
+
+static void getUserHome(LPTSTR userHome, LPCTSTR userId)
+{
+ LPTSTR uh = _tgetenv (_T("USERPROFILE"));
+ if (uh)
+ {
+ _tcscpy(userHome, uh);
+ }
+ else
+ {
+ // Make a half-hearted attempt to support this
+ // legacy version of Windows. Try %WINDIR%\Profiles\%USERNAME%
+ // and failing this, use %WINDIR%.
+ //
+ // See:http://java.sun.com/docs/books/tutorial/security1.2/summary/files.html#UserPolicy
+ //
+ // To do this correctly, we'd have to factor in the
+ // Windows version, but if we did that, then this attempt
+ // wouldn't be half-hearted.
+ TCHAR userHomePath[MAX_PATH], winHome[MAX_PATH];
+ ::GetWindowsDirectory(winHome, MAX_PATH);
+ // assume this call always succeeds
+
+ _stprintf(userHomePath, _T("%s\\Profiles\\%s"), winHome, userId);
+ if (dirExists (userHomePath))
+ _tcscpy(userHome, userHomePath);
+ else
+ _tcscpy(userHome, winHome);
+ }
+}
+
+// Set platform-specific System properties.
+void
+_Jv_platform_initProperties (java::util::Properties* newprops)
+{
+ // A convenience define.
+#define SET(Prop,Val) \
+ newprops->put(JvNewStringLatin1 (Prop), _Jv_Win32NewString (Val))
+
+ SET ("file.separator", _T("\\"));
+ SET ("path.separator", _T(";"));
+ SET ("line.separator", _T("\r\n"));
+
+ // Use GetCurrentDirectory to set 'user.dir'.
+ DWORD buflen = MAX_PATH;
+ TCHAR buffer[buflen];
+ if (buffer != NULL)
+ {
+ if (GetCurrentDirectory (buflen, buffer))
+ SET ("user.dir", buffer);
+
+ if (GetTempPath (buflen, buffer))
+ SET ("java.io.tmpdir", buffer);
+ }
+
+ // Use GetUserName to set 'user.name'.
+ buflen = 257; // UNLEN + 1
+ TCHAR userName[buflen];
+ if (GetUserName (userName, &buflen))
+ SET ("user.name", userName);
+
+ // Set user.home
+ TCHAR userHome[MAX_PATH];
+ getUserHome(userHome, userName);
+ SET ("user.home", userHome);
+
+ // Get and set some OS info.
+ OSVERSIONINFO osvi;
+ ZeroMemory (&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (GetVersionEx (&osvi))
+ {
+ if (buffer != NULL)
+ {
+ _stprintf (buffer, _T("%d.%d"), (int) osvi.dwMajorVersion,
+ (int) osvi.dwMinorVersion);
+ SET ("os.version", buffer);
+ }
+
+ switch (osvi.dwPlatformId)
+ {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
+ SET ("os.name", _T("Windows 95"));
+ else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
+ SET ("os.name", _T("Windows 98"));
+ else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
+ SET ("os.name", _T("Windows Me"));
+ else
+ SET ("os.name", _T("Windows ??"));
+ break;
+
+ case VER_PLATFORM_WIN32_NT:
+ if (osvi.dwMajorVersion <= 4 )
+ SET ("os.name", _T("Windows NT"));
+ else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
+ SET ("os.name", _T("Windows 2000"));
+ else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
+ SET ("os.name", _T("Windows XP"));
+ else
+ SET ("os.name", _T("Windows NT ??"));
+ break;
+
+ default:
+ SET ("os.name", _T("Windows UNKNOWN"));
+ break;
+ }
+ }
+
+ // Set the OS architecture.
+ SYSTEM_INFO si;
+ GetSystemInfo (&si);
+ switch (si.wProcessorArchitecture)
+ {
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ SET ("os.arch", _T("x86"));
+ break;
+ case PROCESSOR_ARCHITECTURE_MIPS:
+ SET ("os.arch", _T("mips"));
+ break;
+ case PROCESSOR_ARCHITECTURE_ALPHA:
+ SET ("os.arch", _T("alpha"));
+ break;
+ case PROCESSOR_ARCHITECTURE_PPC:
+ SET ("os.arch", _T("ppc"));
+ break;
+ case PROCESSOR_ARCHITECTURE_IA64:
+ SET ("os.arch", _T("ia64"));
+ break;
+ case PROCESSOR_ARCHITECTURE_UNKNOWN:
+ default:
+ SET ("os.arch", _T("unknown"));
+ break;
+ }
+}
+
+int
+_Jv_pipe (int filedes[2])
+{
+ return _pipe (filedes, 4096, _O_BINARY);
+}
+
+void
+_Jv_platform_close_on_exec (HANDLE h)
+{
+ // Mark the handle as non-inheritable. This has
+ // no effect under Win9X.
+ SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0);
+}
+
+// Given an address, find the object that defines it and the nearest
+// defined symbol to that address. Returns 0 if no object defines this
+// address.
+int
+_Jv_platform_dladdr (void *addr, _Jv_AddrInfo *info)
+{
+ // Since we do not have dladdr() on Windows, we use a trick involving
+ // VirtualQuery() to find the module (EXE or DLL) that contains a given
+ // address. This was taken from Matt Pietrek's "Under the Hood" column
+ // for the April 1997 issue of Microsoft Systems Journal.
+
+ MEMORY_BASIC_INFORMATION mbi;
+ if (!VirtualQuery (addr, &mbi, sizeof (mbi)))
+ {
+ return 0;
+ }
+
+ HMODULE hMod = (HMODULE) mbi.AllocationBase;
+
+ char moduleName[MAX_PATH];
+
+ // FIXME: We explicitly use the ANSI variant of the function here.
+ if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
+ {
+ return 0;
+ }
+
+ char *file_name = (char *)(malloc (strlen (moduleName) + 1));
+ strcpy (file_name, moduleName);
+ info->file_name = file_name;
+
+ // FIXME.
+ info->base = NULL;
+ info->sym_name = NULL;
+ info->sym_addr = NULL;
+
+ return 1;
+}