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 BOOL SIGNAL_Init(void);
|
||||||
extern void debug_init(void);
|
extern void debug_init(void);
|
||||||
extern void thread_init(void);
|
extern void thread_init(void);
|
||||||
extern void virtual_init(void);
|
|
||||||
|
|
||||||
/* server support */
|
/* server support */
|
||||||
extern time_t server_start_time;
|
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 );
|
extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name );
|
||||||
|
|
||||||
/* virtual memory */
|
/* virtual memory */
|
||||||
|
extern NTSTATUS VIRTUAL_alloc_teb( void **ret, size_t size, BOOL first );
|
||||||
extern NTSTATUS VIRTUAL_HandleFault(LPCVOID addr);
|
extern NTSTATUS VIRTUAL_HandleFault(LPCVOID addr);
|
||||||
extern BOOL VIRTUAL_HasMapping( LPCVOID addr );
|
extern BOOL VIRTUAL_HasMapping( LPCVOID addr );
|
||||||
extern void VIRTUAL_UseLargeAddressSpace(void);
|
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 *)teb->SystemReserved2;
|
||||||
struct ntdll_thread_data *thread_data;
|
|
||||||
|
|
||||||
*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.ExceptionList = (void *)~0UL;
|
||||||
teb->Tib.StackBase = (void *)~0UL;
|
teb->Tib.StackBase = (void *)~0UL;
|
||||||
teb->Tib.Self = &teb->Tib;
|
teb->Tib.Self = &teb->Tib;
|
||||||
teb->Peb = &peb;
|
teb->Peb = &peb;
|
||||||
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
|
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
|
||||||
teb->StaticUnicodeString.MaximumLength = sizeof(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;
|
TEB *teb;
|
||||||
void *addr;
|
void *addr;
|
||||||
ULONG size, info_size;
|
ULONG info_size;
|
||||||
struct ntdll_thread_data *thread_data;
|
struct ntdll_thread_data *thread_data;
|
||||||
struct wine_pthread_thread_info thread_info;
|
struct wine_pthread_thread_info thread_info;
|
||||||
static struct debug_info debug_info; /* debug info for initial thread */
|
static struct debug_info debug_info; /* debug info for initial thread */
|
||||||
|
@ -127,19 +124,17 @@ void thread_init(void)
|
||||||
InitializeListHead( &ldr.InInitializationOrderModuleList );
|
InitializeListHead( &ldr.InInitializationOrderModuleList );
|
||||||
InitializeListHead( &tls_links );
|
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 = (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;
|
thread_data->debug_info = &debug_info;
|
||||||
InsertHeadList( &tls_links, &teb->TlsLinks );
|
InsertHeadList( &tls_links, &teb->TlsLinks );
|
||||||
|
|
||||||
thread_info.stack_base = NULL;
|
thread_info.stack_base = NULL;
|
||||||
thread_info.stack_size = 0;
|
thread_info.stack_size = 0;
|
||||||
thread_info.teb_base = teb;
|
thread_info.teb_base = teb;
|
||||||
thread_info.teb_size = size;
|
|
||||||
thread_info.teb_sel = thread_data->teb_sel;
|
thread_info.teb_sel = thread_data->teb_sel;
|
||||||
wine_pthread_init_current_teb( &thread_info );
|
wine_pthread_init_current_teb( &thread_info );
|
||||||
wine_pthread_init_thread( &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.str_pos = debug_info.strings;
|
||||||
debug_info.out_pos = debug_info.output;
|
debug_info.out_pos = debug_info.output;
|
||||||
debug_init();
|
debug_init();
|
||||||
virtual_init();
|
|
||||||
|
|
||||||
/* setup the server connection */
|
/* setup the server connection */
|
||||||
server_init_process();
|
server_init_process();
|
||||||
info_size = server_init_thread( thread_info.pid, thread_info.tid, NULL );
|
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 */
|
/* create the process heap */
|
||||||
if (!(peb.ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL )))
|
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,
|
PRTL_THREAD_START_ROUTINE start, void *param,
|
||||||
HANDLE *handle_ptr, CLIENT_ID *id )
|
HANDLE *handle_ptr, CLIENT_ID *id )
|
||||||
{
|
{
|
||||||
struct ntdll_thread_data *thread_data;
|
struct ntdll_thread_data *thread_data = NULL;
|
||||||
struct startup_info *info = NULL;
|
struct startup_info *info = NULL;
|
||||||
|
void *addr;
|
||||||
HANDLE handle = 0;
|
HANDLE handle = 0;
|
||||||
TEB *teb = NULL;
|
TEB *teb;
|
||||||
DWORD tid = 0;
|
DWORD tid = 0;
|
||||||
ULONG size;
|
|
||||||
int request_pipe[2];
|
int request_pipe[2];
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
|
@ -286,24 +275,18 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(teb = alloc_teb( &size )))
|
info->pthread_info.teb_size = SIGNAL_STACK_SIZE + sizeof(TEB);
|
||||||
{
|
if ((status = VIRTUAL_alloc_teb( &addr, info->pthread_info.teb_size, FALSE ))) goto error;
|
||||||
status = STATUS_NO_MEMORY;
|
teb = addr;
|
||||||
goto error;
|
if ((status = init_teb( teb ))) goto error;
|
||||||
}
|
|
||||||
teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId();
|
teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId();
|
||||||
teb->ClientId.UniqueThread = (HANDLE)tid;
|
teb->ClientId.UniqueThread = (HANDLE)tid;
|
||||||
|
|
||||||
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
|
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
|
||||||
thread_data->request_fd = request_pipe[1];
|
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;
|
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;
|
info->pthread_info.teb_sel = thread_data->teb_sel;
|
||||||
|
|
||||||
if (!stack_reserve || !stack_commit)
|
if (!stack_reserve || !stack_commit)
|
||||||
|
@ -335,7 +318,12 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
error:
|
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 (info) RtlFreeHeap( GetProcessHeap(), 0, info );
|
||||||
if (handle) NtClose( handle );
|
if (handle) NtClose( handle );
|
||||||
close( request_pipe[1] );
|
close( request_pipe[1] );
|
||||||
|
|
|
@ -1081,7 +1081,7 @@ BOOL is_current_process( HANDLE handle )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* virtual_init
|
* virtual_init
|
||||||
*/
|
*/
|
||||||
void virtual_init(void)
|
static inline void virtual_init(void)
|
||||||
{
|
{
|
||||||
#ifndef page_mask
|
#ifndef page_mask
|
||||||
page_size = getpagesize();
|
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
|
* VIRTUAL_HandleFault
|
||||||
*/
|
*/
|
||||||
|
@ -1456,7 +1501,7 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
|
||||||
{
|
{
|
||||||
/* make the address space end at the user limit, except if
|
/* make the address space end at the user limit, except if
|
||||||
* the last view was mapped beyond that */
|
* 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)
|
if (user_space_limit && base >= (char *)user_space_limit)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue