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()
try
{
char const * p1 = cppuhelper_detail_findSofficePath();
auto* p1 = cppuhelper_detail_findSofficePath();
if (p1 == nullptr) {
throw BootstrapException(
"no soffice installation found!");
}
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(),
(RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR));
free(p1);
if (!bOk)
{
throw BootstrapException(
"bad characters in soffice installation path!");
}
#endif
OUString path;
if (osl::FileBase::getFileURLFromSystemPath(p2, path) !=
osl::FileBase::E_None)
......
......@@ -39,36 +39,42 @@
* @return the installation path or NULL, if no installation was found or
* if an error occurred
*/
static char* getPathFromRegistryKey( HKEY hroot, const char* subKeyName )
static wchar_t* getPathFromRegistryKey( HKEY hroot, const wchar_t* subKeyName )
{
HKEY hkey;
DWORD type;
char* data = NULL;
wchar_t* data = NULL;
DWORD size;
/* 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;
}
/* 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 );
return NULL;
}
/* get memory to hold the default value */
data = (char*) malloc( size );
data = (wchar_t*) malloc( size + sizeof(wchar_t) );
/* 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 );
free( data );
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 */
RegCloseKey( hkey );
......@@ -81,14 +87,22 @@ static char* getPathFromRegistryKey( HKEY hroot, const char* subKeyName )
* @return the installation path or NULL, if no installation was found or
* 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 */
path = getPathFromRegistryKey( HKEY_CURRENT_USER, SUBKEYNAME );
wchar_t* path = getPathFromRegistryKey( HKEY_CURRENT_USER, SUBKEYNAME );
if ( path == NULL )
{
......@@ -115,13 +129,17 @@ static char* platformSpecific()
*/
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 char* PATHSEPARATOR = ":";
const char* PATHVARNAME = "PATH";
const char* APPENDIX = "/libreoffice";
char* path = NULL;
char* env = NULL;
char* str = NULL;
char* dir = NULL;
char* sep = NULL;
......@@ -129,6 +147,11 @@ static char* platformSpecific(void)
char buffer[PATH_MAX];
int pos;
if (env && env[0])
{
return strdup(env);
}
/* get the value of the PATH environment variable */
env = getenv( PATHVARNAME );
if (env == NULL)
......@@ -184,19 +207,14 @@ static char* platformSpecific(void)
#endif
char const* cppuhelper_detail_findSofficePath()
#if defined(_WIN32)
wchar_t*
#else
char*
#endif
cppuhelper_detail_findSofficePath()
{
const char* UNOPATHVARNAME = "UNO_PATH";
char* path = NULL;
/* get the installation path from the UNO_PATH environment variable */
path = getenv( UNOPATHVARNAME );
if (!path || !path[0])
path = platformSpecific();
return path;
return platformSpecific();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -27,8 +27,14 @@ extern "C" {
#endif
/* Internal function to find an soffice installation.
Not to be called by client code */
char const* cppuhelper_detail_findSofficePath(void);
Not to be called by client code.
Returned pointer must be released with free() */
#if defined(_WIN32)
wchar_t*
#else
char*
#endif
cppuhelper_detail_findSofficePath(void);
#if defined __cplusplus
}
......
......@@ -32,7 +32,7 @@
#include "rtl/string.h"
#include "sal/types.h"
char const* getPath(void);
char* getPath(void);
char* createCommandName( char* argv0 );
static const int SEPARATOR = '/';
......@@ -63,7 +63,7 @@ static const char* PATHSEPARATOR = ":";
*/
int main( int argc, char *argv[] )
{
char const* path;
char* path;
char* cmdname;
(void) argc; /* avoid warning about unused parameter */
......@@ -80,9 +80,7 @@ int main( int argc, char *argv[] )
#else
static const char* ENVVARNAME = "LD_LIBRARY_PATH";
#endif
char * libpath;
int freeLibpath;
char* libpath;
char* value;
char* envstr;
int size;
......@@ -96,6 +94,7 @@ int main( int argc, char *argv[] )
pathlen + RTL_CONSTASCII_LENGTH(unoinfoSuffix) + 1);
/*TODO: overflow */
if (unoinfo == NULL) {
free(path);
fprintf(stderr, "Error: out of memory!\n");
exit(EXIT_FAILURE);
}
......@@ -168,13 +167,12 @@ int main( int argc, char *argv[] )
fprintf(stderr, "Error: executing unoinfo failed!\n");
exit(EXIT_FAILURE);
}
freeLibpath = 1;
free(path);
}
else
{
/* Assume an old OOo 2.x installation without unoinfo: */
libpath = (char *) path;
freeLibpath = 0;
libpath = path;
}
value = getenv( ENVVARNAME );
......@@ -196,10 +194,7 @@ int main( int argc, char *argv[] )
strcat( envstr, "=" );
#endif
strcat( envstr, libpath );
if ( freeLibpath != 0 )
{
free( libpath );
}
free( libpath );
if ( value != NULL )
{
strcat( envstr, PATHSEPARATOR );
......@@ -233,11 +228,12 @@ int main( int argc, char *argv[] )
* Gets the path of a UNO installation.
*
* @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 )
{
......
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