ntdll: Create user shared data section in the server, and initialize it in wineboot.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-05-29 12:26:57 +02:00
parent 42bd67b576
commit e854ea34cc
13 changed files with 128 additions and 130 deletions

View File

@ -4397,6 +4397,7 @@ void __wine_process_init(void)
FILE_umask = umask(0777);
umask( FILE_umask );
map_user_shared_data();
load_global_options();
version_init();

View File

@ -221,7 +221,7 @@ extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN;
extern void virtual_fill_image_information( const pe_image_info_t *pe_info,
SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN;
extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN;
extern HANDLE user_shared_data_init_done(void) DECLSPEC_HIDDEN;
extern void map_user_shared_data(void) DECLSPEC_HIDDEN;
/* completion */
extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue,

View File

@ -1529,7 +1529,6 @@ void server_init_process_done(void)
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress );
void *entry = (char *)peb->ImageBaseAddress + nt->OptionalHeader.AddressOfEntryPoint;
NTSTATUS status;
HANDLE usd_handle = user_shared_data_init_done();
int suspend;
#ifdef __APPLE__
@ -1553,12 +1552,10 @@ void server_init_process_done(void)
#endif
req->entry = wine_server_client_ptr( entry );
req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI);
req->usd_handle = wine_server_obj_handle( usd_handle );
status = wine_server_call( req );
suspend = reply->suspend;
}
SERVER_END_REQ;
NtClose( usd_handle );
assert( !status );
signal_start_process( entry, suspend );

View File

