Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
f89ab56e
Commit
f89ab56e
authored
Jul 05, 2019
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mscoree: Build with msvcrt.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
ed435371
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
93 additions
and
86 deletions
+93
-86
Makefile.in
dlls/mscoree/Makefile.in
+2
-0
assembly.c
dlls/mscoree/assembly.c
+0
-1
config.c
dlls/mscoree/config.c
+6
-6
corruntimehost.c
dlls/mscoree/corruntimehost.c
+12
-13
metadata.c
dlls/mscoree/metadata.c
+0
-1
metahost.c
dlls/mscoree/metahost.c
+67
-57
mscoree_main.c
dlls/mscoree/mscoree_main.c
+6
-8
No files found.
dlls/mscoree/Makefile.in
View file @
f89ab56e
MODULE
=
mscoree.dll
IMPORTS
=
dbghelp uuid shell32 advapi32 ole32 oleaut32 shlwapi
EXTRADLLFLAGS
=
-mno-cygwin
C_SRCS
=
\
assembly.c
\
config.c
\
...
...
dlls/mscoree/assembly.c
View file @
f89ab56e
...
...
@@ -37,7 +37,6 @@
#include "mscoree_private.h"
#include "wine/debug.h"
#include "wine/unicode.h"
typedef
struct
{
...
...
dlls/mscoree/config.c
View file @
f89ab56e
...
...
@@ -426,7 +426,7 @@ static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
switch
(
This
->
states
[
This
->
statenum
])
{
case
STATE_ROOT
:
if
(
nLocalName
==
ARRAY_SIZE
(
configuration
)
-
1
&&
lstrcmpW
(
pLocalName
,
configuration
)
==
0
)
if
(
nLocalName
==
ARRAY_SIZE
(
configuration
)
-
1
&&
wcscmp
(
pLocalName
,
configuration
)
==
0
)
{
This
->
states
[
++
This
->
statenum
]
=
STATE_CONFIGURATION
;
break
;
...
...
@@ -434,13 +434,13 @@ static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
else
goto
unknown
;
case
STATE_CONFIGURATION
:
if
(
nLocalName
==
ARRAY_SIZE
(
startup
)
-
1
&&
lstrcmpW
(
pLocalName
,
startup
)
==
0
)
if
(
nLocalName
==
ARRAY_SIZE
(
startup
)
-
1
&&
wcscmp
(
pLocalName
,
startup
)
==
0
)
{
hr
=
parse_startup
(
This
,
pAttr
);
This
->
states
[
++
This
->
statenum
]
=
STATE_STARTUP
;
break
;
}
else
if
(
nLocalName
==
ARRAY_SIZE
(
runtime
)
-
1
&&
lstrcmpW
(
pLocalName
,
runtime
)
==
0
)
else
if
(
nLocalName
==
ARRAY_SIZE
(
runtime
)
-
1
&&
wcscmp
(
pLocalName
,
runtime
)
==
0
)
{
This
->
states
[
++
This
->
statenum
]
=
STATE_RUNTIME
;
break
;
...
...
@@ -449,7 +449,7 @@ static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
goto
unknown
;
case
STATE_RUNTIME
:
if
(
nLocalName
==
ARRAY_SIZE
(
assemblyBinding
)
-
1
&&
lstrcmpW
(
pLocalName
,
assemblyBinding
)
==
0
)
wcscmp
(
pLocalName
,
assemblyBinding
)
==
0
)
{
This
->
states
[
++
This
->
statenum
]
=
STATE_ASSEMBLY_BINDING
;
break
;
...
...
@@ -457,7 +457,7 @@ static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
else
goto
unknown
;
case
STATE_ASSEMBLY_BINDING
:
if
(
nLocalName
==
ARRAY_SIZE
(
probing
)
-
1
&&
lstrcmpW
(
pLocalName
,
probing
)
==
0
)
if
(
nLocalName
==
ARRAY_SIZE
(
probing
)
-
1
&&
wcscmp
(
pLocalName
,
probing
)
==
0
)
{
hr
=
parse_probing
(
This
,
pAttr
);
This
->
states
[
++
This
->
statenum
]
=
STATE_PROBING
;
...
...
@@ -467,7 +467,7 @@ static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
goto
unknown
;
case
STATE_STARTUP
:
if
(
nLocalName
==
ARRAY_SIZE
(
supportedRuntime
)
-
1
&&
lstrcmpW
(
pLocalName
,
supportedRuntime
)
==
0
)
wcscmp
(
pLocalName
,
supportedRuntime
)
==
0
)
{
hr
=
parse_supported_runtime
(
This
,
pAttr
);
This
->
states
[
++
This
->
statenum
]
=
STATE_UNKNOWN
;
...
...
dlls/mscoree/corruntimehost.c
View file @
f89ab56e
...
...
@@ -40,7 +40,6 @@
#include "mscoree_private.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
mscoree
);
...
...
@@ -1480,8 +1479,8 @@ __int32 WINAPI _CorExeMain(void)
WCHAR
config_file
[
MAX_PATH
];
static
const
WCHAR
dotconfig
[]
=
{
'.'
,
'c'
,
'o'
,
'n'
,
'f'
,
'i'
,
'g'
,
0
};
strcpyW
(
config_file
,
filename
);
strcatW
(
config_file
,
dotconfig
);
l
strcpyW
(
config_file
,
filename
);
l
strcatW
(
config_file
,
dotconfig
);
hr
=
RuntimeHost_GetDefaultDomain
(
host
,
config_file
,
&
domain
);
}
...
...
@@ -1686,10 +1685,10 @@ static BOOL try_create_registration_free_com(REFIID clsid, WCHAR *classname, UIN
ERR
(
"Buffer is too small
\n
"
);
goto
end
;
}
strcpyW
(
classname
,
ptr_name
);
l
strcpyW
(
classname
,
ptr_name
);
ptr_path_start
=
assembly_info
->
lpAssemblyEncodedAssemblyIdentity
;
ptr_path_end
=
strchrW
(
ptr_path_start
,
','
);
ptr_path_end
=
wcschr
(
ptr_path_start
,
','
);
memcpy
(
path
,
ptr_path_start
,
(
char
*
)
ptr_path_end
-
(
char
*
)
ptr_path_start
);
GetModuleFileNameW
(
NULL
,
filename
,
filename_size
);
...
...
@@ -1702,7 +1701,7 @@ static BOOL try_create_registration_free_com(REFIID clsid, WCHAR *classname, UIN
}
PathAppendW
(
filename
,
path
);
strcatW
(
filename
,
str_dll
);
l
strcatW
(
filename
,
str_dll
);
ret
=
TRUE
;
...
...
@@ -1766,10 +1765,10 @@ HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
if
(
res
==
ERROR_SUCCESS
)
{
/* Strip file:/// */
if
(
strncmpW
(
codebase
,
wszFileSlash
,
strlenW
(
wszFileSlash
))
==
0
)
offset
=
strlenW
(
wszFileSlash
);
if
(
wcsncmp
(
codebase
,
wszFileSlash
,
l
strlenW
(
wszFileSlash
))
==
0
)
offset
=
l
strlenW
(
wszFileSlash
);
strcpyW
(
filename
,
codebase
+
offset
);
l
strcpyW
(
filename
,
codebase
+
offset
);
}
else
{
...
...
@@ -1808,14 +1807,14 @@ HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
WARN
(
"Attempt to load from the application directory.
\n
"
);
GetModuleFileNameW
(
NULL
,
filename
,
MAX_PATH
);
ns
=
strrchrW
(
filename
,
'\\'
);
ns
=
wcsrchr
(
filename
,
'\\'
);
*
(
ns
+
1
)
=
'\0'
;
ns
=
strchrW
(
assemblyname
,
','
);
ns
=
wcschr
(
assemblyname
,
','
);
*
(
ns
)
=
'\0'
;
strcatW
(
filename
,
assemblyname
);
l
strcatW
(
filename
,
assemblyname
);
*
(
ns
)
=
'.'
;
strcatW
(
filename
,
wszDLL
);
l
strcatW
(
filename
,
wszDLL
);
}
}
}
...
...
dlls/mscoree/metadata.c
View file @
f89ab56e
...
...
@@ -24,7 +24,6 @@
#define COBJMACROS
#include "wine/library.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
...
...
dlls/mscoree/metahost.c
View file @
f89ab56e
...
...
@@ -24,8 +24,6 @@
#define COBJMACROS
#include "wine/unicode.h"
#include "wine/library.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
...
...
@@ -171,12 +169,12 @@ static HRESULT load_mono(LPCWSTR mono_path)
if
(
!
mono_handle
)
{
strcpyW
(
mono_lib_path
,
mono_path
);
strcatW
(
mono_lib_path
,
lib
);
l
strcpyW
(
mono_lib_path
,
mono_path
);
l
strcatW
(
mono_lib_path
,
lib
);
WideCharToMultiByte
(
CP_UTF8
,
0
,
mono_lib_path
,
-
1
,
mono_lib_path_a
,
MAX_PATH
,
NULL
,
NULL
);
strcpyW
(
mono_etc_path
,
mono_path
);
strcatW
(
mono_etc_path
,
etc
);
l
strcpyW
(
mono_etc_path
,
mono_path
);
l
strcatW
(
mono_etc_path
,
etc
);
WideCharToMultiByte
(
CP_UTF8
,
0
,
mono_etc_path
,
-
1
,
mono_etc_path_a
,
MAX_PATH
,
NULL
,
NULL
);
if
(
!
find_mono_dll
(
mono_path
,
mono_dll_path
))
goto
fail
;
...
...
@@ -499,7 +497,7 @@ static HRESULT WINAPI CLRRuntimeInfo_GetRuntimeDirectory(ICLRRuntimeInfo* iface,
if
(
pwzBuffer
)
{
if
(
buffer_size
>=
size
)
strcpyW
(
pwzBuffer
,
system_dir
);
l
strcpyW
(
pwzBuffer
,
system_dir
);
else
hr
=
E_NOT_SUFFICIENT_BUFFER
;
}
...
...
@@ -644,21 +642,21 @@ static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path)
static
const
WCHAR
libmono2_dll
[]
=
{
'\\'
,
'b'
,
'i'
,
'n'
,
'\\'
,
'l'
,
'i'
,
'b'
,
'm'
,
'o'
,
'n'
,
'o'
,
'-'
,
'2'
,
'.'
,
'0'
,
'.'
,
'd'
,
'l'
,
'l'
,
0
};
DWORD
attributes
=
INVALID_FILE_ATTRIBUTES
;
strcpyW
(
dll_path
,
path
);
strcatW
(
dll_path
,
libmono2_arch_dll
);
l
strcpyW
(
dll_path
,
path
);
l
strcatW
(
dll_path
,
libmono2_arch_dll
);
attributes
=
GetFileAttributesW
(
dll_path
);
if
(
attributes
==
INVALID_FILE_ATTRIBUTES
)
{
strcpyW
(
dll_path
,
path
);
strcatW
(
dll_path
,
mono2_dll
);
l
strcpyW
(
dll_path
,
path
);
l
strcatW
(
dll_path
,
mono2_dll
);
attributes
=
GetFileAttributesW
(
dll_path
);
}
if
(
attributes
==
INVALID_FILE_ATTRIBUTES
)
{
strcpyW
(
dll_path
,
path
);
strcatW
(
dll_path
,
libmono2_dll
);
l
strcpyW
(
dll_path
,
path
);
l
strcatW
(
dll_path
,
libmono2_dll
);
attributes
=
GetFileAttributesW
(
dll_path
);
}
...
...
@@ -672,11 +670,11 @@ static BOOL get_mono_path_local(LPWSTR path)
/* c:\windows\mono\mono-2.0 */
GetWindowsDirectoryW
(
base_path
,
MAX_PATH
);
strcatW
(
base_path
,
subdir_mono
);
l
strcatW
(
base_path
,
subdir_mono
);
if
(
find_mono_dll
(
base_path
,
mono_dll_path
))
{
strcpyW
(
path
,
base_path
);
l
strcpyW
(
path
,
base_path
);
return
TRUE
;
}
...
...
@@ -701,7 +699,7 @@ static BOOL get_mono_path_registry(LPWSTR path)
res
=
RegGetValueW
(
hkey
,
NULL
,
valuename
,
RRF_RT_REG_SZ
,
NULL
,
base_path
,
&
valuesize
);
if
(
res
==
ERROR_SUCCESS
&&
find_mono_dll
(
base_path
,
mono_dll_path
))
{
strcpyW
(
path
,
base_path
);
l
strcpyW
(
path
,
base_path
);
ret
=
TRUE
;
}
...
...
@@ -710,12 +708,36 @@ static BOOL get_mono_path_registry(LPWSTR path)
return
ret
;
}
static
BOOL
get_mono_path_
unix
(
const
char
*
unix_
dir
,
LPWSTR
path
)
static
BOOL
get_mono_path_
dos
(
const
WCHAR
*
dir
,
LPWSTR
path
)
{
static
const
WCHAR
unix_prefix
[]
=
{
'\\'
,
'\\'
,
'?'
,
'\\'
,
'u'
,
'n'
,
'i'
,
'x'
,
'\\'
};
static
WCHAR
*
(
CDECL
*
p_wine_get_dos_file_name
)(
const
char
*
)
;
static
const
char
basedir
[]
=
"
\\
wine-mono-"
WINE_MONO_VERSION
;
LPWSTR
dos_dir
;
WCHAR
mono_dll_path
[
MAX_PATH
];
DWORD
len
;
BOOL
ret
;
if
(
memcmp
(
dir
,
unix_prefix
,
sizeof
(
unix_prefix
))
==
0
)
return
FALSE
;
/* No drive letter for this directory */
len
=
lstrlenW
(
dir
)
+
MultiByteToWideChar
(
CP_UNIXCP
,
0
,
basedir
,
-
1
,
NULL
,
0
);
if
(
!
(
dos_dir
=
heap_alloc
(
len
*
sizeof
(
WCHAR
)
)))
return
FALSE
;
lstrcpyW
(
dos_dir
,
dir
);
MultiByteToWideChar
(
CP_UNIXCP
,
0
,
basedir
,
-
1
,
dos_dir
+
lstrlenW
(
dos_dir
),
len
-
lstrlenW
(
dos_dir
));
ret
=
find_mono_dll
(
dos_dir
,
mono_dll_path
);
if
(
ret
)
lstrcpyW
(
path
,
dos_dir
);
heap_free
(
dos_dir
);
return
ret
;
}
static
BOOL
get_mono_path_unix
(
const
char
*
unix_dir
,
LPWSTR
path
)
{
static
WCHAR
*
(
CDECL
*
p_wine_get_dos_file_name
)(
const
char
*
);
LPWSTR
dos_dir
;
BOOL
ret
;
if
(
!
p_wine_get_dos_file_name
)
...
...
@@ -729,49 +751,37 @@ static BOOL get_mono_path_unix(const char *unix_dir, LPWSTR path)
if
(
!
dos_dir
)
return
FALSE
;
if
(
memcmp
(
dos_dir
,
unix_prefix
,
sizeof
(
unix_prefix
))
==
0
)
{
/* No drive letter for this directory */
heap_free
(
dos_dir
);
return
FALSE
;
}
ret
=
find_mono_dll
(
dos_dir
,
mono_dll_path
);
if
(
ret
)
strcpyW
(
path
,
dos_dir
);
ret
=
get_mono_path_dos
(
dos_dir
,
path
);
heap_free
(
dos_dir
);
return
ret
;
}
static
BOOL
get_mono_path_datadir
(
LPWSTR
path
)
{
const
char
*
data_dir
;
char
*
package_dir
;
int
len
;
static
const
WCHAR
winedatadirW
[]
=
{
'W'
,
'I'
,
'N'
,
'E'
,
'D'
,
'A'
,
'T'
,
'A'
,
'D'
,
'I'
,
'R'
,
0
};
static
const
WCHAR
winebuilddirW
[]
=
{
'W'
,
'I'
,
'N'
,
'E'
,
'B'
,
'U'
,
'I'
,
'L'
,
'D'
,
'D'
,
'I'
,
'R'
,
0
};
static
const
WCHAR
unix_prefix
[]
=
{
'\\'
,
'?'
,
'?'
,
'\\'
,
'u'
,
'n'
,
'i'
,
'x'
,
'\\'
};
static
const
WCHAR
monoW
[]
=
{
'\\'
,
'm'
,
'o'
,
'n'
,
'o'
,
0
};
static
const
WCHAR
dotdotW
[]
=
{
'\\'
,
'.'
,
'.'
,
0
};
const
WCHAR
*
data_dir
,
*
suffix
;
WCHAR
*
package_dir
;
BOOL
ret
;
if
((
data_dir
=
wine_get_data_dir
()))
{
len
=
strlen
(
data_dir
);
package_dir
=
heap_alloc
(
len
+
sizeof
(
"/mono/wine-mono-"
WINE_MONO_VERSION
));
memcpy
(
package_dir
,
data_dir
,
len
);
strcpy
(
package_dir
+
len
,
"/mono/wine-mono-"
WINE_MONO_VERSION
);
}
else
if
((
data_dir
=
wine_get_build_dir
()))
{
len
=
strlen
(
data_dir
);
package_dir
=
heap_alloc
(
len
+
sizeof
(
"/../wine-mono-"
WINE_MONO_VERSION
));
memcpy
(
package_dir
,
data_dir
,
len
);
strcpy
(
package_dir
+
len
,
"/../wine-mono-"
WINE_MONO_VERSION
);
}
if
((
data_dir
=
_wgetenv
(
winedatadirW
)))
suffix
=
monoW
;
else
if
((
data_dir
=
_wgetenv
(
winebuilddirW
)))
suffix
=
dotdotW
;
else
{
return
FALSE
;
}
ret
=
get_mono_path_unix
(
package_dir
,
path
);
if
(
!
wcsncmp
(
data_dir
,
unix_prefix
,
wcslen
(
unix_prefix
)
))
return
FALSE
;
data_dir
+=
4
;
/* skip \??\ prefix */
package_dir
=
heap_alloc
(
(
lstrlenW
(
data_dir
)
+
lstrlenW
(
suffix
)
+
1
)
*
sizeof
(
WCHAR
));
lstrcpyW
(
package_dir
,
data_dir
);
lstrcatW
(
package_dir
,
suffix
);
ret
=
get_mono_path_dos
(
package_dir
,
path
);
heap_free
(
package_dir
);
...
...
@@ -783,10 +793,10 @@ BOOL get_mono_path(LPWSTR path, BOOL skip_local)
return
(
!
skip_local
&&
get_mono_path_local
(
path
))
||
get_mono_path_registry
(
path
)
||
get_mono_path_datadir
(
path
)
||
get_mono_path_unix
(
INSTALL_DATADIR
"/wine/mono
/wine-mono-"
WINE_MONO_VERSION
,
path
)
||
get_mono_path_unix
(
INSTALL_DATADIR
"/wine/mono
"
,
path
)
||
(
strcmp
(
INSTALL_DATADIR
,
"/usr/share"
)
&&
get_mono_path_unix
(
"/usr/share/wine/mono
/wine-mono-"
WINE_MONO_VERSION
,
path
))
||
get_mono_path_unix
(
"/opt/wine/mono
/wine-mono-"
WINE_MONO_VERSION
,
path
);
get_mono_path_unix
(
"/usr/share/wine/mono
"
,
path
))
||
get_mono_path_unix
(
"/opt/wine/mono
"
,
path
);
}
struct
InstalledRuntimeEnum
...
...
@@ -1485,9 +1495,9 @@ static HKEY get_app_overrides_key(void)
{
HKEY
tmpkey
;
WCHAR
*
p
,
*
appname
=
bufferW
;
if
((
p
=
strrchrW
(
appname
,
'/'
)))
appname
=
p
+
1
;
if
((
p
=
strrchrW
(
appname
,
'\\'
)))
appname
=
p
+
1
;
strcatW
(
appname
,
subkeyW
);
if
((
p
=
wcsrchr
(
appname
,
'/'
)))
appname
=
p
+
1
;
if
((
p
=
wcsrchr
(
appname
,
'\\'
)))
appname
=
p
+
1
;
l
strcatW
(
appname
,
subkeyW
);
/* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Mono\AsmOverrides */
if
(
!
RegOpenKeyA
(
HKEY_CURRENT_USER
,
"Software
\\
Wine
\\
AppDefaults"
,
&
tmpkey
))
{
...
...
@@ -1683,8 +1693,8 @@ HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
if
(
exefile
&&
!
config_file
&&
!
config_stream
)
{
strcpyW
(
local_config_file
,
exefile
);
strcatW
(
local_config_file
,
dotconfig
);
l
strcpyW
(
local_config_file
,
exefile
);
l
strcatW
(
local_config_file
,
dotconfig
);
config_file
=
local_config_file
;
}
...
...
dlls/mscoree/mscoree_main.c
View file @
f89ab56e
...
...
@@ -22,8 +22,6 @@
#include <stdarg.h>
#define COBJMACROS
#include "wine/unicode.h"
#include "wine/library.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
...
...
@@ -414,11 +412,11 @@ HRESULT WINAPI LoadLibraryShim( LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvR
else
szVersion
=
default_version
;
}
strcatW
(
dll_filename
,
szVersion
);
strcatW
(
dll_filename
,
slash
);
l
strcatW
(
dll_filename
,
szVersion
);
l
strcatW
(
dll_filename
,
slash
);
}
strcatW
(
dll_filename
,
szDllName
);
l
strcatW
(
dll_filename
,
szDllName
);
*
phModDll
=
LoadLibraryW
(
dll_filename
);
...
...
@@ -578,7 +576,7 @@ HRESULT WINAPI CreateDebuggingInterfaceFromVersion(int nDebugVersion, LPCWSTR ve
*
ppv
=
NULL
;
if
(
strcmpW
(
version
,
v2_0
)
!=
0
)
if
(
wcscmp
(
version
,
v2_0
)
!=
0
)
{
FIXME
(
"Currently .NET Version '%s' not support.
\n
"
,
debugstr_w
(
version
));
return
E_INVALIDARG
;
...
...
@@ -732,8 +730,8 @@ static BOOL get_support_msi(LPCWSTR mono_path, LPWSTR msi_path)
hmsi
=
GetModuleHandleA
(
"msi"
);
strcpyW
(
msi_path
,
mono_path
);
strcatW
(
msi_path
,
support_msi_relative
);
l
strcpyW
(
msi_path
,
mono_path
);
l
strcatW
(
msi_path
,
support_msi_relative
);
pMsiOpenPackageW
=
(
void
*
)
GetProcAddress
(
hmsi
,
"MsiOpenPackageW"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment