Commit b96e5d21 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Split up resolve_folder.

parent ecdb2415
...@@ -1189,7 +1189,7 @@ static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param) ...@@ -1189,7 +1189,7 @@ static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param)
ui_actiondata(package, szCreateFolders, uirow); ui_actiondata(package, szCreateFolders, uirow);
msiobj_release(&uirow->hdr); msiobj_release(&uirow->hdr);
full_path = resolve_folder(package,dir,FALSE,FALSE,TRUE,&folder); full_path = resolve_target_folder( package, dir, FALSE, TRUE, &folder );
if (!full_path) if (!full_path)
{ {
ERR("Unable to resolve folder id %s\n",debugstr_w(dir)); ERR("Unable to resolve folder id %s\n",debugstr_w(dir));
...@@ -1264,7 +1264,7 @@ static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param ) ...@@ -1264,7 +1264,7 @@ static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
full_path = resolve_folder( package, dir, FALSE, FALSE, TRUE, &folder ); full_path = resolve_target_folder( package, dir, FALSE, TRUE, &folder );
if (!full_path) if (!full_path)
{ {
ERR("Unable to resolve folder id %s\n", debugstr_w(dir)); ERR("Unable to resolve folder id %s\n", debugstr_w(dir));
...@@ -2151,10 +2151,9 @@ static UINT ITERATE_CostFinalizeDirectories(MSIRECORD *row, LPVOID param) ...@@ -2151,10 +2151,9 @@ static UINT ITERATE_CostFinalizeDirectories(MSIRECORD *row, LPVOID param)
msi_free(f->ResolvedTarget); msi_free(f->ResolvedTarget);
f->ResolvedTarget = NULL; f->ResolvedTarget = NULL;
/* This helper function now does ALL the work */ TRACE("directory %s ...\n", debugstr_w(name));
TRACE("Dir %s ...\n",debugstr_w(name)); path = resolve_target_folder( package, name, TRUE, TRUE, NULL );
path = resolve_folder(package,name,FALSE,TRUE,TRUE,NULL); TRACE("resolves to %s\n", debugstr_w(path));
TRACE("resolves to %s\n",debugstr_w(path));
msi_free(path); msi_free(path);
return ERROR_SUCCESS; return ERROR_SUCCESS;
...@@ -2302,7 +2301,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFILE *file ) ...@@ -2302,7 +2301,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFILE *file )
} }
else else
{ {
WCHAR *dir = resolve_folder( package, file->Component->Directory, FALSE, FALSE, TRUE, NULL ); WCHAR *dir = resolve_target_folder( package, file->Component->Directory, FALSE, TRUE, NULL );
file->TargetPath = build_directory_name( 2, dir, file->FileName ); file->TargetPath = build_directory_name( 2, dir, file->FileName );
msi_free( dir ); msi_free( dir );
} }
...@@ -3133,7 +3132,7 @@ static LPWSTR resolve_keypath( MSIPACKAGE* package, MSICOMPONENT *cmp ) ...@@ -3133,7 +3132,7 @@ static LPWSTR resolve_keypath( MSIPACKAGE* package, MSICOMPONENT *cmp )
{ {
if (!cmp->KeyPath) if (!cmp->KeyPath)
return resolve_folder(package,cmp->Directory,FALSE,FALSE,TRUE,NULL); return resolve_target_folder( package, cmp->Directory, FALSE, TRUE, NULL );
if (cmp->Attributes & msidbComponentAttributesRegistryKeyPath) if (cmp->Attributes & msidbComponentAttributesRegistryKeyPath)
{ {
...@@ -3551,8 +3550,7 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param) ...@@ -3551,8 +3550,7 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
helpid = MSI_RecordGetString(row,6); helpid = MSI_RecordGetString(row,6);
if (helpid) if (helpid) help = resolve_target_folder( package, helpid, FALSE, TRUE, NULL );
help = resolve_folder(package,helpid,FALSE,FALSE,TRUE,NULL);
res = RegisterTypeLib(tl_struct.ptLib,tl_struct.path,help); res = RegisterTypeLib(tl_struct.ptLib,tl_struct.path,help);
msi_free(help); msi_free(help);
...@@ -3686,7 +3684,7 @@ static WCHAR *get_link_file( MSIPACKAGE *package, MSIRECORD *row ) ...@@ -3686,7 +3684,7 @@ static WCHAR *get_link_file( MSIPACKAGE *package, MSIRECORD *row )
LPWSTR link_folder, link_file, filename; LPWSTR link_folder, link_file, filename;
directory = MSI_RecordGetString( row, 2 ); directory = MSI_RecordGetString( row, 2 );
link_folder = resolve_folder( package, directory, FALSE, FALSE, TRUE, NULL ); link_folder = resolve_target_folder( package, directory, FALSE, TRUE, NULL );
/* may be needed because of a bug somewhere else */ /* may be needed because of a bug somewhere else */
create_full_pathW( link_folder ); create_full_pathW( link_folder );
...@@ -3807,7 +3805,7 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param) ...@@ -3807,7 +3805,7 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
if (!MSI_RecordIsNull(row,12)) if (!MSI_RecordIsNull(row,12))
{ {
LPCWSTR wkdir = MSI_RecordGetString(row, 12); LPCWSTR wkdir = MSI_RecordGetString(row, 12);
path = resolve_folder(package, wkdir, FALSE, FALSE, TRUE, NULL); path = resolve_target_folder( package, wkdir, FALSE, TRUE, NULL );
if (path) if (path)
IShellLinkW_SetWorkingDirectory(sl, path); IShellLinkW_SetWorkingDirectory(sl, path);
msi_free(path); msi_free(path);
...@@ -4340,7 +4338,7 @@ static WCHAR *get_ini_file_name( MSIPACKAGE *package, MSIRECORD *row ) ...@@ -4340,7 +4338,7 @@ static WCHAR *get_ini_file_name( MSIPACKAGE *package, MSIRECORD *row )
dirprop = MSI_RecordGetString( row, 3 ); dirprop = MSI_RecordGetString( row, 3 );
if (dirprop) if (dirprop)
{ {
folder = resolve_folder( package, dirprop, FALSE, FALSE, TRUE, NULL ); folder = resolve_target_folder( package, dirprop, FALSE, TRUE, NULL );
if (!folder) if (!folder)
folder = msi_dup_property( package->db, dirprop ); folder = msi_dup_property( package->db, dirprop );
} }
......
...@@ -1150,8 +1150,7 @@ static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source, ...@@ -1150,8 +1150,7 @@ static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source,
memset(&si, 0, sizeof(STARTUPINFOW)); memset(&si, 0, sizeof(STARTUPINFOW));
workingdir = resolve_folder(package, source, FALSE, FALSE, TRUE, NULL); workingdir = resolve_target_folder( package, source, FALSE, TRUE, NULL );
if (!workingdir) if (!workingdir)
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
......
...@@ -163,7 +163,7 @@ static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir ) ...@@ -163,7 +163,7 @@ static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir )
MSIFOLDER *folder; MSIFOLDER *folder;
WCHAR *install_path; WCHAR *install_path;
install_path = resolve_folder( package, dir, FALSE, FALSE, TRUE, &folder ); install_path = resolve_target_folder( package, dir, FALSE, TRUE, &folder );
if (!install_path) if (!install_path)
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
...@@ -690,7 +690,7 @@ static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const ...@@ -690,7 +690,7 @@ static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const
{ {
const WCHAR *dst_key = MSI_RecordGetString( row, 5 ); const WCHAR *dst_key = MSI_RecordGetString( row, 5 );
dst_path = resolve_folder( package, dst_key, FALSE, FALSE, TRUE, NULL ); dst_path = resolve_target_folder( package, dst_key, FALSE, TRUE, NULL );
if (!dst_path) if (!dst_path)
{ {
/* try a property */ /* try a property */
......
...@@ -185,7 +185,6 @@ static LPWSTR deformat_component(FORMAT *format, FORMSTR *str) ...@@ -185,7 +185,6 @@ static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
{ {
LPWSTR key, ret = NULL; LPWSTR key, ret = NULL;
MSICOMPONENT *comp; MSICOMPONENT *comp;
BOOL source;
key = msi_alloc((str->len + 1) * sizeof(WCHAR)); key = msi_alloc((str->len + 1) * sizeof(WCHAR));
lstrcpynW(key, get_formstr_data(format, str), str->len + 1); lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
...@@ -194,8 +193,10 @@ static LPWSTR deformat_component(FORMAT *format, FORMSTR *str) ...@@ -194,8 +193,10 @@ static LPWSTR deformat_component(FORMAT *format, FORMSTR *str)
if (!comp) if (!comp)
goto done; goto done;
source = (comp->Action == INSTALLSTATE_SOURCE) ? TRUE : FALSE; if (comp->Action == INSTALLSTATE_SOURCE)
ret = resolve_folder(format->package, comp->Directory, source, FALSE, TRUE, NULL); ret = resolve_source_folder( format->package, comp->Directory, NULL );
else
ret = resolve_target_folder( format->package, comp->Directory, FALSE, TRUE, NULL );
done: done:
msi_free(key); msi_free(key);
......
...@@ -232,8 +232,7 @@ LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file) ...@@ -232,8 +232,7 @@ LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
if (file->IsCompressed) if (file->IsCompressed)
return NULL; return NULL;
p = resolve_folder(package, file->Component->Directory, p = resolve_source_folder( package, file->Component->Directory, NULL );
TRUE, FALSE, TRUE, NULL);
path = build_directory_name(2, p, file->ShortName); path = build_directory_name(2, p, file->ShortName);
if (file->LongName && if (file->LongName &&
...@@ -245,22 +244,16 @@ LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file) ...@@ -245,22 +244,16 @@ LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
msi_free(p); msi_free(p);
TRACE("file %s source resolves to %s\n", debugstr_w(file->File), TRACE("file %s source resolves to %s\n", debugstr_w(file->File), debugstr_w(path));
debugstr_w(path));
return path; return path;
} }
LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, LPWSTR resolve_source_folder( MSIPACKAGE *package, LPCWSTR name, MSIFOLDER **folder )
BOOL set_prop, BOOL load_prop, MSIFOLDER **folder)
{ {
MSIFOLDER *f; MSIFOLDER *f;
LPWSTR p, path = NULL, parent; LPWSTR p, path = NULL, parent;
TRACE("Working to resolve %s\n",debugstr_w(name)); TRACE("working to resolve %s\n", debugstr_w(name));
if (!name)
return NULL;
if (!strcmpW( name, cszSourceDir )) if (!strcmpW( name, cszSourceDir ))
name = cszTargetDir; name = cszTargetDir;
...@@ -272,6 +265,57 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, ...@@ -272,6 +265,57 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
/* special resolving for Target and Source root dir */ /* special resolving for Target and Source root dir */
if (!strcmpW( name, cszTargetDir )) if (!strcmpW( name, cszTargetDir ))
{ {
if (!f->ResolvedSource)
f->ResolvedSource = get_source_root( package );
}
if (folder)
*folder = f;
if (f->ResolvedSource)
{
path = strdupW( f->ResolvedSource );
TRACE(" already resolved to %s\n", debugstr_w(path));
return path;
}
if (!f->Parent)
return path;
parent = f->Parent;
TRACE(" ! parent is %s\n", debugstr_w(parent));
p = resolve_source_folder( package, parent, NULL );
if (package->WordCount & msidbSumInfoSourceTypeCompressed)
path = get_source_root( package );
else if (package->WordCount & msidbSumInfoSourceTypeSFN)
path = build_directory_name( 3, p, f->SourceShortPath, NULL );
else
path = build_directory_name( 3, p, f->SourceLongPath, NULL );
TRACE("-> %s\n", debugstr_w(path));
f->ResolvedSource = strdupW( path );
msi_free( p );
return path;
}
LPWSTR resolve_target_folder( MSIPACKAGE *package, LPCWSTR name, BOOL set_prop, BOOL load_prop,
MSIFOLDER **folder )
{
MSIFOLDER *f;
LPWSTR p, path = NULL, parent;
TRACE("working to resolve %s\n", debugstr_w(name));
f = get_loaded_folder( package, name );
if (!f)
return NULL;
/* special resolving for Target and Source root dir */
if (!strcmpW( name, cszTargetDir ))
{
if (!f->ResolvedTarget && !f->Property) if (!f->ResolvedTarget && !f->Property)
{ {
LPWSTR check_path; LPWSTR check_path;
...@@ -292,39 +336,27 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, ...@@ -292,39 +336,27 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
f->ResolvedTarget = path; f->ResolvedTarget = path;
} }
if (!f->ResolvedSource)
f->ResolvedSource = get_source_root( package );
} }
if (folder) if (folder)
*folder = f; *folder = f;
if (!source && f->ResolvedTarget) if (f->ResolvedTarget)
{ {
path = strdupW( f->ResolvedTarget ); path = strdupW( f->ResolvedTarget );
TRACE(" already resolved to %s\n",debugstr_w(path)); TRACE(" already resolved to %s\n", debugstr_w(path));
return path;
}
if (source && f->ResolvedSource)
{
path = strdupW( f->ResolvedSource );
TRACE(" (source)already resolved to %s\n",debugstr_w(path));
return path; return path;
} }
if (!source && f->Property) if (f->Property)
{ {
path = build_directory_name( 2, f->Property, NULL ); path = build_directory_name( 2, f->Property, NULL );
TRACE(" internally set to %s\n", debugstr_w(path));
TRACE(" internally set to %s\n",debugstr_w(path)); if (set_prop) msi_set_property( package->db, name, path );
if (set_prop)
msi_set_property( package->db, name, path );
return path; return path;
} }
if (!source && load_prop && (path = msi_dup_property( package->db, name ))) if (load_prop && (path = msi_dup_property( package->db, name )))
{ {
f->ResolvedTarget = strdupW( path ); f->ResolvedTarget = strdupW( path );
TRACE(" property set to %s\n", debugstr_w(path)); TRACE(" property set to %s\n", debugstr_w(path));
...@@ -336,35 +368,18 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, ...@@ -336,35 +368,18 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
parent = f->Parent; parent = f->Parent;
TRACE(" ! Parent is %s\n", debugstr_w(parent)); TRACE(" ! parent is %s\n", debugstr_w(parent));
p = resolve_folder(package, parent, source, set_prop, load_prop, NULL);
if (!source)
{
TRACE(" TargetDefault = %s\n", debugstr_w(f->TargetDefault));
path = build_directory_name( 3, p, f->TargetDefault, NULL ); p = resolve_target_folder( package, parent, set_prop, load_prop, NULL );
clean_spaces_from_path( path );
f->ResolvedTarget = strdupW( path );
TRACE("target -> %s\n", debugstr_w(path));
if (set_prop)
msi_set_property( package->db, name, path );
}
else
{
path = NULL;
if (package->WordCount & msidbSumInfoSourceTypeCompressed) TRACE(" TargetDefault = %s\n", debugstr_w(f->TargetDefault));
path = get_source_root( package ); path = build_directory_name( 3, p, f->TargetDefault, NULL );
else if (package->WordCount & msidbSumInfoSourceTypeSFN) clean_spaces_from_path( path );
path = build_directory_name( 3, p, f->SourceShortPath, NULL ); f->ResolvedTarget = strdupW( path );
else
path = build_directory_name( 3, p, f->SourceLongPath, NULL );
TRACE("source -> %s\n", debugstr_w(path)); TRACE("-> %s\n", debugstr_w(path));
f->ResolvedSource = strdupW( path ); if (set_prop) msi_set_property( package->db, name, path );
} msi_free( p );
msi_free(p);
return path; return path;
} }
......
...@@ -282,7 +282,7 @@ done: ...@@ -282,7 +282,7 @@ done:
return r; return r;
} }
path = resolve_folder( package, szFolder, FALSE, FALSE, TRUE, NULL ); path = resolve_target_folder( package, szFolder, FALSE, TRUE, NULL );
msiobj_release( &package->hdr ); msiobj_release( &package->hdr );
if (!path) if (!path)
...@@ -336,7 +336,7 @@ UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, ...@@ -336,7 +336,7 @@ UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
} }
/*********************************************************************** /***********************************************************************
* MsiGetSourcePath (internal) * MSI_GetSourcePath (internal)
*/ */
static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder, static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
awstring *szPathBuf, LPDWORD pcchPathBuf ) awstring *szPathBuf, LPDWORD pcchPathBuf )
...@@ -413,10 +413,10 @@ done: ...@@ -413,10 +413,10 @@ done:
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
} }
path = resolve_folder(package, szFolder, TRUE, FALSE, TRUE, NULL); path = resolve_source_folder( package, szFolder, NULL );
msiobj_release( &package->hdr ); msiobj_release( &package->hdr );
TRACE("path = %s\n",debugstr_w(path)); TRACE("path = %s\n", debugstr_w(path));
if (!path) if (!path)
return ERROR_DIRECTORY; return ERROR_DIRECTORY;
...@@ -512,7 +512,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, ...@@ -512,7 +512,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
attrib & FILE_ATTRIBUTE_READONLY)) attrib & FILE_ATTRIBUTE_READONLY))
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
path = resolve_folder(package,szFolder,FALSE,FALSE,FALSE,&folder); path = resolve_target_folder( package, szFolder, FALSE, FALSE, &folder );
if (!path) if (!path)
return ERROR_DIRECTORY; return ERROR_DIRECTORY;
...@@ -527,7 +527,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, ...@@ -527,7 +527,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
*/ */
msi_free(folder->ResolvedTarget); msi_free(folder->ResolvedTarget);
folder->ResolvedTarget = NULL; folder->ResolvedTarget = NULL;
path2 = resolve_folder(package,szFolder,FALSE,TRUE,FALSE,NULL); path2 = resolve_target_folder( package, szFolder, TRUE, FALSE, NULL );
msi_free(path2); msi_free(path2);
} }
else else
...@@ -542,7 +542,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, ...@@ -542,7 +542,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry ) LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
{ {
path2 = resolve_folder(package, f->Directory, FALSE, TRUE, FALSE, NULL); path2 = resolve_target_folder( package, f->Directory, TRUE, FALSE, NULL );
msi_free(path2); msi_free(path2);
} }
...@@ -554,7 +554,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, ...@@ -554,7 +554,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
if (!comp->Enabled || (comp->assembly && !comp->assembly->application)) if (!comp->Enabled || (comp->assembly && !comp->assembly->application))
continue; continue;
dir = resolve_folder(package, comp->Directory, FALSE, FALSE, FALSE, NULL); dir = resolve_target_folder( package, comp->Directory, FALSE, FALSE, NULL );
msi_free(file->TargetPath); msi_free(file->TargetPath);
file->TargetPath = build_directory_name(2, dir, file->FileName); file->TargetPath = build_directory_name(2, dir, file->FileName);
......
...@@ -931,8 +931,8 @@ extern LPWSTR msi_dup_property( MSIDATABASE *db, LPCWSTR prop ); ...@@ -931,8 +931,8 @@ extern LPWSTR msi_dup_property( MSIDATABASE *db, LPCWSTR prop );
extern UINT msi_set_property( MSIDATABASE *, LPCWSTR, LPCWSTR ); extern UINT msi_set_property( MSIDATABASE *, LPCWSTR, LPCWSTR );
extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD ); extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD );
extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def ); extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def );
extern LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, extern LPWSTR resolve_source_folder(MSIPACKAGE *package, LPCWSTR name, MSIFOLDER **folder);
BOOL set_prop, BOOL load_prop, MSIFOLDER **folder); extern LPWSTR resolve_target_folder(MSIPACKAGE *package, LPCWSTR name, BOOL set_prop, BOOL load_prop, MSIFOLDER **folder);
extern LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file); extern LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file);
extern void msi_reset_folders( MSIPACKAGE *package, BOOL source ); extern void msi_reset_folders( MSIPACKAGE *package, BOOL source );
extern MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component ); extern MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component );
......
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