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
911e5084
Commit
911e5084
authored
Sep 09, 2019
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel32: Move process startup information functions to kernelbase.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
3e6b961f
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
151 additions
and
118 deletions
+151
-118
environ.c
dlls/kernel32/environ.c
+0
-104
kernel32.spec
dlls/kernel32/kernel32.spec
+6
-6
kernelbase.h
dlls/kernelbase/kernelbase.h
+1
-0
kernelbase.spec
dlls/kernelbase/kernelbase.spec
+6
-6
main.c
dlls/kernelbase/main.c
+17
-2
process.c
dlls/kernelbase/process.c
+121
-0
No files found.
dlls/kernel32/environ.c
View file @
911e5084
...
@@ -46,84 +46,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(environ);
...
@@ -46,84 +46,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(environ);
* to sort them either.
* to sort them either.
*/
*/
static
STARTUPINFOW
startup_infoW
;
static
STARTUPINFOA
startup_infoA
;
static
STARTUPINFOA
startup_infoA
;
/***********************************************************************
* GetCommandLineA (KERNEL32.@)
*
* WARNING: there's a Windows incompatibility lurking here !
* Win32s always includes the full path of the program file,
* whereas Windows NT only returns the full file path plus arguments
* in case the program has been started with a full path.
* Win9x seems to have inherited NT behaviour.
*
* Note that both Start Menu Execute and Explorer start programs with
* fully specified quoted app file paths, which is why probably the only case
* where you'll see single file names is in case of direct launch
* via CreateProcess or WinExec.
*
* Perhaps we should take care of Win3.1 programs here (Win32s "feature").
*
* References: MS KB article q102762.txt (special Win32s handling)
*/
LPSTR
WINAPI
GetCommandLineA
(
void
)
{
static
char
*
cmdlineA
;
/* ASCII command line */
if
(
!
cmdlineA
)
/* make an ansi version if we don't have it */
{
ANSI_STRING
ansi
;
RtlAcquirePebLock
();
cmdlineA
=
(
RtlUnicodeStringToAnsiString
(
&
ansi
,
&
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
CommandLine
,
TRUE
)
==
STATUS_SUCCESS
)
?
ansi
.
Buffer
:
NULL
;
RtlReleasePebLock
();
}
return
cmdlineA
;
}
/***********************************************************************
* GetCommandLineW (KERNEL32.@)
*/
LPWSTR
WINAPI
GetCommandLineW
(
void
)
{
return
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
CommandLine
.
Buffer
;
}
/***********************************************************************
* GetStdHandle (KERNEL32.@)
*/
HANDLE
WINAPI
GetStdHandle
(
DWORD
std_handle
)
{
switch
(
std_handle
)
{
case
STD_INPUT_HANDLE
:
return
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdInput
;
case
STD_OUTPUT_HANDLE
:
return
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdOutput
;
case
STD_ERROR_HANDLE
:
return
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdError
;
}
SetLastError
(
ERROR_INVALID_HANDLE
);
return
INVALID_HANDLE_VALUE
;
}
/***********************************************************************
* SetStdHandle (KERNEL32.@)
*/
BOOL
WINAPI
SetStdHandle
(
DWORD
std_handle
,
HANDLE
handle
)
{
switch
(
std_handle
)
{
case
STD_INPUT_HANDLE
:
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdInput
=
handle
;
return
TRUE
;
case
STD_OUTPUT_HANDLE
:
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdOutput
=
handle
;
return
TRUE
;
case
STD_ERROR_HANDLE
:
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdError
=
handle
;
return
TRUE
;
}
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
/***********************************************************************
/***********************************************************************
* GetStartupInfoA (KERNEL32.@)
* GetStartupInfoA (KERNEL32.@)
*/
*/
...
@@ -132,15 +56,6 @@ VOID WINAPI GetStartupInfoA( LPSTARTUPINFOA info )
...
@@ -132,15 +56,6 @@ VOID WINAPI GetStartupInfoA( LPSTARTUPINFOA info )
*
info
=
startup_infoA
;
*
info
=
startup_infoA
;
}
}
/***********************************************************************
* GetStartupInfoW (KERNEL32.@)
*/
VOID
WINAPI
GetStartupInfoW
(
LPSTARTUPINFOW
info
)
{
*
info
=
startup_infoW
;
}
/******************************************************************
/******************************************************************
* ENV_CopyStartupInformation (internal)
* ENV_CopyStartupInformation (internal)
*
*
...
@@ -155,25 +70,6 @@ void ENV_CopyStartupInformation(void)
...
@@ -155,25 +70,6 @@ void ENV_CopyStartupInformation(void)
rupp
=
NtCurrentTeb
()
->
Peb
->
ProcessParameters
;
rupp
=
NtCurrentTeb
()
->
Peb
->
ProcessParameters
;
startup_infoW
.
cb
=
sizeof
(
startup_infoW
);
startup_infoW
.
lpReserved
=
NULL
;
startup_infoW
.
lpDesktop
=
rupp
->
Desktop
.
Buffer
;
startup_infoW
.
lpTitle
=
rupp
->
WindowTitle
.
Buffer
;
startup_infoW
.
dwX
=
rupp
->
dwX
;
startup_infoW
.
dwY
=
rupp
->
dwY
;
startup_infoW
.
dwXSize
=
rupp
->
dwXSize
;
startup_infoW
.
dwYSize
=
rupp
->
dwYSize
;
startup_infoW
.
dwXCountChars
=
rupp
->
dwXCountChars
;
startup_infoW
.
dwYCountChars
=
rupp
->
dwYCountChars
;
startup_infoW
.
dwFillAttribute
=
rupp
->
dwFillAttribute
;
startup_infoW
.
dwFlags
=
rupp
->
dwFlags
;
startup_infoW
.
wShowWindow
=
rupp
->
wShowWindow
;
startup_infoW
.
cbReserved2
=
rupp
->
RuntimeInfo
.
MaximumLength
;
startup_infoW
.
lpReserved2
=
rupp
->
RuntimeInfo
.
MaximumLength
?
(
void
*
)
rupp
->
RuntimeInfo
.
Buffer
:
NULL
;
startup_infoW
.
hStdInput
=
rupp
->
hStdInput
?
rupp
->
hStdInput
:
INVALID_HANDLE_VALUE
;
startup_infoW
.
hStdOutput
=
rupp
->
hStdOutput
?
rupp
->
hStdOutput
:
INVALID_HANDLE_VALUE
;
startup_infoW
.
hStdError
=
rupp
->
hStdError
?
rupp
->
hStdError
:
INVALID_HANDLE_VALUE
;
startup_infoA
.
cb
=
sizeof
(
startup_infoA
);
startup_infoA
.
cb
=
sizeof
(
startup_infoA
);
startup_infoA
.
lpReserved
=
NULL
;
startup_infoA
.
lpReserved
=
NULL
;
startup_infoA
.
lpDesktop
=
RtlUnicodeStringToAnsiString
(
&
ansi
,
&
rupp
->
Desktop
,
TRUE
)
==
STATUS_SUCCESS
?
startup_infoA
.
lpDesktop
=
RtlUnicodeStringToAnsiString
(
&
ansi
,
&
rupp
->
Desktop
,
TRUE
)
==
STATUS_SUCCESS
?
...
...
dlls/kernel32/kernel32.spec
View file @
911e5084
...
@@ -568,8 +568,8 @@
...
@@ -568,8 +568,8 @@
@ stdcall GetCommProperties(long ptr)
@ stdcall GetCommProperties(long ptr)
@ stdcall GetCommState(long ptr)
@ stdcall GetCommState(long ptr)
@ stdcall GetCommTimeouts(long ptr)
@ stdcall GetCommTimeouts(long ptr)
@ stdcall GetCommandLineA()
@ stdcall
-import
GetCommandLineA()
@ stdcall GetCommandLineW()
@ stdcall
-import
GetCommandLineW()
@ stdcall -import GetCompressedFileSizeA(long ptr)
@ stdcall -import GetCompressedFileSizeA(long ptr)
# @ stub GetCompressedFileSizeTransactedA
# @ stub GetCompressedFileSizeTransactedA
# @ stub GetCompressedFileSizeTransactedW
# @ stub GetCompressedFileSizeTransactedW
...
@@ -810,8 +810,8 @@
...
@@ -810,8 +810,8 @@
@ stdcall GetShortPathNameA(str ptr long)
@ stdcall GetShortPathNameA(str ptr long)
@ stdcall GetShortPathNameW(wstr ptr long)
@ stdcall GetShortPathNameW(wstr ptr long)
@ stdcall GetStartupInfoA(ptr)
@ stdcall GetStartupInfoA(ptr)
@ stdcall GetStartupInfoW(ptr)
@ stdcall
-import
GetStartupInfoW(ptr)
@ stdcall GetStdHandle(long)
@ stdcall
-import
GetStdHandle(long)
# @ stub GetStringScripts
# @ stub GetStringScripts
@ stdcall GetStringTypeA(long long str long ptr)
@ stdcall GetStringTypeA(long long str long ptr)
@ stdcall GetStringTypeExA(long long str long ptr)
@ stdcall GetStringTypeExA(long long str long ptr)
...
@@ -1436,8 +1436,8 @@
...
@@ -1436,8 +1436,8 @@
@ stdcall SetProcessWorkingSetSize(long long long)
@ stdcall SetProcessWorkingSetSize(long long long)
@ stdcall -import SetProcessWorkingSetSizeEx(long long long long)
@ stdcall -import SetProcessWorkingSetSizeEx(long long long long)
@ stdcall SetSearchPathMode(long)
@ stdcall SetSearchPathMode(long)
@ stdcall SetStdHandle(long long)
@ stdcall
-import
SetStdHandle(long long)
# @ stub SetStdHandleEx
@ stdcall -import SetStdHandleEx(long long ptr)
@ stdcall SetSystemFileCacheSize(long long long)
@ stdcall SetSystemFileCacheSize(long long long)
@ stdcall SetSystemPowerState(long long)
@ stdcall SetSystemPowerState(long long)
@ stdcall SetSystemTime(ptr)
@ stdcall SetSystemTime(ptr)
...
...
dlls/kernelbase/kernelbase.h
View file @
911e5084
...
@@ -26,6 +26,7 @@
...
@@ -26,6 +26,7 @@
extern
WCHAR
*
file_name_AtoW
(
LPCSTR
name
,
BOOL
alloc
)
DECLSPEC_HIDDEN
;
extern
WCHAR
*
file_name_AtoW
(
LPCSTR
name
,
BOOL
alloc
)
DECLSPEC_HIDDEN
;
extern
DWORD
file_name_WtoA
(
LPCWSTR
src
,
INT
srclen
,
LPSTR
dest
,
INT
destlen
)
DECLSPEC_HIDDEN
;
extern
DWORD
file_name_WtoA
(
LPCWSTR
src
,
INT
srclen
,
LPSTR
dest
,
INT
destlen
)
DECLSPEC_HIDDEN
;
extern
void
init_startup_info
(
RTL_USER_PROCESS_PARAMETERS
*
params
)
DECLSPEC_HIDDEN
;
extern
const
WCHAR
windows_dir
[]
DECLSPEC_HIDDEN
;
extern
const
WCHAR
windows_dir
[]
DECLSPEC_HIDDEN
;
extern
const
WCHAR
system_dir
[]
DECLSPEC_HIDDEN
;
extern
const
WCHAR
system_dir
[]
DECLSPEC_HIDDEN
;
...
...
dlls/kernelbase/kernelbase.spec
View file @
911e5084
...
@@ -433,8 +433,8 @@
...
@@ -433,8 +433,8 @@
@ stdcall GetCommProperties(long ptr) kernel32.GetCommProperties
@ stdcall GetCommProperties(long ptr) kernel32.GetCommProperties
@ stdcall GetCommState(long ptr) kernel32.GetCommState
@ stdcall GetCommState(long ptr) kernel32.GetCommState
@ stdcall GetCommTimeouts(long ptr) kernel32.GetCommTimeouts
@ stdcall GetCommTimeouts(long ptr) kernel32.GetCommTimeouts
@ stdcall GetCommandLineA()
kernel32.GetCommandLineA
@ stdcall GetCommandLineA()
@ stdcall GetCommandLineW()
kernel32.GetCommandLineW
@ stdcall GetCommandLineW()
@ stdcall GetCompressedFileSizeA(long ptr)
@ stdcall GetCompressedFileSizeA(long ptr)
@ stdcall GetCompressedFileSizeW(long ptr)
@ stdcall GetCompressedFileSizeW(long ptr)
@ stdcall GetComputerNameExA(long ptr ptr) kernel32.GetComputerNameExA
@ stdcall GetComputerNameExA(long ptr ptr) kernel32.GetComputerNameExA
...
@@ -665,14 +665,14 @@
...
@@ -665,14 +665,14 @@
@ stdcall GetSidSubAuthorityCount(ptr)
@ stdcall GetSidSubAuthorityCount(ptr)
# @ stub GetStagedPackageOrigin
# @ stub GetStagedPackageOrigin
# @ stub GetStagedPackagePathByFullName
# @ stub GetStagedPackagePathByFullName
@ stdcall GetStartupInfoW(ptr)
kernel32.GetStartupInfoW
@ stdcall GetStartupInfoW(ptr)
# @ stub GetStateContainerDepth
# @ stub GetStateContainerDepth
# @ stub GetStateFolder
# @ stub GetStateFolder
# @ stub GetStateRootFolder
# @ stub GetStateRootFolder
# @ stub GetStateRootFolderBase
# @ stub GetStateRootFolderBase
# @ stub GetStateSettingsFolder
# @ stub GetStateSettingsFolder
# @ stub GetStateVersion
# @ stub GetStateVersion
@ stdcall GetStdHandle(long)
kernel32.GetStdHandle
@ stdcall GetStdHandle(long)
# @ stub GetStringScripts
# @ stub GetStringScripts
@ stub GetStringTableEntry
@ stub GetStringTableEntry
@ stdcall GetStringTypeA(long long str long ptr) kernel32.GetStringTypeA
@ stdcall GetStringTypeA(long long str long ptr) kernel32.GetStringTypeA
...
@@ -1473,8 +1473,8 @@
...
@@ -1473,8 +1473,8 @@
@ stub SetSecurityDescriptorRMControl
@ stub SetSecurityDescriptorRMControl
@ stdcall SetSecurityDescriptorSacl(ptr long ptr long)
@ stdcall SetSecurityDescriptorSacl(ptr long ptr long)
# @ stub SetStateVersion
# @ stub SetStateVersion
@ stdcall SetStdHandle(long long)
kernel32.SetStdHandle
@ stdcall SetStdHandle(long long)
@ st
ub SetStdHandleEx
@ st
dcall SetStdHandleEx(long long ptr)
@ stdcall SetSystemFileCacheSize(long long long) kernel32.SetSystemFileCacheSize
@ stdcall SetSystemFileCacheSize(long long long) kernel32.SetSystemFileCacheSize
@ stdcall SetSystemTime(ptr) kernel32.SetSystemTime
@ stdcall SetSystemTime(ptr) kernel32.SetSystemTime
@ stdcall SetSystemTimeAdjustment(long long) kernel32.SetSystemTimeAdjustment
@ stdcall SetSystemTimeAdjustment(long long) kernel32.SetSystemTimeAdjustment
...
...
dlls/kernelbase/main.c
View file @
911e5084
...
@@ -25,20 +25,35 @@
...
@@ -25,20 +25,35 @@
#include "appmodel.h"
#include "appmodel.h"
#include "shlwapi.h"
#include "shlwapi.h"
#include "perflib.h"
#include "perflib.h"
#include "winternl.h"
#include "wine/debug.h"
#include "wine/debug.h"
#include "wine/heap.h"
#include "wine/heap.h"
#include "
winternl
.h"
#include "
kernelbase
.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
kernelbase
);
WINE_DEFAULT_DEBUG_CHANNEL
(
kernelbase
);
/***********************************************************************
* DllMain
*/
BOOL
WINAPI
DllMain
(
HINSTANCE
hinst
,
DWORD
reason
,
LPVOID
reserved
)
{
if
(
reason
==
DLL_PROCESS_ATTACH
)
{
DisableThreadLibraryCalls
(
hinst
);
init_startup_info
(
NtCurrentTeb
()
->
Peb
->
ProcessParameters
);
}
return
TRUE
;
}
/*************************************************************
/*************************************************************
* DllMainCRTStartup
* DllMainCRTStartup
*/
*/
BOOL
WINAPI
DllMainCRTStartup
(
HANDLE
inst
,
DWORD
reason
,
LPVOID
reserved
)
BOOL
WINAPI
DllMainCRTStartup
(
HANDLE
inst
,
DWORD
reason
,
LPVOID
reserved
)
{
{
return
TRUE
;
return
DllMain
(
inst
,
reason
,
reserved
)
;
}
}
...
...
dlls/kernelbase/process.c
View file @
911e5084
...
@@ -347,6 +347,127 @@ BOOL WINAPI DECLSPEC_HOTPATCH TerminateProcess( HANDLE handle, DWORD exit_code )
...
@@ -347,6 +347,127 @@ BOOL WINAPI DECLSPEC_HOTPATCH TerminateProcess( HANDLE handle, DWORD exit_code )
/***********************************************************************
/***********************************************************************
* Process startup information
***********************************************************************/
static
STARTUPINFOW
startup_infoW
;
static
char
*
command_lineA
;
static
WCHAR
*
command_lineW
;
/******************************************************************
* init_startup_info
*/
void
init_startup_info
(
RTL_USER_PROCESS_PARAMETERS
*
params
)
{
ANSI_STRING
ansi
;
startup_infoW
.
cb
=
sizeof
(
startup_infoW
);
startup_infoW
.
lpReserved
=
NULL
;
startup_infoW
.
lpDesktop
=
params
->
Desktop
.
Buffer
;
startup_infoW
.
lpTitle
=
params
->
WindowTitle
.
Buffer
;
startup_infoW
.
dwX
=
params
->
dwX
;
startup_infoW
.
dwY
=
params
->
dwY
;
startup_infoW
.
dwXSize
=
params
->
dwXSize
;
startup_infoW
.
dwYSize
=
params
->
dwYSize
;
startup_infoW
.
dwXCountChars
=
params
->
dwXCountChars
;
startup_infoW
.
dwYCountChars
=
params
->
dwYCountChars
;
startup_infoW
.
dwFillAttribute
=
params
->
dwFillAttribute
;
startup_infoW
.
dwFlags
=
params
->
dwFlags
;
startup_infoW
.
wShowWindow
=
params
->
wShowWindow
;
startup_infoW
.
cbReserved2
=
params
->
RuntimeInfo
.
MaximumLength
;
startup_infoW
.
lpReserved2
=
params
->
RuntimeInfo
.
MaximumLength
?
(
void
*
)
params
->
RuntimeInfo
.
Buffer
:
NULL
;
startup_infoW
.
hStdInput
=
params
->
hStdInput
?
params
->
hStdInput
:
INVALID_HANDLE_VALUE
;
startup_infoW
.
hStdOutput
=
params
->
hStdOutput
?
params
->
hStdOutput
:
INVALID_HANDLE_VALUE
;
startup_infoW
.
hStdError
=
params
->
hStdError
?
params
->
hStdError
:
INVALID_HANDLE_VALUE
;
command_lineW
=
params
->
CommandLine
.
Buffer
;
if
(
!
RtlUnicodeStringToAnsiString
(
&
ansi
,
&
params
->
CommandLine
,
TRUE
))
command_lineA
=
ansi
.
Buffer
;
}
/***********************************************************************
* GetCommandLineA (kernelbase.@)
*/
LPSTR
WINAPI
DECLSPEC_HOTPATCH
GetCommandLineA
(
void
)
{
return
command_lineA
;
}
/***********************************************************************
* GetCommandLineW (kernelbase.@)
*/
LPWSTR
WINAPI
DECLSPEC_HOTPATCH
GetCommandLineW
(
void
)
{
return
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
CommandLine
.
Buffer
;
}
/***********************************************************************
* GetStartupInfoW (kernelbase.@)
*/
void
WINAPI
DECLSPEC_HOTPATCH
GetStartupInfoW
(
STARTUPINFOW
*
info
)
{
*
info
=
startup_infoW
;
}
/***********************************************************************
* GetStdHandle (kernelbase.@)
*/
HANDLE
WINAPI
DECLSPEC_HOTPATCH
GetStdHandle
(
DWORD
std_handle
)
{
switch
(
std_handle
)
{
case
STD_INPUT_HANDLE
:
return
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdInput
;
case
STD_OUTPUT_HANDLE
:
return
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdOutput
;
case
STD_ERROR_HANDLE
:
return
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdError
;
}
SetLastError
(
ERROR_INVALID_HANDLE
);
return
INVALID_HANDLE_VALUE
;
}
/***********************************************************************
* SetStdHandle (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
SetStdHandle
(
DWORD
std_handle
,
HANDLE
handle
)
{
switch
(
std_handle
)
{
case
STD_INPUT_HANDLE
:
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdInput
=
handle
;
return
TRUE
;
case
STD_OUTPUT_HANDLE
:
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdOutput
=
handle
;
return
TRUE
;
case
STD_ERROR_HANDLE
:
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdError
=
handle
;
return
TRUE
;
}
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
/***********************************************************************
* SetStdHandleEx (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
SetStdHandleEx
(
DWORD
std_handle
,
HANDLE
handle
,
HANDLE
*
prev
)
{
HANDLE
*
ptr
;
switch
(
std_handle
)
{
case
STD_INPUT_HANDLE
:
ptr
=
&
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdInput
;
break
;
case
STD_OUTPUT_HANDLE
:
ptr
=
&
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdOutput
;
break
;
case
STD_ERROR_HANDLE
:
ptr
=
&
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdError
;
break
;
default:
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
if
(
prev
)
*
prev
=
*
ptr
;
*
ptr
=
handle
;
return
TRUE
;
}
/***********************************************************************
* Process environment
* Process environment
***********************************************************************/
***********************************************************************/
...
...
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