Path: blob/master/runtime/jcl/win32/syshelp.c
12609 views
/*******************************************************************************1* Copyright (c) 1998, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21/* Undefine the winsockapi because winsock2 defines it. Removes warnings. */22#if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)23#undef _WINSOCKAPI_24#endif25#include <winsock2.h>26#include <windows.h>27#include <winbase.h>28#include <stdlib.h>29#include <LMCONS.H>30#include <direct.h>31#include "jcl.h"32#include "jclprots.h"33#include "jclglob.h"34#include "util_api.h"353637#include "portsock.h"3839#include <WinSDKVer.h>4041#if defined(_WIN32_WINNT_WINBLUE) && (_WIN32_WINNT_MAXVER >= _WIN32_WINNT_WINBLUE)42#include <VersionHelpers.h>43#endif4445/* JCL_J2SE */46#define JCL_J2SE474849char* getPlatformFileEncoding(JNIEnv *env, char *codepage, int size, int encodingType);50I_32 convertToUTF8(J9PortLibrary* portLibrary, const wchar_t* unicodeString, char* utf8Buffer, UDATA size);51char * getTmpDir(JNIEnv *env, char **tempdir);52jobject getPlatformPropertyList(JNIEnv *env, const char *strings[], int propIndex);53void mapLibraryToPlatformName(const char *inPath, char *outPath);545556jobject getPlatformPropertyList(JNIEnv *env, const char *strings[], int propIndex) {57PORT_ACCESS_FROM_ENV(env);58#if !defined(_WIN32_WINNT_WINBLUE) || (_WIN32_WINNT_MAXVER < _WIN32_WINNT_WINBLUE)59OSVERSIONINFO versionInfo;60#endif /* !defined(_WIN32_WINNT_WINBLUE) || (_WIN32_WINNT_MAXVER < _WIN32_WINNT_WINBLUE) */61I_32 envSize;62char *envSpace = NULL, *tempdir = NULL;63jobject result;64char userhome[EsMaxPath];65wchar_t unicodeTemp[EsMaxPath];66int i;67char userdir[EsMaxPath];68wchar_t unicodeHome[EsMaxPath];69HANDLE process, token;70UDATA handle;71BOOL (WINAPI *func)(HANDLE hToken, LPWSTR lpProfileDir, LPDWORD lpcchSize);72#if !defined(JCL_J2SE)73UINT codePage;74char codePageBuf[32];75CPINFO cpInfo;76#endif7778/* Hard coded file/path separators and other values */7980strings[propIndex++] = "file.separator";81strings[propIndex++] = "\\";8283strings[propIndex++] = "line.separator";84strings[propIndex++] = "\r\n";8586/* Get the Temp Dir name */87strings[propIndex++] = "java.io.tmpdir";88strings[propIndex++] = getTmpDir(env, &tempdir);8990strings[propIndex++] = "user.home";91i = propIndex;92envSize = (I_32)j9sysinfo_get_env("USERPROFILE", NULL, 0);93if (-1 != envSize) {94envSpace = jclmem_allocate_memory(env, envSize); /* trailing null taken into account */95if (NULL == envSpace) {96strings[propIndex++] = "\\";97} else {98j9sysinfo_get_env("USERPROFILE", envSpace, envSize);99strings[propIndex++] = envSpace;100}101}102#if defined(_WIN32_WINNT_WINBLUE) && (_WIN32_WINNT_MAXVER >= _WIN32_WINNT_WINBLUE)103/* dwPlatformId, VER_PLATFORM_WIN32_NT = https://msdn.microsoft.com/en-us/library/windows/desktop/ms724834(v=vs.85).aspx */104if ((i == propIndex) && IsWindowsVersionOrGreater( 5, 0, 0))105#else /* defined(_WIN32_WINNT_WINBLUE) && (_WIN32_WINNT_MAXVER >= _WIN32_WINNT_WINBLUE) */106versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);107if ((i == propIndex) && GetVersionEx(&versionInfo) && (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT))108#endif /* defined(_WIN32_WINNT_WINBLUE) && (_WIN32_WINNT_MAXVER >= _WIN32_WINNT_WINBLUE) */109{110process = GetCurrentProcess();111if (OpenProcessToken(process, TOKEN_QUERY, &token)) {112envSize = 0;113if (j9util_open_system_library("userenv", &handle, TRUE) == 0) {114if (i == propIndex) {115if (j9sl_lookup_name(handle, "GetUserProfileDirectoryW", (UDATA *)&func, "ZPLP") == 0) {116envSize = EsMaxPath;117if (func(token, unicodeHome, &envSize)) {118/* When the SystemDrive environment variable isn't set, such as when j9 is exec'ed119* running JCK tests, we get %SystemDrive%/Documents and Settings/...120*/121if (!wcsncmp(unicodeHome, L"%SystemDrive%", 13)) {122/* Borrow userdir variable, which is used for real below */123if (GetSystemDirectoryW(unicodeTemp, EsMaxPath) > 1) {124unicodeHome[0] = unicodeTemp[0];125unicodeHome[1] = unicodeTemp[1];126wcsncpy(&unicodeHome[2], &unicodeHome[13], envSize - 13);127}128}129convertToUTF8(PORTLIB, unicodeHome, userhome, EsMaxPath);130strings[propIndex++] = userhome;131}132}133}134}135}136}137138if (i == propIndex) {139/* Fallback to Windows Directory */140envSize = (I_32)j9sysinfo_get_env("WINDIR", NULL, 0);141if (-1 == envSize) {142strings[propIndex++] = "\\";143} else {144envSpace = jclmem_allocate_memory(env,envSize); /* trailing null taken into account */145if(!envSpace) {146strings[propIndex++] = "\\";147} else {148j9sysinfo_get_env("WINDIR", envSpace, envSize);149strings[propIndex++] = envSpace;150}151}152}153154/* Get the directory where the executable was started */155strings[propIndex++] = "user.dir";156if (GetCurrentDirectoryW(EsMaxPath, unicodeTemp) == 0) {157strings[propIndex++] = "\\";158} else {159convertToUTF8(PORTLIB, unicodeTemp, userdir, EsMaxPath);160strings[propIndex++] = userdir;161}162163if (JAVA_SPEC_VERSION < 12) {164/* Get the timezone */165strings[propIndex++] = "user.timezone";166strings[propIndex++] = "";167}168169/* Jazz 52075 JCL_J2SE is always true */170171result = createSystemPropertyList(env, strings, propIndex);172if (tempdir) jclmem_free_memory(env,tempdir);173if (envSpace) jclmem_free_memory(env,envSpace);174return result;175}176177178char* getPlatformFileEncoding(JNIEnv *env, char *codepage, int size, int encodingType) {179PORT_ACCESS_FROM_ENV(env);180LCID threadLocale;181CPINFO cpInfo;182int cp;183#ifdef UNICODE184int i;185#endif186int length;187188/* Called with codepage == NULL to initialize the locale */189if (!codepage) return NULL;190191if (encodingType == 2) {192/* file.encoding */193threadLocale = GetUserDefaultLCID();194} else {195threadLocale = GetSystemDefaultLCID();196}197length = GetLocaleInfo(threadLocale, LOCALE_IDEFAULTANSICODEPAGE, (LPTSTR)&codepage[2], size - 2);198199#ifdef UNICODE200// convert double byte to single byte201for (i=0; i < length; i++) {202codepage[i+2] = (char)((short *)&codepage[2])[i];203}204codepage[length+2]='\0';205#endif206207/*[PR CMVC 84620] file.encoding is incorrect for foreign locales */208if (length == 2 && codepage[2] == '0') {209/* no ANSI code page, return UTF8 if its supported, otherwise fall through to return ISO8859_1 */210if (IsValidCodePage(65001)) {211return "UTF8";212}213}214215if (length == 0 || (cp = atoi(&codepage[2])) == 0)216return "ISO8859_1";217218/*[PR 94901] Get info about the current code page, not the system code page (CP_ACP) */219if (GetCPInfo(cp, &cpInfo) && cpInfo.MaxCharSize > 1) {220if (cp == 936) {221J9JavaVM* vm = ((J9VMThread *)env)->javaVM;222if (J2SE_VERSION(vm) < J2SE_V11) {223if (IsValidCodePage(54936)) {224return "GB18030";225}226}227return "GBK";228} else if (cp == 54936) return "GB18030";229codepage[0] = 'M';230codepage[1] = 'S';231} else {232codepage[0] = 'C';233#if defined(JCL_J2SE)234codepage[1] = 'p';235#else236codepage[1] = 'P';237#endif238}239240return codepage;241}242243244/**245* Turns a platform independent DLL name into a platform specific one246*/247void mapLibraryToPlatformName(const char *inPath, char *outPath) {248strcpy(outPath,inPath);249strcat(outPath, ".dll");250}251252253/**254* Try to find the 'correct' windows temp directory.255*/256char * getTmpDir(JNIEnv *env, char **tempdir) {257PORT_ACCESS_FROM_ENV(env);258259DWORD rc;260wchar_t unicodeBuffer[EsMaxPath];261char *buffer = NULL;262char *retVal = ".";263264rc = GetTempPathW(EsMaxPath, unicodeBuffer);265266/* If the function succeeds, the return value is the number of characters stored into267the buffer, not including the terminating null character. If the buffer is not large enough,268the return value will exceed the length parameter (i.e. the required size)269*/270271if((rc != 0) && (rc < EsMaxPath)) {272/* convert */273rc = WideCharToMultiByte(OS_ENCODING_CODE_PAGE, OS_ENCODING_WC_FLAGS, unicodeBuffer, -1, NULL, 0, NULL, NULL);274if(rc != 0) {275buffer = jclmem_allocate_memory(env, rc);276if(NULL != buffer) {277rc = WideCharToMultiByte(OS_ENCODING_CODE_PAGE, OS_ENCODING_WC_FLAGS, unicodeBuffer, -1, buffer, rc, NULL, NULL);278if(rc == 0) {279jclmem_free_memory(env, buffer);280buffer = NULL;281} else {282retVal = buffer;283}284}285}286}287*tempdir = buffer;288return retVal;289}290291/**292* @internal293* Converts the Unicode string to UTF8 encoded data in the provided buffer.294*295* @param[in] portLibrary The port library296* @param[in] unicodeString The unicode buffer to convert297* @param[in] utf8Buffer The buffer to store the UTF8 encoded bytes into298* @param[in] size The size of utf8Buffer299*300* @return 0 on success, -1 on failure.301*/302I_32303convertToUTF8(J9PortLibrary* portLibrary, const wchar_t* unicodeString, char* utf8Buffer, UDATA size)304{305PORT_ACCESS_FROM_PORT(portLibrary);306if(0 == WideCharToMultiByte(OS_ENCODING_CODE_PAGE, OS_ENCODING_WC_FLAGS, unicodeString, -1, utf8Buffer, (int)size, NULL, NULL)) {307j9error_set_last_error(GetLastError(), J9PORT_ERROR_OPFAILED); /* continue */308return -1;309}310return 0;311}312313314