mirror of
https://github.com/reactos/wine.git
synced 2024-11-24 20:30:01 +00:00
Added support for mappings with no associated file.
This commit is contained in:
parent
875d112dd7
commit
cb28bdc2c8
@ -153,6 +153,8 @@ extern struct file *get_file_obj( struct process *process, int handle,
|
||||
extern int file_get_mmap_fd( struct file *file );
|
||||
extern int set_file_pointer( int handle, int *low, int *high, int whence );
|
||||
extern int truncate_file( int handle );
|
||||
extern int grow_file( struct file *file, int size_high, int size_low );
|
||||
extern struct file *create_temp_file( int access );
|
||||
extern int set_file_time( int handle, time_t access_time, time_t write_time );
|
||||
extern int file_lock( struct file *file, int offset_high, int offset_low,
|
||||
int count_high, int count_low );
|
||||
|
@ -1109,37 +1109,8 @@ HANDLE WINAPI CreateFileMappingA(
|
||||
|
||||
/* Compute the size and extend the file if necessary */
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (!size_high && !size_low)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
if (name)
|
||||
{
|
||||
CHAR buf[260];
|
||||
|
||||
GetTempPathA(260,buf);
|
||||
GetTempFileNameA(buf,"wine",0,buf);
|
||||
hFile = CreateFileA(
|
||||
buf,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,/* so we can reuse the tmpfn */
|
||||
NULL,
|
||||
OPEN_ALWAYS,
|
||||
0,
|
||||
0
|
||||
);
|
||||
/* FIXME: bad hack to avoid lots of leftover tempfiles */
|
||||
DeleteFileA(buf);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
FIXME(virtual,"could not create temp. file for anon shared mapping: reason was 0x%08lx\n",GetLastError());
|
||||
}
|
||||
}
|
||||
if (hFile != INVALID_HANDLE_VALUE) /* We have a file */
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
DWORD access = GENERIC_READ;
|
||||
|
||||
if (((protect & 0xff) == PAGE_READWRITE) ||
|
||||
@ -1150,21 +1121,6 @@ HANDLE WINAPI CreateFileMappingA(
|
||||
|
||||
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
|
||||
K32OBJ_FILE, access )) == -1) goto error;
|
||||
if (!GetFileInformationByHandle( hFile, &info )) goto error;
|
||||
if (!size_high && !size_low)
|
||||
{
|
||||
size_high = info.nFileSizeHigh;
|
||||
size_low = info.nFileSizeLow;
|
||||
}
|
||||
else if ((size_high > info.nFileSizeHigh) ||
|
||||
((size_high == info.nFileSizeHigh) &&
|
||||
(size_low > info.nFileSizeLow)))
|
||||
{
|
||||
/* We have to grow the file */
|
||||
if (SetFilePointer( hFile, size_low, &size_high,
|
||||
FILE_BEGIN ) == 0xffffffff) goto error;
|
||||
if (!SetEndOfFile( hFile )) goto error;
|
||||
}
|
||||
}
|
||||
else req.handle = -1;
|
||||
|
||||
@ -1173,6 +1129,7 @@ HANDLE WINAPI CreateFileMappingA(
|
||||
req.size_high = size_high;
|
||||
req.size_low = ROUND_SIZE( 0, size_low );
|
||||
req.protect = vprot;
|
||||
req.inherit = inherit;
|
||||
CLIENT_SendRequest( REQ_CREATE_MAPPING, -1, 2,
|
||||
&req, sizeof(req),
|
||||
name, name ? strlen(name) + 1 : 0 );
|
||||
|
@ -199,6 +199,45 @@ struct object *create_file( int fd, const char *name, unsigned int access,
|
||||
return &file->obj;
|
||||
}
|
||||
|
||||
/* Create a temp file for anonymous mappings */
|
||||
struct file *create_temp_file( int access )
|
||||
{
|
||||
struct file *file;
|
||||
char *name;
|
||||
int fd;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(name = tmpnam(NULL)))
|
||||
{
|
||||
SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
|
||||
return NULL;
|
||||
}
|
||||
fd = open( name, O_CREAT | O_EXCL | O_RDWR, 0600 );
|
||||
} while ((fd == -1) && (errno == EEXIST));
|
||||
if (fd == -1)
|
||||
{
|
||||
file_set_error();
|
||||
return NULL;
|
||||
}
|
||||
unlink( name );
|
||||
|
||||
if (!(file = mem_alloc( sizeof(*file) )))
|
||||
{
|
||||
close( fd );
|
||||
return NULL;
|
||||
}
|
||||
init_object( &file->obj, &file_ops, NULL );
|
||||
file->name = NULL;
|
||||
file->next = NULL;
|
||||
file->fd = fd;
|
||||
file->access = access;
|
||||
file->flags = 0;
|
||||
file->sharing = 0;
|
||||
CLEAR_ERROR();
|
||||
return file;
|
||||
}
|
||||
|
||||
static void file_dump( struct object *obj, int verbose )
|
||||
{
|
||||
struct file *file = (struct file *)obj;
|
||||
@ -406,6 +445,27 @@ int truncate_file( int handle )
|
||||
|
||||
}
|
||||
|
||||
/* try to grow the file to the specified size */
|
||||
int grow_file( struct file *file, int size_high, int size_low )
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (size_high)
|
||||
{
|
||||
SET_ERROR( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
if (fstat( file->fd, &st ) == -1)
|
||||
{
|
||||
file_set_error();
|
||||
return 0;
|
||||
}
|
||||
if (st.st_size >= size_low) return 1; /* already large enough */
|
||||
if (ftruncate( file->fd, size_low ) != -1) return 1;
|
||||
file_set_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_file_time( int handle, time_t access_time, time_t write_time )
|
||||
{
|
||||
struct file *file;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "winerror.h"
|
||||
#include "winnt.h"
|
||||
#include "server/process.h"
|
||||
@ -40,10 +41,51 @@ static const struct object_ops mapping_ops =
|
||||
mapping_destroy
|
||||
};
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
/* These are always the same on an i386, and it will be faster this way */
|
||||
# define page_mask 0xfff
|
||||
# define page_shift 12
|
||||
# define init_page_size() /* nothing */
|
||||
|
||||
#else /* __i386__ */
|
||||
|
||||
static int page_shift, page_mask;
|
||||
|
||||
static void init_page_size(void)
|
||||
{
|
||||
int page_size;
|
||||
# ifdef HAVE_GETPAGESIZE
|
||||
page_size = getpagesize();
|
||||
# else
|
||||
# ifdef __svr4__
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
# else
|
||||
# error Cannot get the page size on this platform
|
||||
# endif
|
||||
# endif
|
||||
page_mask = page_size - 1;
|
||||
/* Make sure we have a power of 2 */
|
||||
assert( !(page_size & page_mask) );
|
||||
page_shift = 0;
|
||||
while ((1 << page_shift) != page_size) page_shift++;
|
||||
}
|
||||
#endif /* __i386__ */
|
||||
|
||||
#define ROUND_ADDR(addr) \
|
||||
((int)(addr) & ~page_mask)
|
||||
|
||||
#define ROUND_SIZE(addr,size) \
|
||||
(((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask)
|
||||
|
||||
|
||||
struct object *create_mapping( int size_high, int size_low, int protect,
|
||||
int handle, const char *name )
|
||||
{
|
||||
struct mapping *mapping;
|
||||
int access = 0;
|
||||
|
||||
if (!page_mask) init_page_size();
|
||||
|
||||
if (!(mapping = (struct mapping *)create_named_object( name, &mapping_ops,
|
||||
sizeof(*mapping) )))
|
||||
@ -51,22 +93,42 @@ struct object *create_mapping( int size_high, int size_low, int protect,
|
||||
if (GET_ERROR() == ERROR_ALREADY_EXISTS)
|
||||
return &mapping->obj; /* Nothing else to do */
|
||||
|
||||
if (protect & VPROT_READ) access |= GENERIC_READ;
|
||||
if (protect & VPROT_WRITE) access |= GENERIC_WRITE;
|
||||
|
||||
size_low = ROUND_SIZE( 0, size_low );
|
||||
if (handle != -1)
|
||||
{
|
||||
if (!(mapping->file = get_file_obj( current->process, handle, access ))) goto error;
|
||||
if (!size_high && !size_low)
|
||||
{
|
||||
struct get_file_info_reply reply;
|
||||
struct object *obj = (struct object *)mapping->file;
|
||||
obj->ops->get_file_info( obj, &reply );
|
||||
size_high = reply.size_high;
|
||||
size_low = ROUND_SIZE( 0, reply.size_low );
|
||||
}
|
||||
else if (!grow_file( mapping->file, size_high, size_low )) goto error;
|
||||
}
|
||||
else /* Anonymous mapping (no associated file) */
|
||||
{
|
||||
if (!size_high && !size_low)
|
||||
{
|
||||
SET_ERROR( ERROR_INVALID_PARAMETER );
|
||||
mapping->file = NULL;
|
||||
goto error;
|
||||
}
|
||||
if (!(mapping->file = create_temp_file( access ))) goto error;
|
||||
if (!grow_file( mapping->file, size_high, size_low )) goto error;
|
||||
}
|
||||
mapping->size_high = size_high;
|
||||
mapping->size_low = size_low;
|
||||
mapping->protect = protect;
|
||||
if (handle != -1)
|
||||
{
|
||||
int access = 0;
|
||||
if (protect & VPROT_READ) access |= GENERIC_READ;
|
||||
if (protect & VPROT_WRITE) access |= GENERIC_WRITE;
|
||||
if (!(mapping->file = get_file_obj( current->process, handle, access )))
|
||||
{
|
||||
release_object( mapping );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else mapping->file = NULL;
|
||||
return &mapping->obj;
|
||||
|
||||
error:
|
||||
release_object( mapping );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int open_mapping( unsigned int access, int inherit, const char *name )
|
||||
|
Loading…
Reference in New Issue
Block a user