Skip to content
Snippets Groups Projects
Commit 9f32a5c8 authored by Alexandre Julliard's avatar Alexandre Julliard
Browse files

Added a VIRTUAL_alloc_teb function to allocate TEBs while making sure

they don't end up above the address space limit.
parent b8d0f4cd
No related branches found
No related tags found
No related merge requests found
......@@ -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();
......@@ -1094,6 +1094,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
*/
......@@ -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)
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment