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 file_get_mmap_fd( struct file *file );
|
||||||
extern int set_file_pointer( int handle, int *low, int *high, int whence );
|
extern int set_file_pointer( int handle, int *low, int *high, int whence );
|
||||||
extern int truncate_file( int handle );
|
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 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,
|
extern int file_lock( struct file *file, int offset_high, int offset_low,
|
||||||
int count_high, int count_low );
|
int count_high, int count_low );
|
||||||
|
|
|
@ -1109,37 +1109,8 @@ HANDLE WINAPI CreateFileMappingA(
|
||||||
|
|
||||||
/* Compute the size and extend the file if necessary */
|
/* 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 */
|
if (hFile != INVALID_HANDLE_VALUE) /* We have a file */
|
||||||
{
|
{
|
||||||
BY_HANDLE_FILE_INFORMATION info;
|
|
||||||
DWORD access = GENERIC_READ;
|
DWORD access = GENERIC_READ;
|
||||||
|
|
||||||
if (((protect & 0xff) == PAGE_READWRITE) ||
|
if (((protect & 0xff) == PAGE_READWRITE) ||
|
||||||
|
@ -1150,21 +1121,6 @@ HANDLE WINAPI CreateFileMappingA(
|
||||||
|
|
||||||
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
|
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
|
||||||
K32OBJ_FILE, access )) == -1) goto error;
|
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;
|
else req.handle = -1;
|
||||||
|
|
||||||
|
@ -1173,6 +1129,7 @@ HANDLE WINAPI CreateFileMappingA(
|
||||||
req.size_high = size_high;
|
req.size_high = size_high;
|
||||||
req.size_low = ROUND_SIZE( 0, size_low );
|
req.size_low = ROUND_SIZE( 0, size_low );
|
||||||
req.protect = vprot;
|
req.protect = vprot;
|
||||||
|
req.inherit = inherit;
|
||||||
CLIENT_SendRequest( REQ_CREATE_MAPPING, -1, 2,
|
CLIENT_SendRequest( REQ_CREATE_MAPPING, -1, 2,
|
||||||
&req, sizeof(req),
|
&req, sizeof(req),
|
||||||
name, name ? strlen(name) + 1 : 0 );
|
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;
|
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 )
|
static void file_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct file *file = (struct file *)obj;
|
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 )
|
int set_file_time( int handle, time_t access_time, time_t write_time )
|
||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
#include "server/process.h"
|
#include "server/process.h"
|
||||||
|
@ -40,10 +41,51 @@ static const struct object_ops mapping_ops =
|
||||||
mapping_destroy
|
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,
|
struct object *create_mapping( int size_high, int size_low, int protect,
|
||||||
int handle, const char *name )
|
int handle, const char *name )
|
||||||
{
|
{
|
||||||
struct mapping *mapping;
|
struct mapping *mapping;
|
||||||
|
int access = 0;
|
||||||
|
|
||||||
|
if (!page_mask) init_page_size();
|
||||||
|
|
||||||
if (!(mapping = (struct mapping *)create_named_object( name, &mapping_ops,
|
if (!(mapping = (struct mapping *)create_named_object( name, &mapping_ops,
|
||||||
sizeof(*mapping) )))
|
sizeof(*mapping) )))
|
||||||
|
@ -51,22 +93,42 @@ struct object *create_mapping( int size_high, int size_low, int protect,
|
||||||
if (GET_ERROR() == ERROR_ALREADY_EXISTS)
|
if (GET_ERROR() == ERROR_ALREADY_EXISTS)
|
||||||
return &mapping->obj; /* Nothing else to do */
|
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_high = size_high;
|
||||||
mapping->size_low = size_low;
|
mapping->size_low = size_low;
|
||||||
mapping->protect = protect;
|
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;
|
return &mapping->obj;
|
||||||
|
|
||||||
|
error:
|
||||||
|
release_object( mapping );
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int open_mapping( unsigned int access, int inherit, const char *name )
|
int open_mapping( unsigned int access, int inherit, const char *name )
|
||||||
|
|
Loading…
Reference in New Issue