mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 12:49:45 +00:00
Added a VIRTUAL_alloc_teb function to allocate TEBs while making sure
they don't end up above the address space limit.
This commit is contained in:
parent
b8d0f4cd10
commit
9f32a5c865
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user