@ -182,106 +182,23 @@ int __cdecl __wine_dbg_output( const char *str )
return unix_funcs->dbg_output( str );
}
static void fill_user_shared_data( struct _KUSER_SHARED_DATA *data )
{
RTL_OSVERSIONINFOEXW version;
SYSTEM_CPU_INFORMATION sci;
SYSTEM_BASIC_INFORMATION sbi;
BOOLEAN *features = data->ProcessorFeatures;
version.dwOSVersionInfoSize = sizeof(version);
RtlGetVersion( &version );
virtual_get_system_info( &sbi );
NtQuerySystemInformation( SystemCpuInformation, &sci, sizeof(sci), NULL );
data->TickCountMultiplier = 1 << 24;
data->LargePageMinimum = 2 * 1024 * 1024;
data->NtBuildNumber = version.dwBuildNumber;
data->NtProductType = version.wProductType;
data->ProductTypeIsValid = TRUE;
data->NativeProcessorArchitecture = sci.Architecture;
data->NtMajorVersion = version.dwMajorVersion;
data->NtMinorVersion = version.dwMinorVersion;
data->SuiteMask = version.wSuiteMask;
data->NumberOfPhysicalPages = sbi.MmNumberOfPhysicalPages;
wcscpy( data->NtSystemRoot, windows_dir );
switch (sci.Architecture)
{
case PROCESSOR_ARCHITECTURE_INTEL:
case PROCESSOR_ARCHITECTURE_AMD64:
features[PF_COMPARE_EXCHANGE_DOUBLE] = !!(sci.FeatureSet & CPU_FEATURE_CX8);
features[PF_MMX_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_MMX);
features[PF_XMMI_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_SSE);
features[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_3DNOW);
features[PF_RDTSC_INSTRUCTION_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_TSC);
features[PF_PAE_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_PAE);
features[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_SSE2);
features[PF_SSE3_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_SSE3);
features[PF_XSAVE_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_XSAVE);
features[PF_COMPARE_EXCHANGE128] = !!(sci.FeatureSet & CPU_FEATURE_CX128);
features[PF_SSE_DAZ_MODE_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_DAZ);
features[PF_NX_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_NX);
features[PF_SECOND_LEVEL_ADDRESS_TRANSLATION] = !!(sci.FeatureSet & CPU_FEATURE_2NDLEV);
features[PF_VIRT_FIRMWARE_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_VIRT);
features[PF_RDWRFSGSBASE_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_RDFS);
features[PF_FASTFAIL_AVAILABLE] = TRUE;
break;
case PROCESSOR_ARCHITECTURE_ARM:
features[PF_ARM_VFP_32_REGISTERS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_VFP_32);
features[PF_ARM_NEON_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_NEON);
features[PF_ARM_V8_INSTRUCTIONS_AVAILABLE] = (sci.Level >= 8);
break;
case PROCESSOR_ARCHITECTURE_ARM64:
features[PF_ARM_V8_INSTRUCTIONS_AVAILABLE] = TRUE;
features[PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_V8_CRC32);
features[PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_V8_CRYPTO);
break;
}
data->ActiveProcessorCount = NtCurrentTeb()->Peb->NumberOfProcessors;
data->ActiveGroupCount = 1;
}
HANDLE user_shared_data_init_done(void)
void map_user_shared_data(void)
{
static const WCHAR wine_usdW[] = {'\\','K','e','r','n','e','l','O','b','j','e','c','t','s',
'\\','_','_','w','i','n','e','_','u','s','e','r','_','s','h','a','r','e','d','_','d','a','t','a',0};
OBJECT_ATTRIBUTES attr = {sizeof(attr)};
UNICODE_STRING wine_usd_str;
LARGE_INTEGER section_size;
NTSTATUS status;
HANDLE section;
SIZE_T size;
void *addr;
int res, fd, needs_close;
section_size.QuadPart = sizeof(*user_shared_data);
RtlInitUnicodeString( &wine_usd_str, wine_usdW );
InitializeObjectAttributes( &attr, &wine_usd_str, OBJ_OPENIF, NULL, NULL );
if ((status = NtCreateSection( &section, SECTION_ALL_ACCESS, &attr,
&section_size, PAGE_READWRITE, SEC_COMMIT, NULL )) &&
status != STATUS_OBJECT_NAME_EXISTS)
if ((status = NtOpenSection( &section, SECTION_ALL_ACCESS, &attr )))
{
MESSAGE( "wine: failed to create or open the USD section: %08x\n", status );
MESSAGE( "wine: failed to open the USD section: %08x\n", status );
exit(1);
}
if (status != STATUS_OBJECT_NAME_EXISTS)
{
addr = NULL;
size = sizeof(*user_shared_data);
if ((status = NtMapViewOfSection( section, NtCurrentProcess(), &addr, 0, 0, 0,
&size, 0, 0, PAGE_READWRITE )))
{
MESSAGE( "wine: failed to initialize the USD section: %08x\n", status );
exit(1);
}
fill_user_shared_data( addr );
NtUnmapViewOfSection( NtCurrentProcess(), addr );
}
if ((res = server_get_unix_fd( section, 0, &fd, &needs_close, NULL, NULL )) ||
(user_shared_data != mmap( user_shared_data, sizeof(*user_shared_data),
PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0 )))
@ -290,8 +207,7 @@ HANDLE user_shared_data_init_done(void)
exit(1);
}
if (needs_close) close( fd );
return section;
NtClose( section );
}
/***********************************************************************

View File

@ -872,8 +872,6 @@ struct init_process_done_request
mod_handle_t module;
client_ptr_t ldt_copy;
client_ptr_t entry;
obj_handle_t usd_handle;
char __pad_44[4];
};
struct init_process_done_reply
{
@ -6685,7 +6683,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 605
#define SERVER_PROTOCOL_VERSION 606
/* ### protocol_version end ### */

View File

