Commit 9f32a5c8 authored by Alexandre Julliard's avatar Alexandre Julliard

Added a VIRTUAL_alloc_teb function to allocate TEBs while making sure

they don't end up above the address space limit.
parent b8d0f4cd
......@@ -51,7 +51,6 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl
extern BOOL SIGNAL_Init(void);
extern void debug_init(void);
extern void thread_init(void);
extern void virtual_init(void);
/* server support */
extern time_t server_start_time;
......@@ -90,6 +89,7 @@ extern NTSTATUS FILE_GetNtStatus(void);
extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name );
/* virtual memory */
extern NTSTATUS VIRTUAL_alloc_teb( void **ret, size_t size, BOOL first );
extern NTSTATUS VIRTUAL_HandleFault(LPCVOID addr);
extern BOOL VIRTUAL_HasMapping( LPCVOID addr );
extern void VIRTUAL_UseLargeAddressSpace(void);
......
......@@ -55,29 +55,26 @@ static LIST_ENTRY tls_links;
/***********************************************************************
* alloc_teb
* init_teb
*/
static TEB *alloc_teb( ULONG *size )
static inline NTSTATUS init_teb( TEB *teb )
{
TEB *teb;
struct ntdll_thread_data *thread_data;
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
*size = SIGNAL_STACK_SIZE + sizeof(TEB);
teb = wine_anon_mmap( NULL, *size, PROT_READ | PROT_WRITE, 0 );
if (teb == (TEB *)-1) return NULL;
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
if (!(thread_data->teb_sel = wine_ldt_alloc_fs()))
{
munmap( teb, *size );
return NULL;
}
teb->Tib.ExceptionList = (void *)~0UL;
teb->Tib.StackBase = (void *)~0UL;
teb->Tib.Self = &teb->Tib;
teb->Peb = &peb;
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
return teb;
if (!(thread_data->teb_sel = wine_ldt_alloc_fs())) return STATUS_TOO_MANY_THREADS;
thread_data->request_fd = -1;
thread_data->reply_fd = -1;
thread_data->wait_fd[0] = -1;
thread_data->wait_fd[1] = -1;
return STATUS_SUCCESS;
}
......@@ -107,7 +104,7 @@ void thread_init(void)
{
TEB *teb;
void *addr;
ULONG size, info_size;
ULONG info_size;
struct ntdll_thread_data *thread_data;
struct wine_pthread_thread_info thread_info;
static struct debug_info debug_info; /* debug info for initial thread */
......@@ -127,19 +124,17 @@ void thread_init(void)
InitializeListHead( &ldr.InInitializationOrderModuleList );
InitializeListHead( &tls_links );
teb = alloc_teb( &size );
thread_info.teb_size = SIGNAL_STACK_SIZE + sizeof(TEB);
VIRTUAL_alloc_teb( &addr, thread_info.teb_size, TRUE );
teb = addr;
init_teb( teb );
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
thread_data->request_fd = -1;
thread_data->reply_fd = -1;
thread_data->wait_fd[0] = -1;
thread_data->wait_fd[1] = -1;
thread_data->debug_info = &debug_info;
InsertHeadList( &tls_links, &teb->TlsLinks );
thread_info.stack_base = NULL;
thread_info.stack_size = 0;
thread_info.teb_base = teb;
thread_info.teb_size = size;
thread_info.teb_sel = thread_data->teb_sel;
wine_pthread_init_current_teb( &thread_info );
wine_pthread_init_thread( &thread_info );
......@@ -147,17 +142,11 @@ void thread_init(void)
debug_info.str_pos = debug_info.strings;
debug_info.out_pos = debug_info.output;
debug_init();
virtual_init();
/* setup the server connection */
server_init_process();
info_size = server_init_thread( thread_info.pid, thread_info.tid, NULL );
/* create a memory view for the TEB */
addr = teb;
NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size,
MEM_SYSTEM, PAGE_READWRITE );
/* create the process heap */
if (!(peb.ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL )))
{
......@@ -245,12 +234,12 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
PRTL_THREAD_START_ROUTINE start, void *param,
HANDLE *handle_ptr, CLIENT_ID *id )
{
struct ntdll_thread_data *thread_data;
struct ntdll_thread_data *thread_data = NULL;
struct startup_info *info = NULL;
void *addr;
HANDLE handle = 0;
TEB *teb = NULL;
TEB *teb;
DWORD tid = 0;
ULONG size;
int request_pipe[2];
NTSTATUS status;
......@@ -286,24 +275,18 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
goto error;
}
if (!(teb = alloc_teb( &size )))
{
status = STATUS_NO_MEMORY;
goto error;
}
info->pthread_info.teb_size = SIGNAL_STACK_SIZE + sizeof(TEB);
if ((status = VIRTUAL_alloc_teb( &addr, info->pthread_info.teb_size, FALSE ))) goto error;
teb = addr;
if ((status = init_teb( teb ))) goto error;
teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId();
teb->ClientId.UniqueThread = (HANDLE)tid;
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
thread_data->request_fd = request_pipe[1];
thread_data->reply_fd = -1;
thread_data->wait_fd[0] = -1;
thread_data->wait_fd[1] = -1;
info->pthread_info.teb_base = teb;
NtAllocateVirtualMemory( NtCurrentProcess(), &info->pthread_info.teb_base, 0, &size,
MEM_SYSTEM, PAGE_READWRITE );
info->pthread_info.teb_size = size;
info->pthread_info.teb_sel = thread_data->teb_sel;
if (!stack_reserve || !stack_commit)
......@@ -335,7 +318,12 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
return STATUS_SUCCESS;
error:
if (teb) free_teb( teb );
if (thread_data) wine_ldt_free_fs( thread_data->teb_sel );
if (addr)
{
ULONG size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
}
if (info) RtlFreeHeap( GetProcessHeap(), 0, info );
if (handle) NtClose( handle );
close( request_pipe[1] );
......
......@@ -1081,7 +1081,7 @@ BOOL is_current_process( HANDLE handle )
/***********************************************************************
* virtual_init
*/
void virtual_init(void)
static inline void virtual_init(void)
{
#ifndef page_mask
page_size = getpagesize();
......@@ -1095,6 +1095,51 @@ void virtual_init(void)
/***********************************************************************
* VIRTUAL_alloc_teb
*
* Allocate a memory view for a new TEB. We don't care about granularity for TEBs.
*/
NTSTATUS VIRTUAL_alloc_teb( void **ret, size_t size, BOOL first )
{
void *ptr;
NTSTATUS status;
struct file_view *view;
BYTE vprot = VPROT_READ | VPROT_WRITE | VPROT_COMMITTED;
if (first) virtual_init();
*ret = NULL;
size = ROUND_SIZE( 0, size );
for (;;)
{
if ((ptr = wine_anon_mmap( NULL, size, VIRTUAL_GetUnixProt(vprot), 0 )) == (void *)-1)
{
if (errno == ENOMEM) return STATUS_NO_MEMORY;
return STATUS_INVALID_PARAMETER;
}
/* if we got something beyond the user limit, unmap it and retry */
if (is_beyond_limit( ptr, size, user_space_limit )) add_reserved_area( ptr, size );
else break;
}
if (!first) RtlEnterCriticalSection( &csVirtual );
status = create_view( &view, ptr, size, vprot );
if (status == STATUS_SUCCESS)
{
view->flags |= VFLAG_VALLOC;
*ret = ptr;
}
else unmap_area( ptr, size );
if (!first) RtlLeaveCriticalSection( &csVirtual );
return status;
}
/***********************************************************************
* VIRTUAL_HandleFault
*/
NTSTATUS VIRTUAL_HandleFault( LPCVOID addr )
......@@ -1456,7 +1501,7 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
{
/* make the address space end at the user limit, except if
* the last view was mapped beyond that */
if (alloc_base < (char *)user_space_limit)
if (alloc_base <= (char *)user_space_limit)
{
if (user_space_limit && base >= (char *)user_space_limit)
{
......
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