Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
32c96add
Commit
32c96add
authored
Nov 24, 2006
by
Eric Pouech
Committed by
Alexandre Julliard
Nov 27, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dbghelp: Added a process field to the modules pair structure.
This makes the code simpler to read, a bit more efficient, and furthermore it'll be needed in future patches.
parent
04c7c203
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
58 additions
and
58 deletions
+58
-58
dbghelp_private.h
dlls/dbghelp/dbghelp_private.h
+2
-1
module.c
dlls/dbghelp/module.c
+5
-5
source.c
dlls/dbghelp/source.c
+10
-12
symbol.c
dlls/dbghelp/symbol.c
+34
-32
type.c
dlls/dbghelp/type.c
+7
-8
No files found.
dlls/dbghelp/dbghelp_private.h
View file @
32c96add
...
...
@@ -333,6 +333,7 @@ struct line_info
struct
module_pair
{
struct
process
*
pcs
;
struct
module
*
requested
;
/* in: to module_get_debug() */
struct
module
*
effective
;
/* out: module with debug info */
};
...
...
@@ -389,7 +390,7 @@ extern struct module*
extern
struct
module
*
module_find_by_name
(
const
struct
process
*
pcs
,
const
char
*
name
,
enum
module_type
type
);
extern
BOOL
module_get_debug
(
const
struct
process
*
pcs
,
struct
module_pair
*
);
extern
BOOL
module_get_debug
(
struct
module_pair
*
);
extern
struct
module
*
module_new
(
struct
process
*
pcs
,
const
char
*
name
,
enum
module_type
type
,
BOOL
virtual
,
...
...
dlls/dbghelp/module.c
View file @
32c96add
...
...
@@ -244,13 +244,13 @@ struct module* module_get_containee(const struct process* pcs,
* container (and also force the ELF container's debug info loading if deferred)
* - otherwise return the module itself if it has some debug info
*/
BOOL
module_get_debug
(
const
struct
process
*
pcs
,
struct
module_pair
*
pair
)
BOOL
module_get_debug
(
struct
module_pair
*
pair
)
{
IMAGEHLP_DEFERRED_SYMBOL_LOAD64
idsl64
;
if
(
!
pair
->
requested
)
return
FALSE
;
/* for a PE builtin, always get info from container */
if
(
!
(
pair
->
effective
=
module_get_container
(
pcs
,
pair
->
requested
)))
if
(
!
(
pair
->
effective
=
module_get_container
(
p
air
->
p
cs
,
pair
->
requested
)))
pair
->
effective
=
pair
->
requested
;
/* if deferred, force loading */
if
(
pair
->
effective
->
module
.
SymType
==
SymDeferred
)
...
...
@@ -272,9 +272,9 @@ BOOL module_get_debug(const struct process* pcs, struct module_pair* pair)
idsl64
.
Reparse
=
FALSE
;
idsl64
.
hFile
=
INVALID_HANDLE_VALUE
;
pcs_callback
(
pcs
,
CBA_DEFERRED_SYMBOL_LOAD_START
,
&
idsl64
);
ret
=
pe_load_debug_info
(
pcs
,
pair
->
effective
);
pcs_callback
(
pcs
,
pcs_callback
(
p
air
->
p
cs
,
CBA_DEFERRED_SYMBOL_LOAD_START
,
&
idsl64
);
ret
=
pe_load_debug_info
(
p
air
->
p
cs
,
pair
->
effective
);
pcs_callback
(
p
air
->
p
cs
,
ret
?
CBA_DEFERRED_SYMBOL_LOAD_COMPLETE
:
CBA_DEFERRED_SYMBOL_LOAD_FAILURE
,
&
idsl64
);
break
;
...
...
dlls/dbghelp/source.c
View file @
32c96add
...
...
@@ -116,26 +116,25 @@ BOOL WINAPI SymEnumSourceFiles(HANDLE hProcess, ULONG64 ModBase, PCSTR Mask,
PSYM_ENUMSOURCEFILES_CALLBACK
cbSrcFiles
,
PVOID
UserContext
)
{
struct
process
*
pcs
;
struct
module_pair
pair
;
SOURCEFILE
sf
;
char
*
ptr
;
if
(
!
cbSrcFiles
)
return
FALSE
;
pcs
=
process_find_by_handle
(
hProcess
);
if
(
!
pcs
)
return
FALSE
;
p
air
.
p
cs
=
process_find_by_handle
(
hProcess
);
if
(
!
p
air
.
p
cs
)
return
FALSE
;
if
(
ModBase
)
{
pair
.
requested
=
module_find_by_addr
(
pcs
,
ModBase
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
p
air
.
p
cs
,
ModBase
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
}
else
{
if
(
Mask
[
0
]
==
'!'
)
{
pair
.
requested
=
module_find_by_name
(
pcs
,
Mask
+
1
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
pair
.
requested
=
module_find_by_name
(
p
air
.
p
cs
,
Mask
+
1
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
}
else
{
...
...
@@ -162,7 +161,6 @@ BOOL WINAPI SymEnumSourceFiles(HANDLE hProcess, ULONG64 ModBase, PCSTR Mask,
BOOL
WINAPI
SymEnumLines
(
HANDLE
hProcess
,
ULONG64
base
,
PCSTR
compiland
,
PCSTR
srcfile
,
PSYM_ENUMLINES_CALLBACK
cb
,
PVOID
user
)
{
struct
process
*
pcs
;
struct
module_pair
pair
;
struct
hash_table_iter
hti
;
struct
symt_ht
*
sym
;
...
...
@@ -173,8 +171,6 @@ BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland,
const
char
*
file
;
if
(
!
cb
)
return
FALSE
;
pcs
=
process_find_by_handle
(
hProcess
);
if
(
!
pcs
)
return
FALSE
;
if
(
!
(
dbghelp_options
&
SYMOPT_LOAD_LINES
))
return
TRUE
;
if
(
regcomp
(
&
re
,
srcfile
,
REG_NOSUB
))
{
...
...
@@ -182,9 +178,11 @@ BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland,
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
pair
.
pcs
=
process_find_by_handle
(
hProcess
);
if
(
!
pair
.
pcs
)
return
FALSE
;
if
(
compiland
)
FIXME
(
"Unsupported yet (filtering on compiland %s)
\n
"
,
compiland
);
pair
.
requested
=
module_find_by_addr
(
pcs
,
base
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
p
air
.
p
cs
,
base
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
sci
.
SizeOfStruct
=
sizeof
(
sci
);
sci
.
ModBase
=
base
;
...
...
dlls/dbghelp/symbol.c
View file @
32c96add
...
...
@@ -695,13 +695,13 @@ int symt_find_nearest(struct module* module, DWORD addr)
return
low
;
}
static
BOOL
symt_enum_locals_helper
(
struct
process
*
pcs
,
struct
module_pair
*
pair
,
static
BOOL
symt_enum_locals_helper
(
struct
module_pair
*
pair
,
regex_t
*
preg
,
const
struct
sym_enum
*
se
,
struct
vector
*
v
)
{
struct
symt
**
plsym
=
NULL
;
struct
symt
*
lsym
=
NULL
;
DWORD
pc
=
pcs
->
ctx_frame
.
InstructionOffset
;
DWORD
pc
=
p
air
->
p
cs
->
ctx_frame
.
InstructionOffset
;
while
((
plsym
=
vector_iter_up
(
v
,
plsym
)))
{
...
...
@@ -713,7 +713,7 @@ static BOOL symt_enum_locals_helper(struct process* pcs, struct module_pair* pai
struct
symt_block
*
block
=
(
struct
symt_block
*
)
lsym
;
if
(
pc
<
block
->
address
||
block
->
address
+
block
->
size
<=
pc
)
continue
;
if
(
!
symt_enum_locals_helper
(
p
cs
,
p
air
,
preg
,
se
,
&
block
->
vchildren
))
if
(
!
symt_enum_locals_helper
(
pair
,
preg
,
se
,
&
block
->
vchildren
))
return
FALSE
;
}
break
;
...
...
@@ -746,8 +746,9 @@ static BOOL symt_enum_locals(struct process* pcs, const char* mask,
se
->
sym_info
->
SizeOfStruct
=
sizeof
(
*
se
->
sym_info
);
se
->
sym_info
->
MaxNameLen
=
sizeof
(
se
->
buffer
)
-
sizeof
(
SYMBOL_INFO
);
pair
.
requested
=
module_find_by_addr
(
pcs
,
pc
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
pair
.
pcs
=
pcs
;
pair
.
requested
=
module_find_by_addr
(
pair
.
pcs
,
pc
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
if
((
idx
=
symt_find_nearest
(
pair
.
effective
,
pc
))
==
-
1
)
return
FALSE
;
sym
=
pair
.
effective
->
addr_sorttab
[
idx
];
...
...
@@ -758,7 +759,7 @@ static BOOL symt_enum_locals(struct process* pcs, const char* mask,
compile_regex
(
mask
?
mask
:
"*"
,
-
1
,
&
preg
,
dbghelp_options
&
SYMOPT_CASE_INSENSITIVE
);
ret
=
symt_enum_locals_helper
(
pcs
,
&
pair
,
&
preg
,
se
,
ret
=
symt_enum_locals_helper
(
&
pair
,
&
preg
,
se
,
&
((
struct
symt_function
*
)
sym
)
->
vchildren
);
regfree
(
&
preg
);
return
ret
;
...
...
@@ -801,16 +802,16 @@ static void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si)
static
BOOL
sym_enum
(
HANDLE
hProcess
,
ULONG64
BaseOfDll
,
PCSTR
Mask
,
const
struct
sym_enum
*
se
)
{
struct
process
*
pcs
=
process_find_by_handle
(
hProcess
);
struct
module_pair
pair
;
const
char
*
bang
;
regex_t
mod_regex
,
sym_regex
;
pair
.
pcs
=
process_find_by_handle
(
hProcess
);
if
(
BaseOfDll
==
0
)
{
/* do local variables ? */
if
(
!
Mask
||
!
(
bang
=
strchr
(
Mask
,
'!'
)))
return
symt_enum_locals
(
pcs
,
Mask
,
se
);
return
symt_enum_locals
(
p
air
.
p
cs
,
Mask
,
se
);
if
(
bang
==
Mask
)
return
FALSE
;
...
...
@@ -818,9 +819,9 @@ static BOOL sym_enum(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
compile_regex
(
bang
+
1
,
-
1
,
&
sym_regex
,
dbghelp_options
&
SYMOPT_CASE_INSENSITIVE
);
for
(
pair
.
requested
=
pcs
->
lmodules
;
pair
.
requested
;
pair
.
requested
=
pair
.
requested
->
next
)
for
(
pair
.
requested
=
p
air
.
p
cs
->
lmodules
;
pair
.
requested
;
pair
.
requested
=
pair
.
requested
->
next
)
{
if
(
pair
.
requested
->
type
==
DMT_PE
&&
module_get_debug
(
pcs
,
&
pair
))
if
(
pair
.
requested
->
type
==
DMT_PE
&&
module_get_debug
(
&
pair
))
{
if
(
regexec
(
&
mod_regex
,
pair
.
requested
->
module
.
ModuleName
,
0
,
NULL
,
0
)
==
0
&&
symt_enum_module
(
&
pair
,
&
sym_regex
,
se
))
...
...
@@ -831,11 +832,11 @@ static BOOL sym_enum(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
*/
if
(
!
pair
.
requested
&&
(
dbghelp_options
&
SYMOPT_WINE_WITH_ELF_MODULES
))
{
for
(
pair
.
requested
=
pcs
->
lmodules
;
pair
.
requested
;
pair
.
requested
=
pair
.
requested
->
next
)
for
(
pair
.
requested
=
p
air
.
p
cs
->
lmodules
;
pair
.
requested
;
pair
.
requested
=
pair
.
requested
->
next
)
{
if
(
pair
.
requested
->
type
==
DMT_ELF
&&
!
module_get_containee
(
pcs
,
pair
.
requested
)
&&
module_get_debug
(
pcs
,
&
pair
))
!
module_get_containee
(
p
air
.
p
cs
,
pair
.
requested
)
&&
module_get_debug
(
&
pair
))
{
if
(
regexec
(
&
mod_regex
,
pair
.
requested
->
module
.
ModuleName
,
0
,
NULL
,
0
)
==
0
&&
symt_enum_module
(
&
pair
,
&
sym_regex
,
se
))
...
...
@@ -847,8 +848,8 @@ static BOOL sym_enum(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
regfree
(
&
sym_regex
);
return
TRUE
;
}
pair
.
requested
=
module_find_by_addr
(
pcs
,
BaseOfDll
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
pair
.
requested
=
module_find_by_addr
(
p
air
.
p
cs
,
BaseOfDll
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
/* we always ignore module name from Mask when BaseOfDll is defined */
...
...
@@ -978,14 +979,14 @@ BOOL WINAPI SymEnumerateSymbols(HANDLE hProcess, DWORD BaseOfDll,
BOOL
WINAPI
SymFromAddr
(
HANDLE
hProcess
,
DWORD64
Address
,
DWORD64
*
Displacement
,
PSYMBOL_INFO
Symbol
)
{
struct
process
*
pcs
=
process_find_by_handle
(
hProcess
);
struct
module_pair
pair
;
struct
symt_ht
*
sym
;
int
idx
;
if
(
!
pcs
)
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pcs
,
Address
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
pair
.
pcs
=
process_find_by_handle
(
hProcess
);
if
(
!
pair
.
pcs
)
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pair
.
pcs
,
Address
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
if
((
idx
=
symt_find_nearest
(
pair
.
effective
,
Address
))
==
-
1
)
return
FALSE
;
sym
=
pair
.
effective
->
addr_sorttab
[
idx
];
...
...
@@ -1084,8 +1085,9 @@ static BOOL find_name(struct process* pcs, struct module* module, const char* na
struct
symt_ht
*
sym
=
NULL
;
struct
module_pair
pair
;
pair
.
pcs
=
pcs
;
if
(
!
(
pair
.
requested
=
module
))
return
FALSE
;
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
hash_table_iter_init
(
&
pair
.
effective
->
ht_symbols
,
&
hti
,
name
);
while
((
ptr
=
hash_table_iter_up
(
&
hti
)))
...
...
@@ -1232,7 +1234,6 @@ BOOL WINAPI SymGetSymPrev(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
BOOL
WINAPI
SymGetLineFromAddr
(
HANDLE
hProcess
,
DWORD
dwAddr
,
PDWORD
pdwDisplacement
,
PIMAGEHLP_LINE
Line
)
{
struct
process
*
pcs
=
process_find_by_handle
(
hProcess
);
struct
module_pair
pair
;
int
idx
;
...
...
@@ -1240,9 +1241,10 @@ BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr,
if
(
Line
->
SizeOfStruct
<
sizeof
(
*
Line
))
return
FALSE
;
if
(
!
pcs
)
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pcs
,
dwAddr
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
pair
.
pcs
=
process_find_by_handle
(
hProcess
);
if
(
!
pair
.
pcs
)
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pair
.
pcs
,
dwAddr
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
if
((
idx
=
symt_find_nearest
(
pair
.
effective
,
dwAddr
))
==
-
1
)
return
FALSE
;
if
(
pair
.
effective
->
addr_sorttab
[
idx
]
->
symt
.
tag
!=
SymTagFunction
)
return
FALSE
;
...
...
@@ -1339,7 +1341,6 @@ BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr,
*/
BOOL
WINAPI
SymGetLinePrev
(
HANDLE
hProcess
,
PIMAGEHLP_LINE
Line
)
{
struct
process
*
pcs
=
process_find_by_handle
(
hProcess
);
struct
module_pair
pair
;
struct
line_info
*
li
;
BOOL
in_search
=
FALSE
;
...
...
@@ -1348,9 +1349,10 @@ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line)
if
(
Line
->
SizeOfStruct
<
sizeof
(
*
Line
))
return
FALSE
;
if
(
!
pcs
)
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pcs
,
Line
->
Address
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
pair
.
pcs
=
process_find_by_handle
(
hProcess
);
if
(
!
pair
.
pcs
)
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pair
.
pcs
,
Line
->
Address
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
if
(
Line
->
Key
==
0
)
return
FALSE
;
li
=
(
struct
line_info
*
)
Line
->
Key
;
...
...
@@ -1425,15 +1427,15 @@ BOOL symt_get_func_line_next(struct module* module, PIMAGEHLP_LINE line)
*/
BOOL
WINAPI
SymGetLineNext
(
HANDLE
hProcess
,
PIMAGEHLP_LINE
Line
)
{
struct
process
*
pcs
=
process_find_by_handle
(
hProcess
);
struct
module_pair
pair
;
TRACE
(
"(%p %p)
\n
"
,
hProcess
,
Line
);
if
(
Line
->
SizeOfStruct
<
sizeof
(
*
Line
))
return
FALSE
;
if
(
!
pcs
)
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pcs
,
Line
->
Address
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
pair
.
pcs
=
process_find_by_handle
(
hProcess
);
if
(
!
pair
.
pcs
)
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pair
.
pcs
,
Line
->
Address
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
if
(
symt_get_func_line_next
(
pair
.
effective
,
Line
))
return
TRUE
;
SetLastError
(
ERROR_NO_MORE_ITEMS
);
/* FIXME */
...
...
dlls/dbghelp/type.c
View file @
32c96add
...
...
@@ -372,7 +372,6 @@ BOOL WINAPI SymEnumTypes(HANDLE hProcess, ULONG64 BaseOfDll,
PSYM_ENUMERATESYMBOLS_CALLBACK
EnumSymbolsCallback
,
PVOID
UserContext
)
{
struct
process
*
pcs
;
struct
module_pair
pair
;
char
buffer
[
sizeof
(
SYMBOL_INFO
)
+
256
];
SYMBOL_INFO
*
sym_info
=
(
SYMBOL_INFO
*
)
buffer
;
...
...
@@ -385,9 +384,9 @@ BOOL WINAPI SymEnumTypes(HANDLE hProcess, ULONG64 BaseOfDll,
hProcess
,
wine_dbgstr_longlong
(
BaseOfDll
),
EnumSymbolsCallback
,
UserContext
);
if
(
!
(
pcs
=
process_find_by_handle
(
hProcess
)))
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pcs
,
BaseOfDll
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
return
FALSE
;
if
(
!
(
p
air
.
p
cs
=
process_find_by_handle
(
hProcess
)))
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
p
air
.
p
cs
,
BaseOfDll
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
return
FALSE
;
sym_info
->
SizeOfStruct
=
sizeof
(
SYMBOL_INFO
);
sym_info
->
MaxNameLen
=
sizeof
(
buffer
)
-
sizeof
(
SYMBOL_INFO
);
...
...
@@ -787,13 +786,13 @@ BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase,
ULONG
TypeId
,
IMAGEHLP_SYMBOL_TYPE_INFO
GetType
,
PVOID
pInfo
)
{
struct
process
*
pcs
=
process_find_by_handle
(
hProcess
);
struct
module_pair
pair
;
if
(
!
pcs
)
return
FALSE
;
pair
.
pcs
=
process_find_by_handle
(
hProcess
);
if
(
!
pair
.
pcs
)
return
FALSE
;
pair
.
requested
=
module_find_by_addr
(
pcs
,
ModBase
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
pcs
,
&
pair
))
pair
.
requested
=
module_find_by_addr
(
p
air
.
p
cs
,
ModBase
,
DMT_UNKNOWN
);
if
(
!
module_get_debug
(
&
pair
))
{
FIXME
(
"Someone didn't properly set ModBase (%s)
\n
"
,
wine_dbgstr_longlong
(
ModBase
));
return
FALSE
;
...
...
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