@ -60,8 +60,12 @@
#include <intrin.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ntstatus.h>
#define WIN32_NO_STATUS
#include <windows.h>
#include <winternl.h>
#include <ddk/wdm.h>
#include <sddl.h>
#include <wine/svcctl.h>
#include <wine/asm.h>
@ -187,6 +191,89 @@ static DWORD set_reg_value_dword( HKEY hkey, const WCHAR *name, DWORD value )
return RegSetValueExW( hkey, name, 0, REG_DWORD, (const BYTE *)&value, sizeof(value) );
}
static void create_user_shared_data(void)
{
struct _KUSER_SHARED_DATA *data;
RTL_OSVERSIONINFOEXW version;
SYSTEM_CPU_INFORMATION sci;
SYSTEM_BASIC_INFORMATION sbi;
BOOLEAN *features;
OBJECT_ATTRIBUTES attr = {sizeof(attr)};
UNICODE_STRING name;
NTSTATUS status;
HANDLE handle;
RtlInitUnicodeString( &name, L"\\KernelObjects\\__wine_user_shared_data" );
InitializeObjectAttributes( &attr, &name, OBJ_OPENIF, NULL, NULL );
if ((status = NtOpenSection( &handle, SECTION_ALL_ACCESS, &attr )))
{
ERR( "cannot open __wine_user_shared_data: %x\n", status );
return;
}
data = MapViewOfFile( handle, FILE_MAP_WRITE, 0, 0, sizeof(*data) );
CloseHandle( handle );
if (!data)
{
ERR( "cannot map __wine_user_shared_data\n" );
return;
}
version.dwOSVersionInfoSize = sizeof(version);
RtlGetVersion( &version );
NtQuerySystemInformation( SystemBasicInformation, &sbi, sizeof(sbi), NULL );
NtQuerySystemInformation( SystemCpuInformation, &sci, sizeof(sci), NULL );
data->TickCountMultiplier = 1 << 24;
data->LargePageMinimum = 2 * 1024 * 1024;
data->NtBuildNumber = version.dwBuildNumber;
data->NtProductType = version.wProductType;
data->ProductTypeIsValid = TRUE;
data->NativeProcessorArchitecture = sci.Architecture;
data->NtMajorVersion = version.dwMajorVersion;
data->NtMinorVersion = version.dwMinorVersion;
data->SuiteMask = version.wSuiteMask;
data->NumberOfPhysicalPages = sbi.MmNumberOfPhysicalPages;
wcscpy( data->NtSystemRoot, L"C:\\windows" );
features = data->ProcessorFeatures;
switch (sci.Architecture)
{
case PROCESSOR_ARCHITECTURE_INTEL:
case PROCESSOR_ARCHITECTURE_AMD64:
features[PF_COMPARE_EXCHANGE_DOUBLE] = !!(sci.FeatureSet & CPU_FEATURE_CX8);
features[PF_MMX_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_MMX);
features[PF_XMMI_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_SSE);
features[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_3DNOW);
features[PF_RDTSC_INSTRUCTION_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_TSC);
features[PF_PAE_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_PAE);
features[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_SSE2);
features[PF_SSE3_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_SSE3);
features[PF_XSAVE_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_XSAVE);
features[PF_COMPARE_EXCHANGE128] = !!(sci.FeatureSet & CPU_FEATURE_CX128);
features[PF_SSE_DAZ_MODE_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_DAZ);
features[PF_NX_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_NX);
features[PF_SECOND_LEVEL_ADDRESS_TRANSLATION] = !!(sci.FeatureSet & CPU_FEATURE_2NDLEV);
features[PF_VIRT_FIRMWARE_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_VIRT);
features[PF_RDWRFSGSBASE_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_RDFS);
features[PF_FASTFAIL_AVAILABLE] = TRUE;
break;
case PROCESSOR_ARCHITECTURE_ARM:
features[PF_ARM_VFP_32_REGISTERS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_VFP_32);
features[PF_ARM_NEON_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_NEON);
features[PF_ARM_V8_INSTRUCTIONS_AVAILABLE] = (sci.Level >= 8);
break;
case PROCESSOR_ARCHITECTURE_ARM64:
features[PF_ARM_V8_INSTRUCTIONS_AVAILABLE] = TRUE;
features[PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_V8_CRC32);
features[PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_V8_CRYPTO);
break;
}
data->ActiveProcessorCount = NtCurrentTeb()->Peb->NumberOfProcessors;
data->ActiveGroupCount = 1;
UnmapViewOfFile( data );
}
#if defined(__i386__) || defined(__x86_64__)
static void regs_to_str( int *regs, unsigned int len, WCHAR *buffer )
@ -1502,6 +1589,7 @@ int __cdecl main( int argc, char *argv[] )
ResetEvent( event ); /* in case this is a restart */
create_user_shared_data();
create_hardware_registry_keys();
create_dynamic_registry_keys();
create_environment_registry_keys();

