Kaydet (Commit) d32506e9 authored tarafından Mike Kaganski's avatar Mike Kaganski

cppuhelper_detail_findSofficePath: use Unicode on Windows

On Windows, UTF-8 is never current locale encoding; so using 8-bit
strings will always fail for paths containing characters outside
of current codepage.
Also fix leaks caused by failing to release its result: previously
it could return either result of getenv (that shouldn't get freed),
or an allocated string, but never got freed; now the result is
always allocated and properly freed.

Change-Id: I8b255dea20040eec0572de2b34280749fe8f071c
Reviewed-on: https://gerrit.libreoffice.org/42743Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarMike Kaganski <mike.kaganski@collabora.com>
üst 892c719f
...@@ -87,21 +87,28 @@ Reference< XComponentContext > SAL_CALL bootstrap() ...@@ -87,21 +87,28 @@ Reference< XComponentContext > SAL_CALL bootstrap()
try try
{ {
char const * p1 = cppuhelper_detail_findSofficePath(); auto* p1 = cppuhelper_detail_findSofficePath();
if (p1 == nullptr) { if (p1 == nullptr) {
throw BootstrapException( throw BootstrapException(
"no soffice installation found!"); "no soffice installation found!");
} }
rtl::OUString p2; rtl::OUString p2;
if (!rtl_convertStringToUString( #if defined(_WIN32)
p2 = SAL_U(p1);
free(p1);
#else
bool bOk = rtl_convertStringToUString(
&p2.pData, p1, std::strlen(p1), osl_getThreadTextEncoding(), &p2.pData, p1, std::strlen(p1), osl_getThreadTextEncoding(),
(RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR));
free(p1);
if (!bOk)
{ {
throw BootstrapException( throw BootstrapException(
"bad characters in soffice installation path!"); "bad characters in soffice installation path!");
} }
#endif
OUString path; OUString path;
if (osl::FileBase::getFileURLFromSystemPath(p2, path) != if (osl::FileBase::getFileURLFromSystemPath(p2, path) !=
osl::FileBase::E_None) osl::FileBase::E_None)
......
...@@ -39,36 +39,42 @@ ...@@ -39,36 +39,42 @@
* @return the installation path or NULL, if no installation was found or * @return the installation path or NULL, if no installation was found or
* if an error occurred * if an error occurred
*/ */
static char* getPathFromRegistryKey( HKEY hroot, const char* subKeyName ) static wchar_t* getPathFromRegistryKey( HKEY hroot, const wchar_t* subKeyName )
{ {
HKEY hkey; HKEY hkey;
DWORD type; DWORD type;
char* data = NULL; wchar_t* data = NULL;
DWORD size; DWORD size;
/* open the specified registry key */ /* open the specified registry key */
if ( RegOpenKeyEx( hroot, subKeyName, 0, KEY_READ, &hkey ) != ERROR_SUCCESS ) if ( RegOpenKeyExW( hroot, subKeyName, 0, KEY_READ, &hkey ) != ERROR_SUCCESS )
{ {
return NULL; return NULL;
} }
/* find the type and size of the default value */ /* find the type and size of the default value */
if ( RegQueryValueEx( hkey, NULL, NULL, &type, NULL, &size) != ERROR_SUCCESS ) if ( RegQueryValueExW( hkey, NULL, NULL, &type, NULL, &size) != ERROR_SUCCESS )
{ {
RegCloseKey( hkey ); RegCloseKey( hkey );
return NULL; return NULL;
} }
/* get memory to hold the default value */ /* get memory to hold the default value */
data = (char*) malloc( size ); data = (wchar_t*) malloc( size + sizeof(wchar_t) );
/* read the default value */ /* read the default value */
if ( RegQueryValueEx( hkey, NULL, NULL, &type, (LPBYTE) data, &size ) != ERROR_SUCCESS ) if ( RegQueryValueExW( hkey, NULL, NULL, &type, (LPBYTE) data, &size ) != ERROR_SUCCESS )
{ {
RegCloseKey( hkey ); RegCloseKey( hkey );
free( data );
return NULL; return NULL;
} }
// According to https://msdn.microsoft.com/en-us/ms724911, If the data has the REG_SZ,
// REG_MULTI_SZ or REG_EXPAND_SZ type, the string may not have been stored with the
// proper terminating null characters
data[size / sizeof(wchar_t)] = 0;
/* release registry key handle */ /* release registry key handle */
RegCloseKey( hkey ); RegCloseKey( hkey );
...@@ -81,14 +87,22 @@ static char* getPathFromRegistryKey( HKEY hroot, const char* subKeyName ) ...@@ -81,14 +87,22 @@ static char* getPathFromRegistryKey( HKEY hroot, const char* subKeyName )
* @return the installation path or NULL, if no installation was found or * @return the installation path or NULL, if no installation was found or
* if an error occurred * if an error occurred
*/ */
static char* platformSpecific() static wchar_t* platformSpecific()
{ {
const char* SUBKEYNAME = "Software\\LibreOffice\\UNO\\InstallPath"; const wchar_t* UNOPATHVARNAME = L"UNO_PATH";
char* path = NULL; /* get the installation path from the UNO_PATH environment variable */
wchar_t* env = _wgetenv(UNOPATHVARNAME);
if (env && env[0])
{
return wcsdup(env);
}
const wchar_t* SUBKEYNAME = L"Software\\LibreOffice\\UNO\\InstallPath";
/* read the key's default value from HKEY_CURRENT_USER */ /* read the key's default value from HKEY_CURRENT_USER */
path = getPathFromRegistryKey( HKEY_CURRENT_USER, SUBKEYNAME ); wchar_t* path = getPathFromRegistryKey( HKEY_CURRENT_USER, SUBKEYNAME );
if ( path == NULL ) if ( path == NULL )
{ {
...@@ -115,13 +129,17 @@ static char* platformSpecific() ...@@ -115,13 +129,17 @@ static char* platformSpecific()
*/ */
static char* platformSpecific(void) static char* platformSpecific(void)
{ {
const char* UNOPATHVARNAME = "UNO_PATH";
/* get the installation path from the UNO_PATH environment variable */
char* env = getenv(UNOPATHVARNAME);
const int SEPARATOR = '/'; const int SEPARATOR = '/';
const char* PATHSEPARATOR = ":"; const char* PATHSEPARATOR = ":";
const char* PATHVARNAME = "PATH"; const char* PATHVARNAME = "PATH";
const char* APPENDIX = "/libreoffice"; const char* APPENDIX = "/libreoffice";
char* path = NULL; char* path = NULL;
char* env = NULL;
char* str = NULL; char* str = NULL;
char* dir = NULL; char* dir = NULL;
char* sep = NULL; char* sep = NULL;
...@@ -129,6 +147,11 @@ static char* platformSpecific(void) ...@@ -129,6 +147,11 @@ static char* platformSpecific(void)
char buffer[PATH_MAX]; char buffer[PATH_MAX];
int pos; int pos;
if (env && env[0])
{
return strdup(env);
}
/* get the value of the PATH environment variable */ /* get the value of the PATH environment variable */
env = getenv( PATHVARNAME ); env = getenv( PATHVARNAME );
if (env == NULL) if (env == NULL)
...@@ -184,19 +207,14 @@ static char* platformSpecific(void) ...@@ -184,19 +207,14 @@ static char* platformSpecific(void)
#endif #endif
char const* cppuhelper_detail_findSofficePath() #if defined(_WIN32)
wchar_t*
#else
char*
#endif
cppuhelper_detail_findSofficePath()
{ {
const char* UNOPATHVARNAME = "UNO_PATH"; return platformSpecific();
char* path = NULL;
/* get the installation path from the UNO_PATH environment variable */
path = getenv( UNOPATHVARNAME );
if (!path || !path[0])
path = platformSpecific();
return path;
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -27,8 +27,14 @@ extern "C" { ...@@ -27,8 +27,14 @@ extern "C" {
#endif #endif
/* Internal function to find an soffice installation. /* Internal function to find an soffice installation.
Not to be called by client code */ Not to be called by client code.
char const* cppuhelper_detail_findSofficePath(void); Returned pointer must be released with free() */
#if defined(_WIN32)
wchar_t*
#else
char*
#endif
cppuhelper_detail_findSofficePath(void);
#if defined __cplusplus #if defined __cplusplus
} }
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include "rtl/string.h" #include "rtl/string.h"
#include "sal/types.h" #include "sal/types.h"
char const* getPath(void); char* getPath(void);
char* createCommandName( char* argv0 ); char* createCommandName( char* argv0 );
static const int SEPARATOR = '/'; static const int SEPARATOR = '/';
...@@ -63,7 +63,7 @@ static const char* PATHSEPARATOR = ":"; ...@@ -63,7 +63,7 @@ static const char* PATHSEPARATOR = ":";
*/ */
int main( int argc, char *argv[] ) int main( int argc, char *argv[] )
{ {
char const* path; char* path;
char* cmdname; char* cmdname;
(void) argc; /* avoid warning about unused parameter */ (void) argc; /* avoid warning about unused parameter */
...@@ -80,9 +80,7 @@ int main( int argc, char *argv[] ) ...@@ -80,9 +80,7 @@ int main( int argc, char *argv[] )
#else #else
static const char* ENVVARNAME = "LD_LIBRARY_PATH"; static const char* ENVVARNAME = "LD_LIBRARY_PATH";
#endif #endif
char * libpath; char* libpath;
int freeLibpath;
char* value; char* value;
char* envstr; char* envstr;
int size; int size;
...@@ -96,6 +94,7 @@ int main( int argc, char *argv[] ) ...@@ -96,6 +94,7 @@ int main( int argc, char *argv[] )
pathlen + RTL_CONSTASCII_LENGTH(unoinfoSuffix) + 1); pathlen + RTL_CONSTASCII_LENGTH(unoinfoSuffix) + 1);
/*TODO: overflow */ /*TODO: overflow */
if (unoinfo == NULL) { if (unoinfo == NULL) {
free(path);
fprintf(stderr, "Error: out of memory!\n"); fprintf(stderr, "Error: out of memory!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -168,13 +167,12 @@ int main( int argc, char *argv[] ) ...@@ -168,13 +167,12 @@ int main( int argc, char *argv[] )
fprintf(stderr, "Error: executing unoinfo failed!\n"); fprintf(stderr, "Error: executing unoinfo failed!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
freeLibpath = 1; free(path);
} }
else else
{ {
/* Assume an old OOo 2.x installation without unoinfo: */ /* Assume an old OOo 2.x installation without unoinfo: */
libpath = (char *) path; libpath = path;
freeLibpath = 0;
} }
value = getenv( ENVVARNAME ); value = getenv( ENVVARNAME );
...@@ -196,10 +194,7 @@ int main( int argc, char *argv[] ) ...@@ -196,10 +194,7 @@ int main( int argc, char *argv[] )
strcat( envstr, "=" ); strcat( envstr, "=" );
#endif #endif
strcat( envstr, libpath ); strcat( envstr, libpath );
if ( freeLibpath != 0 ) free( libpath );
{
free( libpath );
}
if ( value != NULL ) if ( value != NULL )
{ {
strcat( envstr, PATHSEPARATOR ); strcat( envstr, PATHSEPARATOR );
...@@ -233,11 +228,12 @@ int main( int argc, char *argv[] ) ...@@ -233,11 +228,12 @@ int main( int argc, char *argv[] )
* Gets the path of a UNO installation. * Gets the path of a UNO installation.
* *
* @return the installation path or NULL, if no installation was specified or * @return the installation path or NULL, if no installation was specified or
* found, or if an error occurred * found, or if an error occurred.
* Returned pointer must be released with free()
*/ */
char const* getPath(void) char* getPath(void)
{ {
char const* path = cppuhelper_detail_findSofficePath(); char* path = cppuhelper_detail_findSofficePath();
if ( path == NULL ) if ( path == NULL )
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment