blob: 5d77b873dbe1e409656e6f59f618b84f2b8cf108 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CDEV_CURRENT_FUNCTION _comment_
/**
* @file
* @ingroup Port
* @brief System information
*/
#undef CDEV_CURRENT_FUNCTION
#include <stdio.h>
#include <windows.h>
#include "portpriv.h"
#include "hyportpg.h"
/* Missing from the ALPHA include files */
#if !defined(VER_PLATFORM_WIN32_WINDOWS)
#define VER_PLATFORM_WIN32_WINDOWS 1
#endif
#define CDEV_CURRENT_FUNCTION _prototypes_private
/* none */
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION _prototypes_public
IDATA VMCALL hysysinfo_get_executable_name (struct HyPortLibrary *
portLibrary, char *argv0,
char **result);
const char *VMCALL hysysinfo_get_OS_type (struct HyPortLibrary *portLibrary);
U_64 VMCALL hysysinfo_get_physical_memory (struct HyPortLibrary *portLibrary);
UDATA VMCALL hysysinfo_DLPAR_max_CPUs (struct HyPortLibrary *portLibrary);
UDATA VMCALL hysysinfo_get_number_CPUs (struct HyPortLibrary *portLibrary);
const char *VMCALL hysysinfo_get_CPU_architecture (struct HyPortLibrary
*portLibrary);
UDATA VMCALL hysysinfo_get_processing_capacity (struct HyPortLibrary
*portLibrary);
const char *VMCALL hysysinfo_get_OS_version (struct HyPortLibrary
*portLibrary);
I_32 VMCALL hysysinfo_startup (struct HyPortLibrary *portLibrary);
UDATA VMCALL hysysinfo_DLPAR_enabled (struct HyPortLibrary *portLibrary);
void VMCALL hysysinfo_shutdown (struct HyPortLibrary *portLibrary);
UDATA VMCALL hysysinfo_get_pid (struct HyPortLibrary *portLibrary);
U_16 VMCALL hysysinfo_get_classpathSeparator (struct HyPortLibrary
*portLibrary);
IDATA VMCALL hysysinfo_get_username (struct HyPortLibrary *portLibrary,
char *buffer, UDATA length);
UDATA VMCALL hysysinfo_weak_memory_consistency (struct HyPortLibrary
*portLibrary);
IDATA VMCALL hysysinfo_get_env (struct HyPortLibrary *portLibrary,
char *envVar, char *infoString,
UDATA bufSize);
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_CPU_architecture
/**
* Determine the CPU architecture.
*
* @param[in] portLibrary The port library.
*
* @return A null-terminated string describing the CPU architecture of the hardware, NULL on error.
*
* @note portLibrary is responsible for allocation/deallocation of returned buffer.
* @note See http://www.tolstoy.com/samizdat/sysprops.html for good values to return.
*/
const char *VMCALL
hysysinfo_get_CPU_architecture (struct HyPortLibrary *portLibrary)
{
#if defined(_ALPHA_)
return HYPORT_ARCH_ALPHA;
#elif defined(_ARM_)
return HYPORT_ARCH_ARM;
#elif defined( _MIPS_)
return HYPORT_ARCH_MIPS;
#elif defined(_PPC_)
return HYPORT_ARCH_PPC;
#elif defined( _SH4_)
return HYPORT_ARCH_SH4;
#elif defined( _SH3_)
return HYPORT_ARCH_SH3;
#elif defined(_X86_)
return HYPORT_ARCH_X86;
#elif defined( _AMD64_)
return HYPORT_ARCH_HAMMER;
#else
return "unknown";
#endif
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_env
/**
* Query the operating system for environment variables.
*
* Obtain the value of the environment variable specified by envVar from the operating system
* and write out to supplied buffer.
*
* @param[in] portLibrary The port library.
* @param[in] envVar Environment variable to query.
* @param[out] infoString Buffer for value string describing envVar.
* @param[in] bufSize Size of buffer to hold returned string.
*
* @return 0 on success, number of bytes required to hold the
* information if the output buffer was too small, -1 on failure.
*
* @note infoString is undefined on error or when supplied buffer was too small.
*/
IDATA VMCALL
hysysinfo_get_env (struct HyPortLibrary * portLibrary, char *envVar,
char *infoString, UDATA bufSize)
{
DWORD rc;
rc = GetEnvironmentVariable (envVar, infoString, bufSize);
/* If the function succeeds, the return value is the number of characters stored into
the buffer, not including the terminating null character. If the specified environment
variable name was not found in the environment block for the current process, the
return value is zero.
If the buffer pointed to by lpBuffer is not large enough, the return value is the buffer
size, in characters, required to hold the value string and its terminating null character.
*/
if (rc > bufSize)
{
return rc;
}
else if (rc == 0)
{
return -1;
}
else
{
return 0; /* success */
}
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_OS_type
/**
* Determine the OS type.
*
* @param[in] portLibrary The port library.
*
* @return OS type string (NULL terminated) on success, NULL on error.
*
* @note portLibrary is responsible for allocation/deallocation of returned buffer.
*/
const char *VMCALL
hysysinfo_get_OS_type (struct HyPortLibrary *portLibrary)
{
if (NULL == PPG_si_osType)
{
OSVERSIONINFOEX versionInfo;
versionInfo.dwOSVersionInfoSize = sizeof (versionInfo);
if (!GetVersionEx ((OSVERSIONINFO *) & versionInfo))
{
return NULL;
}
switch (versionInfo.dwPlatformId)
{
case VER_PLATFORM_WIN32s:
PPG_si_osType = "Windows 3.1";
break;
case VER_PLATFORM_WIN32_WINDOWS:
switch (versionInfo.dwMinorVersion)
{
case 0:
PPG_si_osType = "Windows 95";
break;
case 90:
PPG_si_osType = "Windows Me";
break;
default:
PPG_si_osType = "Windows 98";
break;
}
break;
case VER_PLATFORM_WIN32_NT:
if (versionInfo.dwMajorVersion < 5)
{
PPG_si_osType = "Windows NT";
}
else
{
switch (versionInfo.dwMinorVersion)
{
case 0:
PPG_si_osType = "Windows 2000";
break;
/* case 1: WinNT 5.1 => Windows XP. Handled by the default. */
case 2:
/* WinNT 5.2 can be either Win2003 Server or Workstation (e.g. XP64).
Report workstation products as "Windows XP". */
if (versionInfo.wProductType == VER_NT_WORKSTATION)
{
PPG_si_osType = "Windows XP";
}
else
{
PPG_si_osType = "Windows Server 2003";
}
break;
default:
PPG_si_osType = "Windows XP";
break;
}
}
break;
default:
PPG_si_osType = "unknown";
break;
}
}
return PPG_si_osType;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_OS_version
/**
* Determine version information from the operating system.
*
* @param[in] portLibrary The port library.
*
* @return OS version string (NULL terminated) on success, NULL on error.
*
* @note portLibrary is responsible for allocation/deallocation of returned buffer.
*/
const char *VMCALL
hysysinfo_get_OS_version (struct HyPortLibrary *portLibrary)
{
if (NULL == PPG_si_osVersion)
{
OSVERSIONINFO versionInfo;
int len = sizeof ("0123456789.0123456789 build 0123456789") + 1;
char *buffer;
#if defined(UNICODE)
int convSize;
int position;
#endif /* UNICODE */
versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (!GetVersionEx (&versionInfo))
{
return NULL;
}
#if defined(UNICODE)
convSize =
WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK,
versionInfo.szCSDVersion, -1, NULL, 0, NULL,
NULL);
convSize = (convSize + 1) * 2;
len = len + convSize + 2;
buffer = portLibrary->mem_allocate_memory (portLibrary, len);
if (NULL == buffer)
{
return NULL;
}
position = sprintf (buffer, "%d.%d build %d%s",
versionInfo.dwMajorVersion,
versionInfo.dwMinorVersion,
versionInfo.dwBuildNumber & 0x0000FFFF,
versionInfo.szCSDVersion ? " " : "");
WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK,
versionInfo.szCSDVersion, -1,
(WCHAR *) & buffer[position], convSize, NULL,
NULL);
PPG_si_osVersion = buffer;
#else
len = len + strlen (versionInfo.szCSDVersion) + 2;
buffer = portLibrary->mem_allocate_memory (portLibrary, len);
if (NULL == buffer)
{
return NULL;
}
sprintf (buffer, "%d.%d build %d%s%s",
versionInfo.dwMajorVersion,
versionInfo.dwMinorVersion,
versionInfo.dwBuildNumber & 0x0000FFFF,
versionInfo.szCSDVersion ? " " : "",
versionInfo.szCSDVersion ? versionInfo.szCSDVersion : "");
PPG_si_osVersion = buffer;
#endif
}
return PPG_si_osVersion;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_pid
/**
* Determine the process ID of the calling process.
*
* @param[in] portLibrary The port library.
*
* @return the PID.
*/
UDATA VMCALL
hysysinfo_get_pid (struct HyPortLibrary * portLibrary)
{
return GetCurrentProcessId ();
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_classpathSeparator
/**
* Determine the character used to separate entries on the classpath.
*
* @param[in] portLibrary The port library.
*
* @return the classpathSeparator character.
*/
U_16 VMCALL
hysysinfo_get_classpathSeparator (struct HyPortLibrary * portLibrary)
{
return ';';
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_executable_name
/**
* Determines an absolute pathname for the executable.
*
* @param[in] portLibrary The port library.
* @param[in] argv0 argv[0] value
* @param[out] result Null terminated pathname string
*
* @return 0 on success, -1 on error (or information is not available).
*
* @note Caller is responsible for de-allocating memory for result buffer with @ref hymem_free_memory.
*/
IDATA VMCALL
hysysinfo_get_executable_name (struct HyPortLibrary * portLibrary,
char *argv0, char **result)
{
char *temp;
TCHAR osTemp[_MAX_PATH + 2];
DWORD length;
(void) argv0; /* unused */
length = GetModuleFileName (NULL, osTemp, _MAX_PATH + 1);
if (!length || (length >= _MAX_PATH))
{
return -1;
}
osTemp[length] = (TCHAR) '\0'; /* jic */
#if defined(UNICODE)
length =
WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, osTemp, -1, NULL, 0, NULL,
NULL);
temp = portLibrary->mem_allocate_memory (portLibrary, length + 1);
if (!temp)
{
return -1;
}
length =
WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, osTemp, -1, temp, length,
NULL, NULL);
#else
temp = portLibrary->mem_allocate_memory (portLibrary, length + 1);
if (!temp)
{
return -1;
}
strcpy (temp, osTemp);
#endif
*result = temp;
return 0;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_number_CPUs
/**
* Determine the number of CPUs on this platform.
*
* @param[in] portLibrary The port library.
*
* @return The number of supported CPUs.
*/
UDATA VMCALL
hysysinfo_get_number_CPUs (struct HyPortLibrary * portLibrary)
{
SYSTEM_INFO aSysInfo;
GetSystemInfo (&aSysInfo);
return aSysInfo.dwNumberOfProcessors;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_physical_memory
/**
* Determine the size of the total physical memory in the system, in bytes.
*
* @param[in] portLibrary The port library.
*
* @return 0 if the information was unavailable, otherwise total physical memory in bytes.
*/
U_64 VMCALL
hysysinfo_get_physical_memory (struct HyPortLibrary * portLibrary)
{
MEMORYSTATUS aMemStatus;
/* Function does not work properly on systems with more than 4 GB, when not running Win2K */
SetLastError (ERROR_SUCCESS);
GlobalMemoryStatus (&aMemStatus);
if (GetLastError () != ERROR_SUCCESS)
{
return HYCONST64 (0);
}
return (U_64) aMemStatus.dwTotalPhys;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_DLPAR_enabled
/**
* Determine if DLPAR (i.e. the ability to change number of CPUs and amount of memory dynamically)
* is enabled on this platform.
*
* @param[in] portLibrary The port library.
*
* @return 1 if DLPAR is supported, otherwise 0.
*/
UDATA VMCALL
hysysinfo_DLPAR_enabled (struct HyPortLibrary * portLibrary)
{
return FALSE;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_weak_memory_consistency
/**
* Determine if the platform has weak memory consistency behaviour.
*
* @param[in] portLibrary The port library.
*
* @return 1 if weak memory consistency, 0 otherwise.
*/
UDATA VMCALL
hysysinfo_weak_memory_consistency (struct HyPortLibrary * portLibrary)
{
return FALSE;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_shutdown
/**
* PortLibrary shutdown.
*
* This function is called during shutdown of the portLibrary. Any resources that were created by @ref hysysinfo_startup
* should be destroyed here.
*
* @param[in] portLibrary The port library.
*
* @note Most implementations will be empty.
*/
void VMCALL
hysysinfo_shutdown (struct HyPortLibrary *portLibrary)
{
if (PPG_si_osVersion)
{
portLibrary->mem_free_memory (portLibrary, PPG_si_osVersion);
PPG_si_osVersion = NULL;
}
/* PPG_si_osType is not dynamically allocated, so no need to free */
PPG_si_osType = NULL;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_startup
/**
* PortLibrary startup.
*
* This function is called during startup of the portLibrary. Any resources that are required for
* the system information operations may be created here. All resources created here should be destroyed
* in @ref hysysinfo_shutdown.
*
* @param[in] portLibrary The port library.
*
* @return 0 on success, negative error code on failure. Error code values returned are
* \arg HYPORT_ERROR_STARTUP_SYSINFO
*
* @note Most implementations will simply return success.
*/
I_32 VMCALL
hysysinfo_startup (struct HyPortLibrary *portLibrary)
{
return 0;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_DLPAR_max_CPUs
/**
* Determine the maximum number of CPUs on this platform
*
* @param[in] portLibrary The port library.
*
* @return The maximum number of supported CPUs..
*/
UDATA VMCALL
hysysinfo_DLPAR_max_CPUs (struct HyPortLibrary * portLibrary)
{
return portLibrary->sysinfo_get_number_CPUs (portLibrary);
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_username
/**
* Query the operating system for the name of the user associate with the current thread
*
* Obtain the value of the name of the user associated with the current thread, and then
* write it out into the buffer supplied by the user
*
* @param[in] portLibrary The port Library
* @param[out] buffer Buffer for the name of the user
* @param[in,out] length The length of the buffer
*
* @return 0 on success, number of bytes required to hold the
* information if the output buffer was too small, -1 on failure.
*
* @note buffer is undefined on error or when supplied buffer was too small.
*/
IDATA VMCALL
hysysinfo_get_username (struct HyPortLibrary * portLibrary, char *buffer,
UDATA length)
{
int resultLength = length;
if (GetUserName (buffer, &resultLength))
{
return 0;
}
if (GetLastError () == ERROR_INSUFFICIENT_BUFFER)
{
return resultLength;
}
return -1;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hysysinfo_get_processing_capacity
/**
* Determine the collective processing capacity available to the VM
* in units of 1% of a physical processor. In environments without
* some kind of virtual partitioning, this will simply be the number
* of CPUs * 100.
*
* @param[in] portLibrary The port library.
*
* @return The processing capacity available to the VM.
*/
UDATA VMCALL
hysysinfo_get_processing_capacity (struct HyPortLibrary * portLibrary)
{
return portLibrary->sysinfo_get_number_CPUs (portLibrary) * 100;
}
#undef CDEV_CURRENT_FUNCTION