View File

@ -380,9 +380,13 @@ void init_directories(void)
};
static const struct unicode_str keyed_event_crit_sect_str = {keyed_event_crit_sectW, sizeof(keyed_event_crit_sectW)};
/* mappings */
static const WCHAR user_dataW[] = {'_','_','w','i','n','e','_','u','s','e','r','_','s','h','a','r','e','d','_','d','a','t','a'};
static const struct unicode_str user_data_str = {user_dataW, sizeof(user_dataW)};
struct directory *dir_driver, *dir_device, *dir_global, *dir_kernel;
struct object *link_dosdev, *link_global, *link_nul, *link_pipe, *link_mailslot;
struct object *named_pipe_device, *mailslot_device, *null_device;
struct object *named_pipe_device, *mailslot_device, *null_device, *user_data_mapping;
struct keyed_event *keyed_event;
unsigned int i;
@ -429,6 +433,10 @@ void init_directories(void)
keyed_event = create_keyed_event( &dir_kernel->obj, &keyed_event_crit_sect_str, 0, NULL );
make_object_static( (struct object *)keyed_event );
/* user data mapping */
user_data_mapping = create_user_data_mapping( &dir_kernel->obj, &user_data_str, 0, NULL );
make_object_static( user_data_mapping );
/* the objects hold references so we can release these directories */
release_object( dir_global );
release_object( dir_device );

View File

@ -167,15 +167,13 @@ extern int is_file_executable( const char *name );
/* file mapping functions */
extern struct mapping *get_mapping_obj( struct process *process, obj_handle_t handle,
unsigned int access );
extern struct file *get_mapping_file( struct process *process, client_ptr_t base,
unsigned int access, unsigned int sharing );
extern const pe_image_info_t *get_mapping_image_info( struct process *process, client_ptr_t base );
extern void free_mapped_views( struct process *process );
extern int get_page_size(void);
extern void init_kusd_mapping( struct mapping *mapping );
extern struct object *create_user_data_mapping( struct object *root, const struct unicode_str *name,
unsigned int attr, const struct security_descriptor *sd );
/* device functions */

View File

@ -782,7 +782,7 @@ static unsigned int get_mapping_flags( obj_handle_t handle, unsigned int flags )
}
static struct object *create_mapping( struct object *root, const struct unicode_str *name,
static struct mapping *create_mapping( struct object *root, const struct unicode_str *name,
unsigned int attr, mem_size_t size, unsigned int flags,
obj_handle_t handle, unsigned int file_access,
const struct security_descriptor *sd )
@ -798,7 +798,7 @@ static struct object *create_mapping( struct object *root, const struct unicode_
if (!(mapping = create_named_object( root, &mapping_ops, name, attr, sd )))
return NULL;
if (get_error() == STATUS_OBJECT_NAME_EXISTS)
return &mapping->obj; /* Nothing else to do */
return mapping; /* Nothing else to do */
mapping->size = size;
mapping->fd = NULL;
@ -837,7 +837,7 @@ static struct object *create_mapping( struct object *root, const struct unicode_
if (flags & SEC_IMAGE)
{
unsigned int err = get_image_params( mapping, st.st_size, unix_fd );
if (!err) return &mapping->obj;
if (!err) return mapping;
set_error( err );
goto error;
}
@ -873,14 +873,14 @@ static struct object *create_mapping( struct object *root, const struct unicode_
FILE_SYNCHRONOUS_IO_NONALERT ))) goto error;
allow_fd_caching( mapping->fd );
}
return &mapping->obj;
return mapping;
error:
release_object( mapping );
return NULL;
}
struct mapping *get_mapping_obj( struct process *process, obj_handle_t handle, unsigned int access )
static struct mapping *get_mapping_obj( struct process *process, obj_handle_t handle, unsigned int access )
{
return (struct mapping *)get_handle_obj( process, handle, access, &mapping_ops );
}
@ -955,36 +955,39 @@ int get_page_size(void)
return page_mask + 1;
}
void init_kusd_mapping( struct mapping *mapping )
struct object *create_user_data_mapping( struct object *root, const struct unicode_str *name,
unsigned int attr, const struct security_descriptor *sd )
{
void *ptr;
struct mapping *mapping;
if (user_shared_data) return;
grab_object( mapping );
make_object_static( &mapping->obj );
if (!(mapping = create_mapping( root, name, OBJ_OPENIF, sizeof(KSHARED_USER_DATA),
SEC_COMMIT, 0, FILE_READ_DATA | FILE_WRITE_DATA, NULL ))) return NULL;
ptr = mmap( NULL, mapping->size, PROT_WRITE, MAP_SHARED, get_unix_fd( mapping->fd ), 0 );
if (ptr != MAP_FAILED) user_shared_data = ptr;
return &mapping->obj;
}
/* create a file mapping */
DECL_HANDLER(create_mapping)
{
struct object *root, *obj;
struct object *root;
struct mapping *mapping;
struct unicode_str name;
const struct security_descriptor *sd;
const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root );
if (!objattr) return;
if ((obj = create_mapping( root, &name, objattr->attributes, req->size, req->flags,
if ((mapping = create_mapping( root, &name, objattr->attributes, req->size, req->flags,
req->file_handle, req->file_access, sd )))
{
if (get_error() == STATUS_OBJECT_NAME_EXISTS)
reply->handle = alloc_handle( current->process, obj, req->access, objattr->attributes );
reply->handle = alloc_handle( current->process, &mapping->obj, req->access, objattr->attributes );
else
reply->handle = alloc_handle_no_access_check( current->process, obj,
reply->handle = alloc_handle_no_access_check( current->process, &mapping->obj,
req->access, objattr->attributes );
release_object( obj );
release_object( mapping );
}
if (root) release_object( root );

View File

@ -1361,7 +1361,6 @@ DECL_HANDLER(init_process_done)
{
struct process_dll *dll;
struct process *process = current->process;
struct mapping *mapping;
if (is_process_init_done(process))
{
@ -1373,13 +1372,6 @@ DECL_HANDLER(init_process_done)
set_error( STATUS_DLL_NOT_FOUND );
return;
}
if (!(mapping = get_mapping_obj( current->process, req->usd_handle, SECTION_MAP_WRITE )))
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
init_kusd_mapping( mapping );
release_object( mapping );
/* main exe is the first in the dll list */
list_remove( &dll->entry );

View File

@ -854,7 +854,6 @@ struct rawinput_device
mod_handle_t module; /* main module base address */
client_ptr_t ldt_copy; /* address of LDT copy (in thread address space) */
client_ptr_t entry; /* process entry point */
obj_handle_t usd_handle; /* USD mapping handle */
@REPLY
int suspend; /* is process suspended? */
@END

View File

@ -784,8 +784,7 @@ C_ASSERT( FIELD_OFFSET(struct init_process_done_request, gui) == 12 );
C_ASSERT( FIELD_OFFSET(struct init_process_done_request, module) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_process_done_request, ldt_copy) == 24 );
C_ASSERT( FIELD_OFFSET(struct init_process_done_request, entry) == 32 );
C_ASSERT( FIELD_OFFSET(struct init_process_done_request, usd_handle) == 40 );
C_ASSERT( sizeof(struct init_process_done_request) == 48 );
C_ASSERT( sizeof(struct init_process_done_request) == 40 );
C_ASSERT( FIELD_OFFSET(struct init_process_done_reply, suspend) == 8 );
C_ASSERT( sizeof(struct init_process_done_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_pid) == 12 );

View File

@ -1317,7 +1317,6 @@ static void dump_init_process_done_request( const struct init_process_done_reque
dump_uint64( ", module=", &req->module );
dump_uint64( ", ldt_copy=", &req->ldt_copy );
dump_uint64( ", entry=", &req->entry );
fprintf( stderr, ", usd_handle=%04x", req->usd_handle );
}
static void dump_init_process_done_reply( const struct init_process_done_reply *req )