Implemented file sharing checks in the server.
Added set file time server request. Overall clean up of the file handling (DOS device handling is now broken, should be redone).
This commit is contained in:
parent
74304fc31c
commit
0562539d18
|
@ -607,12 +607,10 @@ const DOS_DEVICE *DOSFS_GetDevice( const char *name )
|
||||||
*
|
*
|
||||||
* Open a DOS device. This might not map 1:1 into the UNIX device concept.
|
* Open a DOS device. This might not map 1:1 into the UNIX device concept.
|
||||||
*/
|
*/
|
||||||
HFILE32 DOSFS_OpenDevice( const char *name, int unixmode )
|
HFILE32 DOSFS_OpenDevice( const char *name, DWORD access )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char *p;
|
const char *p;
|
||||||
FILE_OBJECT *file;
|
|
||||||
HFILE32 handle;
|
|
||||||
|
|
||||||
if (!name) return (HFILE32)NULL; /* if FILE_DupUnixHandle was used */
|
if (!name) return (HFILE32)NULL; /* if FILE_DupUnixHandle was used */
|
||||||
if (name[0] && (name[1] == ':')) name += 2;
|
if (name[0] && (name[1] == ':')) name += 2;
|
||||||
|
@ -627,15 +625,17 @@ HFILE32 DOSFS_OpenDevice( const char *name, int unixmode )
|
||||||
if (!*p || (*p == '.')) {
|
if (!*p || (*p == '.')) {
|
||||||
/* got it */
|
/* got it */
|
||||||
if (!strcmp(DOSFS_Devices[i].name,"NUL"))
|
if (!strcmp(DOSFS_Devices[i].name,"NUL"))
|
||||||
return FILE_OpenUnixFile("/dev/null",unixmode);
|
return FILE_CreateFile( "/dev/null", access,
|
||||||
|
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
|
||||||
|
OPEN_EXISTING, 0, -1 );
|
||||||
if (!strcmp(DOSFS_Devices[i].name,"CON")) {
|
if (!strcmp(DOSFS_Devices[i].name,"CON")) {
|
||||||
HFILE32 to_dup;
|
HFILE32 to_dup;
|
||||||
HFILE32 handle;
|
HFILE32 handle;
|
||||||
switch (unixmode) {
|
switch (access & (GENERIC_READ|GENERIC_WRITE)) {
|
||||||
case O_RDONLY:
|
case GENERIC_READ:
|
||||||
to_dup = GetStdHandle( STD_INPUT_HANDLE );
|
to_dup = GetStdHandle( STD_INPUT_HANDLE );
|
||||||
break;
|
break;
|
||||||
case O_WRONLY:
|
case GENERIC_WRITE:
|
||||||
to_dup = GetStdHandle( STD_OUTPUT_HANDLE );
|
to_dup = GetStdHandle( STD_OUTPUT_HANDLE );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -651,8 +651,10 @@ HFILE32 DOSFS_OpenDevice( const char *name, int unixmode )
|
||||||
if (!strcmp(DOSFS_Devices[i].name,"SCSIMGR$") ||
|
if (!strcmp(DOSFS_Devices[i].name,"SCSIMGR$") ||
|
||||||
!strcmp(DOSFS_Devices[i].name,"HPSCAN"))
|
!strcmp(DOSFS_Devices[i].name,"HPSCAN"))
|
||||||
{
|
{
|
||||||
int fd = open( "/dev/null", unixmode );
|
/* FIXME: should keep the name somewhere */
|
||||||
return FILE_Alloc( &file, fd, DOSFS_Devices[i].name );
|
return FILE_CreateFile( "/dev/null", access,
|
||||||
|
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
|
||||||
|
OPEN_EXISTING, 0, -1 );
|
||||||
}
|
}
|
||||||
FIXME(dosfs,"device open %s not supported (yet)\n",DOSFS_Devices[i].name);
|
FIXME(dosfs,"device open %s not supported (yet)\n",DOSFS_Devices[i].name);
|
||||||
return HFILE_ERROR32;
|
return HFILE_ERROR32;
|
||||||
|
|
565
files/file.c
565
files/file.c
|
@ -27,6 +27,7 @@
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "drive.h"
|
#include "drive.h"
|
||||||
|
#include "device.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
|
@ -66,43 +67,6 @@ typedef struct DOS_FILE_LOCK DOS_FILE_LOCK;
|
||||||
static DOS_FILE_LOCK *locks = NULL;
|
static DOS_FILE_LOCK *locks = NULL;
|
||||||
static void DOS_RemoveFileLocks(FILE_OBJECT *file);
|
static void DOS_RemoveFileLocks(FILE_OBJECT *file);
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* FILE_Alloc
|
|
||||||
*
|
|
||||||
* Allocate a file. The unix_handle is closed.
|
|
||||||
*/
|
|
||||||
HFILE32 FILE_Alloc( FILE_OBJECT **file, int unix_handle, const char *unix_name )
|
|
||||||
{
|
|
||||||
HFILE32 handle;
|
|
||||||
struct create_file_request req;
|
|
||||||
struct create_file_reply reply;
|
|
||||||
|
|
||||||
req.access = FILE_ALL_ACCESS | GENERIC_READ |
|
|
||||||
GENERIC_WRITE | GENERIC_EXECUTE; /* FIXME */
|
|
||||||
req.inherit = 1; /* FIXME */
|
|
||||||
CLIENT_SendRequest( REQ_CREATE_FILE, unix_handle, 1, &req, sizeof(req) );
|
|
||||||
CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
|
|
||||||
if (reply.handle == -1) return INVALID_HANDLE_VALUE32;
|
|
||||||
|
|
||||||
*file = HeapAlloc( SystemHeap, 0, sizeof(FILE_OBJECT) );
|
|
||||||
if (!*file)
|
|
||||||
{
|
|
||||||
DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
|
|
||||||
CLIENT_CloseHandle( reply.handle );
|
|
||||||
return (HFILE32)NULL;
|
|
||||||
}
|
|
||||||
(*file)->header.type = K32OBJ_FILE;
|
|
||||||
(*file)->header.refcount = 0;
|
|
||||||
(*file)->unix_name = unix_name ? HEAP_strdupA( SystemHeap, 0, unix_name ) : NULL;
|
|
||||||
(*file)->type = FILE_TYPE_DISK;
|
|
||||||
(*file)->mode = 0;
|
|
||||||
|
|
||||||
handle = HANDLE_Alloc( PROCESS_Current(), &(*file)->header, req.access,
|
|
||||||
req.inherit, reply.handle );
|
|
||||||
/* If the allocation failed, the object is already destroyed */
|
|
||||||
if (handle == INVALID_HANDLE_VALUE32) *file = NULL;
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -149,56 +113,32 @@ void FILE_ReleaseFile( FILE_OBJECT *file )
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FILE_UnixToDosMode
|
* FILE_ConvertOFMode
|
||||||
*
|
*
|
||||||
* PARAMS
|
* Convert OF_* mode into flags for CreateFile.
|
||||||
* unixmode[I]
|
|
||||||
* RETURNS
|
|
||||||
* dosmode
|
|
||||||
*/
|
*/
|
||||||
static int FILE_UnixToDosMode(int unixMode)
|
static void FILE_ConvertOFMode( INT32 mode, DWORD *access, DWORD *sharing )
|
||||||
{
|
{
|
||||||
int dosMode;
|
switch(mode & 0x03)
|
||||||
switch(unixMode & 3)
|
{
|
||||||
{
|
case OF_READ: *access = GENERIC_READ; break;
|
||||||
case O_WRONLY:
|
case OF_WRITE: *access = GENERIC_WRITE; break;
|
||||||
dosMode = OF_WRITE;
|
case OF_READWRITE: *access = GENERIC_READ | GENERIC_WRITE; break;
|
||||||
break;
|
default: *access = 0; break;
|
||||||
case O_RDWR:
|
}
|
||||||
dosMode =OF_READWRITE;
|
switch(mode & 0x70)
|
||||||
break;
|
{
|
||||||
case O_RDONLY:
|
case OF_SHARE_EXCLUSIVE: *sharing = 0; break;
|
||||||
default:
|
case OF_SHARE_DENY_WRITE: *sharing = FILE_SHARE_READ; break;
|
||||||
dosMode = OF_READ;
|
case OF_SHARE_DENY_READ: *sharing = FILE_SHARE_WRITE; break;
|
||||||
break;
|
case OF_SHARE_DENY_NONE:
|
||||||
}
|
case OF_SHARE_COMPAT:
|
||||||
return dosMode;
|
default: *sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* FILE_DOSToUnixMode
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
* dosMode[I]
|
|
||||||
* RETURNS
|
|
||||||
* unixmode
|
|
||||||
*/
|
|
||||||
static int FILE_DOSToUnixMode(int dosMode)
|
|
||||||
{
|
|
||||||
int unixMode;
|
|
||||||
switch(dosMode & 3)
|
|
||||||
{
|
|
||||||
case OF_WRITE:
|
|
||||||
unixMode = O_WRONLY; break;
|
|
||||||
case OF_READWRITE:
|
|
||||||
unixMode = O_RDWR; break;
|
|
||||||
case OF_READ:
|
|
||||||
default:
|
|
||||||
unixMode = O_RDONLY; break;
|
|
||||||
}
|
|
||||||
return unixMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FILE_ShareDeny
|
* FILE_ShareDeny
|
||||||
*
|
*
|
||||||
|
@ -352,58 +292,8 @@ fail_error05:
|
||||||
DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
|
DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Look if the File is in Use For the OF_SHARE_XXX options
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
* name [I]: full unix name of the file that should be opened
|
|
||||||
* mode [O]: mode how the file was first opened
|
|
||||||
* RETURNS
|
|
||||||
* TRUE if the file was opened before
|
|
||||||
* FALSE if we open the file exclusive for this process
|
|
||||||
*
|
|
||||||
* Scope of the files we look for is only the current pdb
|
|
||||||
* Could we use /proc/self/? on Linux for this?
|
|
||||||
* Should we use flock? Should we create another structure?
|
|
||||||
* Searching through all files seem quite expensive for me, but
|
|
||||||
* I don't see any other way.
|
|
||||||
*
|
|
||||||
* FIXME: Extend scope to the whole Wine process
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static BOOL32 FILE_InUse(char * name, int * mode)
|
|
||||||
{
|
|
||||||
FILE_OBJECT *file;
|
|
||||||
int i;
|
|
||||||
HGLOBAL16 hPDB = GetCurrentPDB();
|
|
||||||
PDB *pdb = (PDB *)GlobalLock16( hPDB );
|
|
||||||
|
|
||||||
if (!pdb) return 0;
|
|
||||||
for (i=0;i<pdb->nbFiles;i++)
|
|
||||||
{
|
|
||||||
file =FILE_GetFile( (HFILE32)i, 0, NULL );
|
|
||||||
if(file)
|
|
||||||
{
|
|
||||||
if(file->unix_name)
|
|
||||||
{
|
|
||||||
TRACE(file,"got %s at %d\n",file->unix_name,i);
|
|
||||||
if(!lstrcmp32A(file->unix_name,name))
|
|
||||||
{
|
|
||||||
*mode = file->mode;
|
|
||||||
FILE_ReleaseFile(file);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FILE_ReleaseFile(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FILE_SetDosError
|
* FILE_SetDosError
|
||||||
|
@ -468,164 +358,213 @@ void FILE_SetDosError(void)
|
||||||
*
|
*
|
||||||
* Duplicate a Unix handle into a task handle.
|
* Duplicate a Unix handle into a task handle.
|
||||||
*/
|
*/
|
||||||
HFILE32 FILE_DupUnixHandle( int fd )
|
HFILE32 FILE_DupUnixHandle( int fd, DWORD access )
|
||||||
{
|
{
|
||||||
int unix_handle;
|
|
||||||
FILE_OBJECT *file;
|
FILE_OBJECT *file;
|
||||||
|
int unix_handle;
|
||||||
|
struct create_file_request req;
|
||||||
|
struct create_file_reply reply;
|
||||||
|
|
||||||
if ((unix_handle = dup(fd)) == -1)
|
if ((unix_handle = dup(fd)) == -1)
|
||||||
{
|
{
|
||||||
FILE_SetDosError();
|
FILE_SetDosError();
|
||||||
return INVALID_HANDLE_VALUE32;
|
return INVALID_HANDLE_VALUE32;
|
||||||
}
|
}
|
||||||
return FILE_Alloc( &file, unix_handle, NULL );
|
req.access = access;
|
||||||
|
req.inherit = 1;
|
||||||
|
req.sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||||
|
req.create = 0;
|
||||||
|
req.attrs = 0;
|
||||||
|
|
||||||
|
CLIENT_SendRequest( REQ_CREATE_FILE, unix_handle, 1,
|
||||||
|
&req, sizeof(req) );
|
||||||
|
CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
|
||||||
|
if (reply.handle == -1) return INVALID_HANDLE_VALUE32;
|
||||||
|
|
||||||
|
if (!(file = HeapAlloc( SystemHeap, 0, sizeof(FILE_OBJECT) )))
|
||||||
|
{
|
||||||
|
DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
|
||||||
|
CLIENT_CloseHandle( reply.handle );
|
||||||
|
return (HFILE32)NULL;
|
||||||
|
}
|
||||||
|
file->header.type = K32OBJ_FILE;
|
||||||
|
file->header.refcount = 0;
|
||||||
|
file->unix_name = NULL;
|
||||||
|
return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access,
|
||||||
|
req.inherit, reply.handle );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FILE_OpenUnixFile
|
* FILE_CreateFile
|
||||||
|
*
|
||||||
|
* Implementation of CreateFile. Takes a Unix path name.
|
||||||
*/
|
*/
|
||||||
HFILE32 FILE_OpenUnixFile( const char *name, int mode )
|
HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
|
||||||
|
LPSECURITY_ATTRIBUTES sa, DWORD creation,
|
||||||
|
DWORD attributes, HANDLE32 template )
|
||||||
{
|
{
|
||||||
int unix_handle;
|
|
||||||
FILE_OBJECT *file;
|
FILE_OBJECT *file;
|
||||||
struct stat st;
|
struct create_file_request req;
|
||||||
|
struct create_file_reply reply;
|
||||||
|
|
||||||
if ((unix_handle = open( name, mode, 0666 )) == -1)
|
req.access = access;
|
||||||
{
|
req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||||
if (!Options.failReadOnly && (mode == O_RDWR))
|
req.sharing = sharing;
|
||||||
unix_handle = open( name, O_RDONLY );
|
req.create = creation;
|
||||||
}
|
req.attrs = attributes;
|
||||||
if ((unix_handle == -1) || (fstat( unix_handle, &st ) == -1))
|
CLIENT_SendRequest( REQ_CREATE_FILE, -1, 2,
|
||||||
{
|
&req, sizeof(req),
|
||||||
FILE_SetDosError();
|
filename, strlen(filename) + 1 );
|
||||||
return INVALID_HANDLE_VALUE32;
|
CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
|
||||||
}
|
|
||||||
if (S_ISDIR(st.st_mode))
|
|
||||||
{
|
|
||||||
DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
|
|
||||||
close( unix_handle );
|
|
||||||
return INVALID_HANDLE_VALUE32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* File opened OK, now allocate a handle */
|
/* If write access failed, retry without GENERIC_WRITE */
|
||||||
|
|
||||||
return FILE_Alloc( &file, unix_handle, name );
|
if ((reply.handle == -1) && !Options.failReadOnly &&
|
||||||
|
(access & GENERIC_WRITE) && (GetLastError() == ERROR_ACCESS_DENIED))
|
||||||
|
{
|
||||||
|
req.access &= ~GENERIC_WRITE;
|
||||||
|
CLIENT_SendRequest( REQ_CREATE_FILE, -1, 2,
|
||||||
|
&req, sizeof(req),
|
||||||
|
filename, strlen(filename) + 1 );
|
||||||
|
CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
|
||||||
|
}
|
||||||
|
if (reply.handle == -1) return INVALID_HANDLE_VALUE32;
|
||||||
|
|
||||||
|
/* Now build the FILE_OBJECT */
|
||||||
|
|
||||||
|
if (!(file = HeapAlloc( SystemHeap, 0, sizeof(FILE_OBJECT) )))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_OUTOFMEMORY );
|
||||||
|
CLIENT_CloseHandle( reply.handle );
|
||||||
|
return (HFILE32)INVALID_HANDLE_VALUE32;
|
||||||
|
}
|
||||||
|
file->header.type = K32OBJ_FILE;
|
||||||
|
file->header.refcount = 0;
|
||||||
|
file->unix_name = HEAP_strdupA( SystemHeap, 0, filename );
|
||||||
|
return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access,
|
||||||
|
req.inherit, reply.handle );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/*************************************************************************
|
||||||
* FILE_Open
|
* CreateFile32A [KERNEL32.45] Creates or opens a file or other object
|
||||||
*
|
*
|
||||||
* path[I] name of file to open
|
* Creates or opens an object, and returns a handle that can be used to
|
||||||
* mode[I] mode how to open, in unix notation
|
* access that object.
|
||||||
* shareMode[I] the sharing mode in the win OpenFile notation
|
|
||||||
*
|
*
|
||||||
|
* PARAMS
|
||||||
|
*
|
||||||
|
* filename [I] pointer to filename to be accessed
|
||||||
|
* access [I] access mode requested
|
||||||
|
* sharing [I] share mode
|
||||||
|
* sa [I] pointer to security attributes
|
||||||
|
* creation [I] how to create the file
|
||||||
|
* attributes [I] attributes for newly created file
|
||||||
|
* template [I] handle to file with extended attributes to copy
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: Open handle to specified file
|
||||||
|
* Failure: INVALID_HANDLE_VALUE
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* Should call SetLastError() on failure.
|
||||||
|
*
|
||||||
|
* BUGS
|
||||||
|
*
|
||||||
|
* Doesn't support character devices, pipes, template files, or a
|
||||||
|
* lot of the 'attributes' flags yet.
|
||||||
*/
|
*/
|
||||||
HFILE32 FILE_Open( LPCSTR path, INT32 mode, INT32 shareMode )
|
HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing,
|
||||||
|
LPSECURITY_ATTRIBUTES sa, DWORD creation,
|
||||||
|
DWORD attributes, HANDLE32 template )
|
||||||
{
|
{
|
||||||
DOS_FULL_NAME full_name;
|
DOS_FULL_NAME full_name;
|
||||||
const char *unixName;
|
HANDLE32 to_dup = HFILE_ERROR32;
|
||||||
int oldMode, dosMode; /* FIXME: Do we really need unixmode as argument for
|
|
||||||
FILE_Open */
|
|
||||||
FILE_OBJECT *file;
|
|
||||||
HFILE32 hFileRet;
|
|
||||||
BOOL32 fileInUse = FALSE;
|
|
||||||
|
|
||||||
TRACE(file, "'%s' %04x\n", path, mode );
|
if (!filename)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||||||
|
return HFILE_ERROR32;
|
||||||
|
}
|
||||||
|
|
||||||
if (!path) return HFILE_ERROR32;
|
/* If the name starts with '\\?\', ignore the first 4 chars. */
|
||||||
|
if (!strncmp(filename, "\\\\?\\", 4))
|
||||||
|
{
|
||||||
|
filename += 4;
|
||||||
|
if (!strncmp(filename, "UNC\\", 4))
|
||||||
|
{
|
||||||
|
FIXME( file, "UNC name (%s) not supported.\n", filename );
|
||||||
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
||||||
|
return HFILE_ERROR32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (DOSFS_GetDevice( path ))
|
if (!strncmp(filename, "\\\\.\\", 4)) return DEVICE_Open( filename+4 );
|
||||||
|
|
||||||
|
/* If the name still starts with '\\', it's a UNC name. */
|
||||||
|
if (!strncmp(filename, "\\\\", 2))
|
||||||
|
{
|
||||||
|
FIXME( file, "UNC name (%s) not supported.\n", filename );
|
||||||
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
||||||
|
return HFILE_ERROR32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the name is either CONIN$ or CONOUT$, give them duplicated stdin
|
||||||
|
* or stdout, respectively. The lower case version is also allowed. Most likely
|
||||||
|
* this should be a case ignore string compare.
|
||||||
|
*/
|
||||||
|
if(!strcasecmp(filename, "CONIN$"))
|
||||||
|
to_dup = GetStdHandle( STD_INPUT_HANDLE );
|
||||||
|
else if(!strcasecmp(filename, "CONOUT$"))
|
||||||
|
to_dup = GetStdHandle( STD_OUTPUT_HANDLE );
|
||||||
|
|
||||||
|
if(to_dup != HFILE_ERROR32)
|
||||||
|
{
|
||||||
|
HFILE32 handle;
|
||||||
|
if (!DuplicateHandle( GetCurrentProcess(), to_dup, GetCurrentProcess(),
|
||||||
|
&handle, access, FALSE, 0 ))
|
||||||
|
handle = HFILE_ERROR32;
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DOSFS_GetDevice( filename ))
|
||||||
{
|
{
|
||||||
HFILE32 ret;
|
HFILE32 ret;
|
||||||
|
|
||||||
TRACE(file, "opening device '%s'\n", path );
|
TRACE(file, "opening device '%s'\n", filename );
|
||||||
|
|
||||||
if (HFILE_ERROR32!=(ret=DOSFS_OpenDevice( path, mode )))
|
if (HFILE_ERROR32!=(ret=DOSFS_OpenDevice( filename, access )))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Do not silence this please. It is a critical error. -MM */
|
/* Do not silence this please. It is a critical error. -MM */
|
||||||
ERR(file, "Couldn't open device '%s'!\n",path);
|
ERR(file, "Couldn't open device '%s'!\n",filename);
|
||||||
DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
|
DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
|
||||||
return HFILE_ERROR32;
|
return HFILE_ERROR32;
|
||||||
|
|
||||||
}
|
}
|
||||||
else /* check for filename, don't check for last entry if creating */
|
|
||||||
{
|
/* check for filename, don't check for last entry if creating */
|
||||||
if (!DOSFS_GetFullName( path, !(mode & O_CREAT), &full_name ))
|
if (!DOSFS_GetFullName( filename,
|
||||||
return HFILE_ERROR32;
|
(creation == OPEN_EXISTING) || (creation == TRUNCATE_EXISTING), &full_name ))
|
||||||
unixName = full_name.long_name;
|
return HFILE_ERROR32;
|
||||||
}
|
|
||||||
|
return FILE_CreateFile( full_name.long_name, access, sharing,
|
||||||
dosMode = FILE_UnixToDosMode(mode)| shareMode;
|
sa, creation, attributes, template );
|
||||||
fileInUse = FILE_InUse(full_name.long_name,&oldMode);
|
|
||||||
if(fileInUse)
|
|
||||||
{
|
|
||||||
TRACE(file, "found another instance with mode 0x%02x\n",oldMode&0x70);
|
|
||||||
if (FILE_ShareDeny(dosMode,oldMode)) return HFILE_ERROR32;
|
|
||||||
}
|
|
||||||
hFileRet = FILE_OpenUnixFile( unixName, mode );
|
|
||||||
/* we need to save the mode, but only if it is not in use yet*/
|
|
||||||
if ((hFileRet) && (!fileInUse) && ((file =FILE_GetFile(hFileRet, 0, NULL))))
|
|
||||||
{
|
|
||||||
file->mode=dosMode;
|
|
||||||
FILE_ReleaseFile(file);
|
|
||||||
}
|
|
||||||
return hFileRet;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* FILE_Create
|
/*************************************************************************
|
||||||
|
* CreateFile32W (KERNEL32.48)
|
||||||
*/
|
*/
|
||||||
static HFILE32 FILE_Create( LPCSTR path, int mode, int unique )
|
HFILE32 WINAPI CreateFile32W( LPCWSTR filename, DWORD access, DWORD sharing,
|
||||||
|
LPSECURITY_ATTRIBUTES sa, DWORD creation,
|
||||||
|
DWORD attributes, HANDLE32 template)
|
||||||
{
|
{
|
||||||
HFILE32 handle;
|
LPSTR afn = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
|
||||||
int unix_handle;
|
HFILE32 res = CreateFile32A( afn, access, sharing, sa, creation, attributes, template );
|
||||||
FILE_OBJECT *file;
|
HeapFree( GetProcessHeap(), 0, afn );
|
||||||
DOS_FULL_NAME full_name;
|
return res;
|
||||||
BOOL32 fileInUse = FALSE;
|
|
||||||
int oldMode,dosMode; /* FIXME: Do we really need unixmode as argument for
|
|
||||||
FILE_Create */;
|
|
||||||
|
|
||||||
TRACE(file, "'%s' %04x %d\n", path, mode, unique );
|
|
||||||
|
|
||||||
if (!path) return INVALID_HANDLE_VALUE32;
|
|
||||||
|
|
||||||
if (DOSFS_GetDevice( path ))
|
|
||||||
{
|
|
||||||
WARN(file, "cannot create DOS device '%s'!\n", path);
|
|
||||||
DOS_ERROR( ER_AccessDenied, EC_NotFound, SA_Abort, EL_Disk );
|
|
||||||
return INVALID_HANDLE_VALUE32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DOSFS_GetFullName( path, FALSE, &full_name )) return INVALID_HANDLE_VALUE32;
|
|
||||||
|
|
||||||
dosMode = FILE_UnixToDosMode(mode);
|
|
||||||
fileInUse = FILE_InUse(full_name.long_name,&oldMode);
|
|
||||||
if(fileInUse)
|
|
||||||
{
|
|
||||||
TRACE(file, "found another instance with mode 0x%02x\n",oldMode&0x70);
|
|
||||||
if (FILE_ShareDeny(dosMode,oldMode)) return INVALID_HANDLE_VALUE32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((unix_handle = open( full_name.long_name,
|
|
||||||
O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0),
|
|
||||||
mode )) == -1)
|
|
||||||
{
|
|
||||||
FILE_SetDosError();
|
|
||||||
return INVALID_HANDLE_VALUE32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* File created OK, now fill the FILE_OBJECT */
|
|
||||||
|
|
||||||
if ((handle = FILE_Alloc( &file, unix_handle,
|
|
||||||
full_name.long_name )) == INVALID_HANDLE_VALUE32)
|
|
||||||
return INVALID_HANDLE_VALUE32;
|
|
||||||
file->mode = dosMode;
|
|
||||||
return handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -789,23 +728,6 @@ INT32 WINAPI CompareFileTime( LPFILETIME x, LPFILETIME y )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* FILE_Dup
|
|
||||||
*
|
|
||||||
* dup() function for DOS handles.
|
|
||||||
*/
|
|
||||||
HFILE32 FILE_Dup( HFILE32 hFile )
|
|
||||||
{
|
|
||||||
HFILE32 handle;
|
|
||||||
|
|
||||||
TRACE(file, "FILE_Dup for handle %d\n", hFile );
|
|
||||||
if (!DuplicateHandle( GetCurrentProcess(), hFile, GetCurrentProcess(),
|
|
||||||
&handle, FILE_ALL_ACCESS /* FIXME */, FALSE, 0 ))
|
|
||||||
handle = HFILE_ERROR32;
|
|
||||||
TRACE(file, "FILE_Dup return handle %d\n", handle );
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FILE_Dup2
|
* FILE_Dup2
|
||||||
|
@ -886,7 +808,8 @@ UINT32 WINAPI GetTempFileName32A( LPCSTR path, LPCSTR prefix, UINT32 unique,
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
HFILE32 handle = FILE_Create( buffer, 0666, TRUE );
|
HFILE32 handle = CreateFile32A( buffer, GENERIC_WRITE, 0, NULL,
|
||||||
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1 );
|
||||||
if (handle != INVALID_HANDLE_VALUE32)
|
if (handle != INVALID_HANDLE_VALUE32)
|
||||||
{ /* We created it */
|
{ /* We created it */
|
||||||
TRACE(file, "created %s\n",
|
TRACE(file, "created %s\n",
|
||||||
|
@ -949,14 +872,11 @@ static HFILE32 FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT32 mode,
|
||||||
FILETIME filetime;
|
FILETIME filetime;
|
||||||
WORD filedatetime[2];
|
WORD filedatetime[2];
|
||||||
DOS_FULL_NAME full_name;
|
DOS_FULL_NAME full_name;
|
||||||
|
DWORD access, sharing;
|
||||||
char *p;
|
char *p;
|
||||||
int unixMode, oldMode;
|
|
||||||
FILE_OBJECT *file;
|
|
||||||
BOOL32 fileInUse = FALSE;
|
|
||||||
|
|
||||||
if (!ofs) return HFILE_ERROR32;
|
if (!ofs) return HFILE_ERROR32;
|
||||||
|
|
||||||
|
|
||||||
ofs->cBytes = sizeof(OFSTRUCT);
|
ofs->cBytes = sizeof(OFSTRUCT);
|
||||||
ofs->nErrCode = 0;
|
ofs->nErrCode = 0;
|
||||||
if (mode & OF_REOPEN) name = ofs->szPathName;
|
if (mode & OF_REOPEN) name = ofs->szPathName;
|
||||||
|
@ -973,6 +893,7 @@ static HFILE32 FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT32 mode,
|
||||||
Uwe Bonnes 1997 Apr 2 */
|
Uwe Bonnes 1997 Apr 2 */
|
||||||
if (!GetFullPathName32A( name, sizeof(ofs->szPathName),
|
if (!GetFullPathName32A( name, sizeof(ofs->szPathName),
|
||||||
ofs->szPathName, NULL )) goto error;
|
ofs->szPathName, NULL )) goto error;
|
||||||
|
FILE_ConvertOFMode( mode, &access, &sharing );
|
||||||
|
|
||||||
/* OF_PARSE simply fills the structure */
|
/* OF_PARSE simply fills the structure */
|
||||||
|
|
||||||
|
@ -990,7 +911,9 @@ static HFILE32 FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT32 mode,
|
||||||
|
|
||||||
if (mode & OF_CREATE)
|
if (mode & OF_CREATE)
|
||||||
{
|
{
|
||||||
if ((hFileRet = FILE_Create(name,0666,FALSE))== INVALID_HANDLE_VALUE32)
|
if ((hFileRet = CreateFile32A( name, access, sharing, NULL,
|
||||||
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
||||||
|
-1 ))== INVALID_HANDLE_VALUE32)
|
||||||
goto error;
|
goto error;
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
|
@ -1018,13 +941,6 @@ found:
|
||||||
lstrcpyn32A( ofs->szPathName, full_name.short_name,
|
lstrcpyn32A( ofs->szPathName, full_name.short_name,
|
||||||
sizeof(ofs->szPathName) );
|
sizeof(ofs->szPathName) );
|
||||||
|
|
||||||
fileInUse = FILE_InUse(full_name.long_name,&oldMode);
|
|
||||||
if(fileInUse)
|
|
||||||
{
|
|
||||||
TRACE(file, "found another instance with mode 0x%02x\n",oldMode&0x70);
|
|
||||||
if (FILE_ShareDeny(mode,oldMode)) return HFILE_ERROR32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode & OF_SHARE_EXCLUSIVE)
|
if (mode & OF_SHARE_EXCLUSIVE)
|
||||||
/* Some InstallShield version uses OF_SHARE_EXCLUSIVE
|
/* Some InstallShield version uses OF_SHARE_EXCLUSIVE
|
||||||
on the file <tempdir>/_ins0432._mp to determine how
|
on the file <tempdir>/_ins0432._mp to determine how
|
||||||
|
@ -1054,16 +970,9 @@ found:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unixMode=FILE_DOSToUnixMode(mode);
|
hFileRet = FILE_CreateFile( full_name.long_name, access, sharing,
|
||||||
|
NULL, OPEN_EXISTING, 0, -1 );
|
||||||
hFileRet = FILE_OpenUnixFile( full_name.long_name, unixMode );
|
|
||||||
if (hFileRet == HFILE_ERROR32) goto not_found;
|
if (hFileRet == HFILE_ERROR32) goto not_found;
|
||||||
/* we need to save the mode, but only if it is not in use yet*/
|
|
||||||
if( (!fileInUse) &&(file =FILE_GetFile(hFileRet,0,NULL)))
|
|
||||||
{
|
|
||||||
file->mode=mode;
|
|
||||||
FILE_ReleaseFile(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
GetFileTime( hFileRet, NULL, NULL, &filetime );
|
GetFileTime( hFileRet, NULL, NULL, &filetime );
|
||||||
FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
|
FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
|
||||||
|
@ -1255,9 +1164,8 @@ UINT16 WINAPI _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count )
|
||||||
*/
|
*/
|
||||||
HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr )
|
HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr )
|
||||||
{
|
{
|
||||||
int mode = (attr & 1) ? 0444 : 0666;
|
|
||||||
TRACE(file, "%s %02x\n", path, attr );
|
TRACE(file, "%s %02x\n", path, attr );
|
||||||
return (HFILE16) HFILE32_TO_HFILE16(FILE_Create( path, mode, FALSE ));
|
return (HFILE16) HFILE32_TO_HFILE16(_lcreat32( path, attr ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1266,9 +1174,10 @@ HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr )
|
||||||
*/
|
*/
|
||||||
HFILE32 WINAPI _lcreat32( LPCSTR path, INT32 attr )
|
HFILE32 WINAPI _lcreat32( LPCSTR path, INT32 attr )
|
||||||
{
|
{
|
||||||
int mode = (attr & 1) ? 0444 : 0666;
|
|
||||||
TRACE(file, "%s %02x\n", path, attr );
|
TRACE(file, "%s %02x\n", path, attr );
|
||||||
return FILE_Create( path, mode, FALSE );
|
return CreateFile32A( path, GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||||
|
CREATE_ALWAYS, attr, -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1277,9 +1186,10 @@ HFILE32 WINAPI _lcreat32( LPCSTR path, INT32 attr )
|
||||||
*/
|
*/
|
||||||
HFILE32 _lcreat_uniq( LPCSTR path, INT32 attr )
|
HFILE32 _lcreat_uniq( LPCSTR path, INT32 attr )
|
||||||
{
|
{
|
||||||
int mode = (attr & 1) ? 0444 : 0666;
|
|
||||||
TRACE(file, "%s %02x\n", path, attr );
|
TRACE(file, "%s %02x\n", path, attr );
|
||||||
return FILE_Create( path, mode, TRUE );
|
return CreateFile32A( path, GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||||
|
CREATE_NEW, attr, -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1353,12 +1263,11 @@ HFILE16 WINAPI _lopen16( LPCSTR path, INT16 mode )
|
||||||
*/
|
*/
|
||||||
HFILE32 WINAPI _lopen32( LPCSTR path, INT32 mode )
|
HFILE32 WINAPI _lopen32( LPCSTR path, INT32 mode )
|
||||||
{
|
{
|
||||||
INT32 unixMode;
|
DWORD access, sharing;
|
||||||
|
|
||||||
TRACE(file, "('%s',%04x)\n", path, mode );
|
TRACE(file, "('%s',%04x)\n", path, mode );
|
||||||
|
FILE_ConvertOFMode( mode, &access, &sharing );
|
||||||
unixMode= FILE_DOSToUnixMode(mode);
|
return CreateFile32A( path, access, sharing, NULL, OPEN_EXISTING, 0, -1 );
|
||||||
return FILE_Open( path, unixMode , (mode & 0x70));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1572,19 +1481,6 @@ BOOL32 WINAPI DeleteFile32W( LPCWSTR path )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* FILE_SetFileType
|
|
||||||
*/
|
|
||||||
BOOL32 FILE_SetFileType( HFILE32 hFile, DWORD type )
|
|
||||||
{
|
|
||||||
FILE_OBJECT *file = FILE_GetFile( hFile, 0, NULL );
|
|
||||||
if (!file) return FALSE;
|
|
||||||
file->type = type;
|
|
||||||
FILE_ReleaseFile( file );
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FILE_dommap
|
* FILE_dommap
|
||||||
*/
|
*/
|
||||||
|
@ -1681,10 +1577,16 @@ int FILE_munmap( LPVOID start, DWORD size_high, DWORD size_low )
|
||||||
*/
|
*/
|
||||||
DWORD WINAPI GetFileType( HFILE32 hFile )
|
DWORD WINAPI GetFileType( HFILE32 hFile )
|
||||||
{
|
{
|
||||||
FILE_OBJECT *file = FILE_GetFile(hFile, 0, NULL);
|
struct get_file_info_request req;
|
||||||
if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
|
struct get_file_info_reply reply;
|
||||||
FILE_ReleaseFile( file );
|
|
||||||
return file->type;
|
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
|
||||||
|
K32OBJ_FILE, 0 )) == -1)
|
||||||
|
return FILE_TYPE_UNKNOWN;
|
||||||
|
CLIENT_SendRequest( REQ_GET_FILE_INFO, -1, 1, &req, sizeof(req) );
|
||||||
|
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ))
|
||||||
|
return FILE_TYPE_UNKNOWN;
|
||||||
|
return reply.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1859,7 +1761,9 @@ BOOL32 WINAPI CopyFile32A( LPCSTR source, LPCSTR dest, BOOL32 fail_if_exists )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
mode = (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
|
mode = (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
|
||||||
if ((h2 = FILE_Create( dest, mode, fail_if_exists )) == HFILE_ERROR32)
|
if ((h2 = CreateFile32A( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||||
|
fail_if_exists ? CREATE_NEW : CREATE_ALWAYS,
|
||||||
|
info.dwFileAttributes, h1 )) == HFILE_ERROR32)
|
||||||
{
|
{
|
||||||
CloseHandle( h1 );
|
CloseHandle( h1 );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1959,33 +1863,22 @@ BOOL32 WINAPI SetFileTime( HFILE32 hFile,
|
||||||
const FILETIME *lpLastAccessTime,
|
const FILETIME *lpLastAccessTime,
|
||||||
const FILETIME *lpLastWriteTime )
|
const FILETIME *lpLastWriteTime )
|
||||||
{
|
{
|
||||||
FILE_OBJECT *file = FILE_GetFile(hFile, 0, NULL);
|
struct set_file_time_request req;
|
||||||
struct utimbuf utimbuf;
|
|
||||||
|
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
|
||||||
if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
|
K32OBJ_FILE, GENERIC_WRITE )) == -1)
|
||||||
TRACE(file,"('%s',%p,%p,%p)\n",
|
return FALSE;
|
||||||
file->unix_name,
|
|
||||||
lpCreationTime,
|
|
||||||
lpLastAccessTime,
|
|
||||||
lpLastWriteTime
|
|
||||||
);
|
|
||||||
if (lpLastAccessTime)
|
if (lpLastAccessTime)
|
||||||
utimbuf.actime = DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
|
req.access_time = DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
|
||||||
else
|
else
|
||||||
utimbuf.actime = 0; /* FIXME */
|
req.access_time = 0; /* FIXME */
|
||||||
if (lpLastWriteTime)
|
if (lpLastWriteTime)
|
||||||
utimbuf.modtime = DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
|
req.write_time = DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
|
||||||
else
|
else
|
||||||
utimbuf.modtime = 0; /* FIXME */
|
req.write_time = 0; /* FIXME */
|
||||||
if (-1==utime(file->unix_name,&utimbuf))
|
|
||||||
{
|
CLIENT_SendRequest( REQ_SET_FILE_TIME, -1, 1, &req, sizeof(req) );
|
||||||
MSG("Couldn't set the time for file '%s'. Insufficient permissions !?\n", file->unix_name);
|
return !CLIENT_WaitReply( NULL, NULL, 0 );
|
||||||
FILE_ReleaseFile( file );
|
|
||||||
FILE_SetDosError();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
FILE_ReleaseFile( file );
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locks need to be mirrored because unix file locking is based
|
/* Locks need to be mirrored because unix file locking is based
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __WINE_DEVICE_H
|
#ifndef __WINE_DEVICE_H
|
||||||
#define __WINE_DEVICE_H
|
#define __WINE_DEVICE_H
|
||||||
extern HANDLE32 DEVICE_Open( LPCSTR name, DWORD flags);
|
extern HANDLE32 DEVICE_Open( LPCSTR name);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
K32OBJ header;
|
K32OBJ header;
|
||||||
int mode;
|
|
||||||
char *unix_name;
|
char *unix_name;
|
||||||
DWORD type; /* Type for win32 apps */
|
|
||||||
} FILE_OBJECT;
|
} FILE_OBJECT;
|
||||||
|
|
||||||
/* Definition of a full DOS file name */
|
/* Definition of a full DOS file name */
|
||||||
|
@ -60,15 +58,13 @@ typedef struct
|
||||||
extern FILE_OBJECT *FILE_GetFile( HFILE32 handle, DWORD access,
|
extern FILE_OBJECT *FILE_GetFile( HFILE32 handle, DWORD access,
|
||||||
int *server_handle );
|
int *server_handle );
|
||||||
extern void FILE_ReleaseFile( FILE_OBJECT *file );
|
extern void FILE_ReleaseFile( FILE_OBJECT *file );
|
||||||
extern HFILE32 FILE_Alloc( FILE_OBJECT **file, int unix_handle, const char *unix_name );
|
|
||||||
extern void FILE_SetDosError(void);
|
extern void FILE_SetDosError(void);
|
||||||
extern HFILE32 FILE_DupUnixHandle( int fd );
|
extern HFILE32 FILE_DupUnixHandle( int fd, DWORD access );
|
||||||
extern BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
|
extern BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
|
||||||
extern HFILE32 FILE_Dup( HFILE32 hFile );
|
|
||||||
extern HFILE32 FILE_Dup2( HFILE32 hFile1, HFILE32 hFile2 );
|
extern HFILE32 FILE_Dup2( HFILE32 hFile1, HFILE32 hFile2 );
|
||||||
extern HFILE32 FILE_Open( LPCSTR path, INT32 mode ,INT32 sharemode);
|
extern HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
|
||||||
extern HFILE32 FILE_OpenUnixFile( LPCSTR path, INT32 mode );
|
LPSECURITY_ATTRIBUTES sa, DWORD creation,
|
||||||
extern BOOL32 FILE_SetFileType( HFILE32 hFile, DWORD type );
|
DWORD attributes, HANDLE32 template );
|
||||||
extern LPVOID FILE_dommap( int unix_handle, LPVOID start,
|
extern LPVOID FILE_dommap( int unix_handle, LPVOID start,
|
||||||
DWORD size_high, DWORD size_low,
|
DWORD size_high, DWORD size_low,
|
||||||
DWORD offset_high, DWORD offset_low,
|
DWORD offset_high, DWORD offset_low,
|
||||||
|
@ -89,7 +85,7 @@ extern void DOSFS_UnixTimeToFileTime( time_t unixtime, LPFILETIME ft,
|
||||||
extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder );
|
extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder );
|
||||||
extern BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer );
|
extern BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer );
|
||||||
extern const DOS_DEVICE *DOSFS_GetDevice( const char *name );
|
extern const DOS_DEVICE *DOSFS_GetDevice( const char *name );
|
||||||
extern HFILE32 DOSFS_OpenDevice( const char *name, INT32 mode );
|
extern HFILE32 DOSFS_OpenDevice( const char *name, DWORD access );
|
||||||
extern BOOL32 DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
|
extern BOOL32 DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
|
||||||
INT32 long_len, LPSTR short_buf,
|
INT32 long_len, LPSTR short_buf,
|
||||||
BOOL32 ignore_case );
|
BOOL32 ignore_case );
|
||||||
|
|
|
@ -255,6 +255,10 @@ struct create_file_request
|
||||||
{
|
{
|
||||||
unsigned int access; /* wanted access rights */
|
unsigned int access; /* wanted access rights */
|
||||||
int inherit; /* inherit flag */
|
int inherit; /* inherit flag */
|
||||||
|
unsigned int sharing; /* sharing flags */
|
||||||
|
int create; /* file create action */
|
||||||
|
unsigned int attrs; /* file attributes for creation */
|
||||||
|
char name[0]; /* file name */
|
||||||
};
|
};
|
||||||
struct create_file_reply
|
struct create_file_reply
|
||||||
{
|
{
|
||||||
|
@ -298,6 +302,15 @@ struct truncate_file_request
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Set a file access and modification times */
|
||||||
|
struct set_file_time_request
|
||||||
|
{
|
||||||
|
int handle; /* handle to the file */
|
||||||
|
time_t access_time; /* last access time */
|
||||||
|
time_t write_time; /* last write time */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Flush a file buffers */
|
/* Flush a file buffers */
|
||||||
struct flush_file_request
|
struct flush_file_request
|
||||||
{
|
{
|
||||||
|
@ -312,6 +325,7 @@ struct get_file_info_request
|
||||||
};
|
};
|
||||||
struct get_file_info_reply
|
struct get_file_info_reply
|
||||||
{
|
{
|
||||||
|
int type; /* file type */
|
||||||
int attr; /* file attributes */
|
int attr; /* file attributes */
|
||||||
time_t access_time; /* last access time */
|
time_t access_time; /* last access time */
|
||||||
time_t write_time; /* last write time */
|
time_t write_time; /* last write time */
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct thread;
|
||||||
struct file;
|
struct file;
|
||||||
struct wait_queue_entry;
|
struct wait_queue_entry;
|
||||||
|
|
||||||
|
/* operations valid on all objects */
|
||||||
struct object_ops
|
struct object_ops
|
||||||
{
|
{
|
||||||
/* dump the object (for debugging) */
|
/* dump the object (for debugging) */
|
||||||
|
@ -40,7 +41,9 @@ struct object_ops
|
||||||
/* return a Unix fd that can be used to write to the object */
|
/* return a Unix fd that can be used to write to the object */
|
||||||
int (*get_write_fd)(struct object *);
|
int (*get_write_fd)(struct object *);
|
||||||
/* flush the object buffers */
|
/* flush the object buffers */
|
||||||
int (*flush)(struct object *);
|
int (*flush)(struct object *);
|
||||||
|
/* get file information */
|
||||||
|
int (*get_file_info)(struct object *,struct get_file_info_reply *);
|
||||||
/* destroy on refcount == 0 */
|
/* destroy on refcount == 0 */
|
||||||
void (*destroy)(struct object *);
|
void (*destroy)(struct object *);
|
||||||
};
|
};
|
||||||
|
@ -57,8 +60,8 @@ struct object
|
||||||
extern void *mem_alloc( size_t size ); /* malloc wrapper */
|
extern void *mem_alloc( size_t size ); /* malloc wrapper */
|
||||||
extern struct object *create_named_object( const char *name, const struct object_ops *ops,
|
extern struct object *create_named_object( const char *name, const struct object_ops *ops,
|
||||||
size_t size );
|
size_t size );
|
||||||
extern int init_object( struct object *obj, const struct object_ops *ops,
|
extern int init_object( struct object *obj, const struct object_ops *ops, const char *name );
|
||||||
const char *name );
|
extern const char *get_object_name( struct object *obj );
|
||||||
/* grab/release_object can take any pointer, but you better make sure */
|
/* grab/release_object can take any pointer, but you better make sure */
|
||||||
/* that the thing pointed to starts with a struct object... */
|
/* that the thing pointed to starts with a struct object... */
|
||||||
extern struct object *grab_object( void *obj );
|
extern struct object *grab_object( void *obj );
|
||||||
|
@ -69,6 +72,7 @@ extern int no_satisfied( struct object *obj, struct thread *thread );
|
||||||
extern int no_read_fd( struct object *obj );
|
extern int no_read_fd( struct object *obj );
|
||||||
extern int no_write_fd( struct object *obj );
|
extern int no_write_fd( struct object *obj );
|
||||||
extern int no_flush( struct object *obj );
|
extern int no_flush( struct object *obj );
|
||||||
|
extern int no_get_file_info( struct object *obj, struct get_file_info_reply *info );
|
||||||
extern void default_select_event( int fd, int event, void *private );
|
extern void default_select_event( int fd, int event, void *private );
|
||||||
|
|
||||||
/* request handlers */
|
/* request handlers */
|
||||||
|
@ -172,13 +176,14 @@ extern int release_semaphore( int handle, unsigned int count, unsigned int *prev
|
||||||
|
|
||||||
/* file functions */
|
/* file functions */
|
||||||
|
|
||||||
extern struct object *create_file( int fd );
|
extern struct object *create_file( int fd, const char *name, unsigned int access,
|
||||||
|
unsigned int sharing, int create, unsigned int attrs );
|
||||||
extern struct file *get_file_obj( struct process *process, int handle,
|
extern struct file *get_file_obj( struct process *process, int handle,
|
||||||
unsigned int access );
|
unsigned int access );
|
||||||
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 get_file_info( int handle, struct get_file_info_reply *reply );
|
extern int set_file_time( int handle, time_t access_time, time_t write_time );
|
||||||
extern void file_set_error(void);
|
extern void file_set_error(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ enum request
|
||||||
REQ_GET_WRITE_FD,
|
REQ_GET_WRITE_FD,
|
||||||
REQ_SET_FILE_POINTER,
|
REQ_SET_FILE_POINTER,
|
||||||
REQ_TRUNCATE_FILE,
|
REQ_TRUNCATE_FILE,
|
||||||
|
REQ_SET_FILE_TIME,
|
||||||
REQ_FLUSH_FILE,
|
REQ_FLUSH_FILE,
|
||||||
REQ_GET_FILE_INFO,
|
REQ_GET_FILE_INFO,
|
||||||
REQ_CREATE_PIPE,
|
REQ_CREATE_PIPE,
|
||||||
|
@ -67,6 +68,7 @@ DECL_HANDLER(get_read_fd);
|
||||||
DECL_HANDLER(get_write_fd);
|
DECL_HANDLER(get_write_fd);
|
||||||
DECL_HANDLER(set_file_pointer);
|
DECL_HANDLER(set_file_pointer);
|
||||||
DECL_HANDLER(truncate_file);
|
DECL_HANDLER(truncate_file);
|
||||||
|
DECL_HANDLER(set_file_time);
|
||||||
DECL_HANDLER(flush_file);
|
DECL_HANDLER(flush_file);
|
||||||
DECL_HANDLER(get_file_info);
|
DECL_HANDLER(get_file_info);
|
||||||
DECL_HANDLER(create_pipe);
|
DECL_HANDLER(create_pipe);
|
||||||
|
@ -103,6 +105,7 @@ static const struct handler {
|
||||||
{ (void(*)())req_get_write_fd, sizeof(struct get_write_fd_request) },
|
{ (void(*)())req_get_write_fd, sizeof(struct get_write_fd_request) },
|
||||||
{ (void(*)())req_set_file_pointer, sizeof(struct set_file_pointer_request) },
|
{ (void(*)())req_set_file_pointer, sizeof(struct set_file_pointer_request) },
|
||||||
{ (void(*)())req_truncate_file, sizeof(struct truncate_file_request) },
|
{ (void(*)())req_truncate_file, sizeof(struct truncate_file_request) },
|
||||||
|
{ (void(*)())req_set_file_time, sizeof(struct set_file_time_request) },
|
||||||
{ (void(*)())req_flush_file, sizeof(struct flush_file_request) },
|
{ (void(*)())req_flush_file, sizeof(struct flush_file_request) },
|
||||||
{ (void(*)())req_get_file_info, sizeof(struct get_file_info_request) },
|
{ (void(*)())req_get_file_info, sizeof(struct get_file_info_request) },
|
||||||
{ (void(*)())req_create_pipe, sizeof(struct create_pipe_request) },
|
{ (void(*)())req_create_pipe, sizeof(struct create_pipe_request) },
|
||||||
|
|
|
@ -397,7 +397,6 @@ BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
|
||||||
*/
|
*/
|
||||||
HANDLE32 NE_OpenFile( NE_MODULE *pModule )
|
HANDLE32 NE_OpenFile( NE_MODULE *pModule )
|
||||||
{
|
{
|
||||||
DOS_FULL_NAME full_name;
|
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
static HANDLE32 cachedfd = -1;
|
static HANDLE32 cachedfd = -1;
|
||||||
|
@ -408,8 +407,8 @@ HANDLE32 NE_OpenFile( NE_MODULE *pModule )
|
||||||
CloseHandle( cachedfd );
|
CloseHandle( cachedfd );
|
||||||
pCachedModule = pModule;
|
pCachedModule = pModule;
|
||||||
name = NE_MODULE_NAME( pModule );
|
name = NE_MODULE_NAME( pModule );
|
||||||
if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
|
if ((cachedfd = CreateFile32A( name, GENERIC_READ, FILE_SHARE_READ,
|
||||||
(cachedfd = FILE_OpenUnixFile( full_name.long_name, O_RDONLY )) == -1)
|
NULL, OPEN_EXISTING, 0, -1 )) == -1)
|
||||||
MSG( "Can't open file '%s' for module %04x\n", name, pModule->self );
|
MSG( "Can't open file '%s' for module %04x\n", name, pModule->self );
|
||||||
else
|
else
|
||||||
/* FIXME: should not be necessary */
|
/* FIXME: should not be necessary */
|
||||||
|
|
|
@ -475,7 +475,7 @@ static HMODULE32 PE_LoadImage( LPCSTR name, OFSTRUCT *ofs )
|
||||||
if (!strchr( p, '.' )) strcat( dllname, ".DLL" );
|
if (!strchr( p, '.' )) strcat( dllname, ".DLL" );
|
||||||
|
|
||||||
/* Open PE file */
|
/* Open PE file */
|
||||||
hFile = OpenFile32( dllname, ofs, OF_READ );
|
hFile = OpenFile32( dllname, ofs, OF_READ | OF_SHARE_DENY_WRITE );
|
||||||
if ( hFile == HFILE_ERROR32 )
|
if ( hFile == HFILE_ERROR32 )
|
||||||
{
|
{
|
||||||
WARN( win32, "OpenFile error %ld\n", GetLastError() );
|
WARN( win32, "OpenFile error %ld\n", GetLastError() );
|
||||||
|
@ -868,7 +868,7 @@ HINSTANCE16 PE_CreateProcess( LPCSTR name, LPCSTR cmd_line,
|
||||||
if ((hModule32 = PE_LoadImage( name, &ofs )) < 32)
|
if ((hModule32 = PE_LoadImage( name, &ofs )) < 32)
|
||||||
return hModule32;
|
return hModule32;
|
||||||
if (PE_HEADER(hModule32)->FileHeader.Characteristics & IMAGE_FILE_DLL)
|
if (PE_HEADER(hModule32)->FileHeader.Characteristics & IMAGE_FILE_DLL)
|
||||||
return 11;
|
return 20; /* FIXME: not the right error code */
|
||||||
|
|
||||||
/* Create 16-bit dummy module */
|
/* Create 16-bit dummy module */
|
||||||
if ((hModule16 = MODULE_CreateDummyModule( &ofs )) < 32) return hModule16;
|
if ((hModule16 = MODULE_CreateDummyModule( &ofs )) < 32) return hModule16;
|
||||||
|
|
|
@ -296,23 +296,37 @@ CRTDLL_FILE * __cdecl CRTDLL_fopen(LPCSTR path, LPCSTR mode)
|
||||||
|
|
||||||
file=fopen(full_name.long_name ,mode);
|
file=fopen(full_name.long_name ,mode);
|
||||||
#endif
|
#endif
|
||||||
INT32 flagmode=0;
|
DWORD access = 0, creation = 0;
|
||||||
|
|
||||||
if ((strchr(mode,'r')&&strchr(mode,'a'))||
|
if ((strchr(mode,'r')&&strchr(mode,'a'))||
|
||||||
(strchr(mode,'r')&&strchr(mode,'w'))||
|
(strchr(mode,'r')&&strchr(mode,'w'))||
|
||||||
(strchr(mode,'w')&&strchr(mode,'a')))
|
(strchr(mode,'w')&&strchr(mode,'a')))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (strstr(mode,"r+")) flagmode=O_RDWR;
|
if (mode[0] == 'r')
|
||||||
else if (strchr(mode,'r')) flagmode = O_RDONLY;
|
{
|
||||||
else if (strstr(mode,"w+")) flagmode= O_RDWR | O_TRUNC | O_CREAT;
|
access = GENERIC_READ;
|
||||||
else if (strchr(mode,'w')) flagmode = O_WRONLY | O_TRUNC | O_CREAT;
|
creation = OPEN_EXISTING;
|
||||||
else if (strstr(mode,"a+")) flagmode= O_RDWR | O_CREAT | O_APPEND;
|
if (mode[1] == '+') access |= GENERIC_WRITE;
|
||||||
else if (strchr(mode,'w')) flagmode = O_RDWR | O_CREAT | O_APPEND;
|
}
|
||||||
else if (strchr(mode,'b'))
|
else if (mode[0] == 'w')
|
||||||
TRACE(crtdll, "%s in BINARY mode\n",path);
|
{
|
||||||
|
access = GENERIC_WRITE;
|
||||||
if ((handle = FILE_Open(path, flagmode,0)) != INVALID_HANDLE_VALUE32)
|
creation = CREATE_ALWAYS;
|
||||||
|
if (mode[1] == '+') access |= GENERIC_READ;
|
||||||
|
}
|
||||||
|
else if (mode[0] == 'a')
|
||||||
|
{
|
||||||
|
/* FIXME: there is no O_APPEND in CreateFile, should emulate it */
|
||||||
|
access = GENERIC_WRITE;
|
||||||
|
creation = OPEN_ALWAYS;
|
||||||
|
if (mode[1] == '+') access |= GENERIC_READ;
|
||||||
|
}
|
||||||
|
/* FIXME: should handle text/binary mode */
|
||||||
|
|
||||||
|
if ((handle = CreateFile32A( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
NULL, creation, FILE_ATTRIBUTE_NORMAL,
|
||||||
|
-1 )) != INVALID_HANDLE_VALUE32)
|
||||||
{
|
{
|
||||||
file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
|
file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
|
||||||
file->handle = handle;
|
file->handle = handle;
|
||||||
|
@ -1181,8 +1195,8 @@ int __cdecl CRTDLL__stat(const char * filename, struct win_stat * buf)
|
||||||
*/
|
*/
|
||||||
HFILE32 __cdecl CRTDLL__open(LPCSTR path,INT32 flags)
|
HFILE32 __cdecl CRTDLL__open(LPCSTR path,INT32 flags)
|
||||||
{
|
{
|
||||||
HFILE32 ret=0;
|
DWORD access = 0, creation = 0;
|
||||||
int wineflags=0;
|
HFILE32 ret;
|
||||||
|
|
||||||
/* FIXME:
|
/* FIXME:
|
||||||
the flags in lcc's header differ from the ones in Linux, e.g.
|
the flags in lcc's header differ from the ones in Linux, e.g.
|
||||||
|
@ -1191,18 +1205,38 @@ HFILE32 __cdecl CRTDLL__open(LPCSTR path,INT32 flags)
|
||||||
so here a scheme to translate them
|
so here a scheme to translate them
|
||||||
Probably lcc is wrong here, but at least a hack to get is going
|
Probably lcc is wrong here, but at least a hack to get is going
|
||||||
*/
|
*/
|
||||||
wineflags = (flags & 3);
|
switch(flags & 3)
|
||||||
if (flags & 0x0008 ) wineflags |= O_APPEND;
|
{
|
||||||
if (flags & 0x0100 ) wineflags |= O_CREAT;
|
case O_RDONLY: access |= GENERIC_READ; break;
|
||||||
if (flags & 0x0200 ) wineflags |= O_TRUNC;
|
case O_WRONLY: access |= GENERIC_WRITE; break;
|
||||||
if (flags & 0x0400 ) wineflags |= O_EXCL;
|
case O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
|
||||||
if (flags & 0xf0f4 )
|
}
|
||||||
|
|
||||||
|
if (flags & 0x0100) /* O_CREAT */
|
||||||
|
{
|
||||||
|
if (flags & 0x0400) /* O_EXCL */
|
||||||
|
creation = CREATE_NEW;
|
||||||
|
else if (flags & 0x0200) /* O_TRUNC */
|
||||||
|
creation = CREATE_ALWAYS;
|
||||||
|
else
|
||||||
|
creation = OPEN_ALWAYS;
|
||||||
|
}
|
||||||
|
else /* no O_CREAT */
|
||||||
|
{
|
||||||
|
if (flags & 0x0200) /* O_TRUNC */
|
||||||
|
creation = TRUNCATE_EXISTING;
|
||||||
|
else
|
||||||
|
creation = OPEN_EXISTING;
|
||||||
|
}
|
||||||
|
if (flags & 0x0008) /* O_APPEND */
|
||||||
|
FIXME(crtdll, "O_APPEND not supported\n" );
|
||||||
|
if (flags & 0xf0f4)
|
||||||
TRACE(crtdll,"CRTDLL_open file unsupported flags 0x%04x\n",flags);
|
TRACE(crtdll,"CRTDLL_open file unsupported flags 0x%04x\n",flags);
|
||||||
/* End Fixme */
|
/* End Fixme */
|
||||||
|
|
||||||
ret = FILE_Open(path,wineflags,0);
|
ret = CreateFile32A( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
TRACE(crtdll,"CRTDLL_open file %s mode 0x%04x (lccmode 0x%04x) got dfh %d\n",
|
NULL, creation, FILE_ATTRIBUTE_NORMAL, -1 );
|
||||||
path,wineflags,flags,ret);
|
TRACE(crtdll,"CRTDLL_open file %s mode 0x%04x got handle %d\n", path,flags,ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1635,9 +1635,18 @@ void WINAPI DOS3Call( CONTEXT *context )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
|
case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
|
||||||
TRACE(int21,"DUP - DUPLICATE FILE HANDLE %d\n",BX_reg(context));
|
{
|
||||||
bSetDOSExtendedError = ((AX_reg(context) = HFILE32_TO_HFILE16(FILE_Dup(HFILE16_TO_HFILE32(BX_reg(context))))) == (WORD)HFILE_ERROR16);
|
HANDLE32 handle;
|
||||||
break;
|
TRACE(int21,"DUP - DUPLICATE FILE HANDLE %d\n",BX_reg(context));
|
||||||
|
if ((bSetDOSExtendedError = !DuplicateHandle( GetCurrentProcess(),
|
||||||
|
HFILE16_TO_HFILE32(BX_reg(context)),
|
||||||
|
GetCurrentProcess(), &handle,
|
||||||
|
0, TRUE, DUPLICATE_SAME_ACCESS )))
|
||||||
|
AX_reg(context) = HFILE_ERROR16;
|
||||||
|
else
|
||||||
|
AX_reg(context) = HFILE32_TO_HFILE16(handle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
|
case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
|
||||||
TRACE(int21,"FORCEDUP - FORCE DUPLICATE FILE HANDLE %d to %d\n",
|
TRACE(int21,"FORCEDUP - FORCE DUPLICATE FILE HANDLE %d to %d\n",
|
||||||
|
|
|
@ -687,7 +687,7 @@ void VXD_Win32s( CONTEXT *context )
|
||||||
IMAGE_NT_HEADERS *nt_header = PE_HEADER(module->baseAddr);
|
IMAGE_NT_HEADERS *nt_header = PE_HEADER(module->baseAddr);
|
||||||
IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(module->baseAddr);
|
IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(module->baseAddr);
|
||||||
|
|
||||||
HFILE32 image = FILE_Open(module->pathName, O_RDONLY,0);
|
HFILE32 image = _lopen32(module->pathName, OF_READ);
|
||||||
BOOL32 error = (image == INVALID_HANDLE_VALUE32);
|
BOOL32 error = (image == INVALID_HANDLE_VALUE32);
|
||||||
UINT32 i;
|
UINT32 i;
|
||||||
|
|
||||||
|
|
|
@ -1378,7 +1378,8 @@ HRESULT WINAPI IStorage16_fnCreateStream(
|
||||||
FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
|
FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
|
||||||
_create_istream16(ppstm);
|
_create_istream16(ppstm);
|
||||||
lpstr = (_IStream16*)PTR_SEG_TO_LIN(*ppstm);
|
lpstr = (_IStream16*)PTR_SEG_TO_LIN(*ppstm);
|
||||||
lpstr->hf = FILE_Dup(this->hf);
|
DuplicateHandle( GetCurrentProcess(), this->hf, GetCurrentProcess(),
|
||||||
|
&lpstr->hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||||
lpstr->offset.LowPart = 0;
|
lpstr->offset.LowPart = 0;
|
||||||
lpstr->offset.HighPart = 0;
|
lpstr->offset.HighPart = 0;
|
||||||
|
|
||||||
|
@ -1430,7 +1431,8 @@ HRESULT WINAPI IStorage16_fnOpenStorage(
|
||||||
FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
|
FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
|
||||||
_create_istorage16(ppstg);
|
_create_istorage16(ppstg);
|
||||||
lpstg = (_IStream16*)PTR_SEG_TO_LIN(*ppstg);
|
lpstg = (_IStream16*)PTR_SEG_TO_LIN(*ppstg);
|
||||||
lpstg->hf = FILE_Dup(this->hf);
|
DuplicateHandle( GetCurrentProcess(), this->hf, GetCurrentProcess(),
|
||||||
|
&lpstg->hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||||
lstrcpyAtoW(name,pwcsName);
|
lstrcpyAtoW(name,pwcsName);
|
||||||
newpps = STORAGE_look_for_named_pps(lpstg->hf,this->stde.pps_dir,name);
|
newpps = STORAGE_look_for_named_pps(lpstg->hf,this->stde.pps_dir,name);
|
||||||
if (newpps==-1) {
|
if (newpps==-1) {
|
||||||
|
@ -1464,7 +1466,8 @@ HRESULT WINAPI IStorage16_fnOpenStream(
|
||||||
FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
|
FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
|
||||||
_create_istream16(ppstm);
|
_create_istream16(ppstm);
|
||||||
lpstr = (_IStream16*)PTR_SEG_TO_LIN(*ppstm);
|
lpstr = (_IStream16*)PTR_SEG_TO_LIN(*ppstm);
|
||||||
lpstr->hf = FILE_Dup(this->hf);
|
DuplicateHandle( GetCurrentProcess(), this->hf, GetCurrentProcess(),
|
||||||
|
&lpstr->hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||||
lstrcpyAtoW(name,pwcsName);
|
lstrcpyAtoW(name,pwcsName);
|
||||||
newpps = STORAGE_look_for_named_pps(lpstr->hf,this->stde.pps_dir,name);
|
newpps = STORAGE_look_for_named_pps(lpstr->hf,this->stde.pps_dir,name);
|
||||||
if (newpps==-1) {
|
if (newpps==-1) {
|
||||||
|
|
|
@ -108,12 +108,9 @@ static BOOL32 PROCESS_BuildEnvDB( PDB32 *pdb )
|
||||||
|
|
||||||
/* Allocate the standard handles */
|
/* Allocate the standard handles */
|
||||||
|
|
||||||
pdb->env_db->hStdin = FILE_DupUnixHandle( 0 );
|
pdb->env_db->hStdin = FILE_DupUnixHandle( 0, GENERIC_READ );
|
||||||
pdb->env_db->hStdout = FILE_DupUnixHandle( 1 );
|
pdb->env_db->hStdout = FILE_DupUnixHandle( 1, GENERIC_WRITE );
|
||||||
pdb->env_db->hStderr = FILE_DupUnixHandle( 2 );
|
pdb->env_db->hStderr = FILE_DupUnixHandle( 2, GENERIC_WRITE );
|
||||||
FILE_SetFileType( pdb->env_db->hStdin, FILE_TYPE_CHAR );
|
|
||||||
FILE_SetFileType( pdb->env_db->hStdout, FILE_TYPE_CHAR );
|
|
||||||
FILE_SetFileType( pdb->env_db->hStderr, FILE_TYPE_CHAR );
|
|
||||||
|
|
||||||
/* Build the command-line */
|
/* Build the command-line */
|
||||||
|
|
||||||
|
@ -661,46 +658,19 @@ DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* GetStdHandle (KERNEL32.276)
|
* GetStdHandle (KERNEL32.276)
|
||||||
*
|
|
||||||
* FIXME: These should be allocated when a console is created, or inherited
|
|
||||||
* from the parent.
|
|
||||||
*/
|
*/
|
||||||
HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
|
HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
|
||||||
{
|
{
|
||||||
HFILE32 hFile;
|
|
||||||
int fd;
|
|
||||||
PDB32 *pdb = PROCESS_Current();
|
PDB32 *pdb = PROCESS_Current();
|
||||||
|
|
||||||
switch(std_handle)
|
switch(std_handle)
|
||||||
{
|
{
|
||||||
case STD_INPUT_HANDLE:
|
case STD_INPUT_HANDLE: return pdb->env_db->hStdin;
|
||||||
if (pdb->env_db->hStdin) return pdb->env_db->hStdin;
|
case STD_OUTPUT_HANDLE: return pdb->env_db->hStdout;
|
||||||
fd = 0;
|
case STD_ERROR_HANDLE: return pdb->env_db->hStderr;
|
||||||
break;
|
|
||||||
case STD_OUTPUT_HANDLE:
|
|
||||||
if (pdb->env_db->hStdout) return pdb->env_db->hStdout;
|
|
||||||
fd = 1;
|
|
||||||
break;
|
|
||||||
case STD_ERROR_HANDLE:
|
|
||||||
if (pdb->env_db->hStderr) return pdb->env_db->hStderr;
|
|
||||||
fd = 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SetLastError( ERROR_INVALID_PARAMETER );
|
|
||||||
return INVALID_HANDLE_VALUE32;
|
|
||||||
}
|
}
|
||||||
hFile = FILE_DupUnixHandle( fd );
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||||||
if (hFile != HFILE_ERROR32)
|
return INVALID_HANDLE_VALUE32;
|
||||||
{
|
|
||||||
FILE_SetFileType( hFile, FILE_TYPE_CHAR );
|
|
||||||
switch(std_handle)
|
|
||||||
{
|
|
||||||
case STD_INPUT_HANDLE: pdb->env_db->hStdin = hFile; break;
|
|
||||||
case STD_OUTPUT_HANDLE: pdb->env_db->hStdout = hFile; break;
|
|
||||||
case STD_ERROR_HANDLE: pdb->env_db->hStderr = hFile; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ static const struct object_ops change_ops =
|
||||||
no_read_fd,
|
no_read_fd,
|
||||||
no_write_fd,
|
no_write_fd,
|
||||||
no_flush,
|
no_flush,
|
||||||
|
no_get_file_info,
|
||||||
change_destroy
|
change_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,8 +52,8 @@ static void change_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct change *change = (struct change *)obj;
|
struct change *change = (struct change *)obj;
|
||||||
assert( obj->ops == &change_ops );
|
assert( obj->ops == &change_ops );
|
||||||
printf( "Change notification sub=%d filter=%08x\n",
|
fprintf( stderr, "Change notification sub=%d filter=%08x\n",
|
||||||
change->subtree, change->filter );
|
change->subtree, change->filter );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int change_signaled( struct object *obj, struct thread *thread )
|
static int change_signaled( struct object *obj, struct thread *thread )
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
|
@ -35,6 +36,7 @@ static void console_remove_queue( struct object *obj, struct wait_queue_entry *e
|
||||||
static int console_signaled( struct object *obj, struct thread *thread );
|
static int console_signaled( struct object *obj, struct thread *thread );
|
||||||
static int console_get_read_fd( struct object *obj );
|
static int console_get_read_fd( struct object *obj );
|
||||||
static int console_get_write_fd( struct object *obj );
|
static int console_get_write_fd( struct object *obj );
|
||||||
|
static int console_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||||
static void console_destroy( struct object *obj );
|
static void console_destroy( struct object *obj );
|
||||||
|
|
||||||
static const struct object_ops console_ops =
|
static const struct object_ops console_ops =
|
||||||
|
@ -47,6 +49,7 @@ static const struct object_ops console_ops =
|
||||||
console_get_read_fd,
|
console_get_read_fd,
|
||||||
console_get_write_fd,
|
console_get_write_fd,
|
||||||
no_flush,
|
no_flush,
|
||||||
|
console_get_info,
|
||||||
console_destroy
|
console_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,8 +123,8 @@ static void console_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct console *console = (struct console *)obj;
|
struct console *console = (struct console *)obj;
|
||||||
assert( obj->ops == &console_ops );
|
assert( obj->ops == &console_ops );
|
||||||
printf( "Console %s fd=%d\n",
|
fprintf( stderr, "Console %s fd=%d\n",
|
||||||
console->is_read ? "input" : "output", console->fd );
|
console->is_read ? "input" : "output", console->fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int console_add_queue( struct object *obj, struct wait_queue_entry *entry )
|
static int console_add_queue( struct object *obj, struct wait_queue_entry *entry )
|
||||||
|
@ -194,6 +197,13 @@ static int console_get_write_fd( struct object *obj )
|
||||||
return dup( console->fd );
|
return dup( console->fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int console_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||||
|
{
|
||||||
|
memset( reply, 0, sizeof(*reply) );
|
||||||
|
reply->type = FILE_TYPE_CHAR;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void console_destroy( struct object *obj )
|
static void console_destroy( struct object *obj )
|
||||||
{
|
{
|
||||||
struct console *console = (struct console *)obj;
|
struct console *console = (struct console *)obj;
|
||||||
|
|
|
@ -34,6 +34,7 @@ static const struct object_ops event_ops =
|
||||||
no_read_fd,
|
no_read_fd,
|
||||||
no_write_fd,
|
no_write_fd,
|
||||||
no_flush,
|
no_flush,
|
||||||
|
no_get_file_info,
|
||||||
event_destroy
|
event_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,7 +104,9 @@ static void event_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct event *event = (struct event *)obj;
|
struct event *event = (struct event *)obj;
|
||||||
assert( obj->ops == &event_ops );
|
assert( obj->ops == &event_ops );
|
||||||
printf( "Event manual=%d signaled=%d\n", event->manual_reset, event->signaled );
|
fprintf( stderr, "Event manual=%d signaled=%d name='%s'\n",
|
||||||
|
event->manual_reset, event->signaled,
|
||||||
|
get_object_name( &event->obj ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int event_signaled( struct object *obj, struct thread *thread )
|
static int event_signaled( struct object *obj, struct thread *thread )
|
||||||
|
|
231
server/file.c
231
server/file.c
|
@ -15,6 +15,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <utime.h>
|
||||||
|
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
|
@ -23,10 +24,18 @@
|
||||||
struct file
|
struct file
|
||||||
{
|
{
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
|
struct file *next; /* next file in hashing list */
|
||||||
|
char *name; /* file name */
|
||||||
int fd; /* Unix file descriptor */
|
int fd; /* Unix file descriptor */
|
||||||
int event; /* possible events on this file */
|
unsigned int access; /* file access (GENERIC_READ/WRITE) */
|
||||||
|
unsigned int flags; /* flags (FILE_FLAG_*) */
|
||||||
|
unsigned int sharing; /* file sharing mode */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NAME_HASH_SIZE 37
|
||||||
|
|
||||||
|
static struct file *file_hash[NAME_HASH_SIZE];
|
||||||
|
|
||||||
static void file_dump( struct object *obj, int verbose );
|
static void file_dump( struct object *obj, int verbose );
|
||||||
static int file_add_queue( struct object *obj, struct wait_queue_entry *entry );
|
static int file_add_queue( struct object *obj, struct wait_queue_entry *entry );
|
||||||
static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry );
|
static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry );
|
||||||
|
@ -34,6 +43,7 @@ static int file_signaled( struct object *obj, struct thread *thread );
|
||||||
static int file_get_read_fd( struct object *obj );
|
static int file_get_read_fd( struct object *obj );
|
||||||
static int file_get_write_fd( struct object *obj );
|
static int file_get_write_fd( struct object *obj );
|
||||||
static int file_flush( struct object *obj );
|
static int file_flush( struct object *obj );
|
||||||
|
static int file_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||||
static void file_destroy( struct object *obj );
|
static void file_destroy( struct object *obj );
|
||||||
|
|
||||||
static const struct object_ops file_ops =
|
static const struct object_ops file_ops =
|
||||||
|
@ -46,6 +56,7 @@ static const struct object_ops file_ops =
|
||||||
file_get_read_fd,
|
file_get_read_fd,
|
||||||
file_get_write_fd,
|
file_get_write_fd,
|
||||||
file_flush,
|
file_flush,
|
||||||
|
file_get_info,
|
||||||
file_destroy
|
file_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,31 +66,134 @@ static const struct select_ops select_ops =
|
||||||
NULL /* we never set a timeout on a file */
|
NULL /* we never set a timeout on a file */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct object *create_file( int fd )
|
|
||||||
|
static int get_name_hash( const char *name )
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
while (*name) hash ^= *name++;
|
||||||
|
return hash % NAME_HASH_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if the desired access is possible without violating */
|
||||||
|
/* the sharing mode of other opens of the same file */
|
||||||
|
static int check_sharing( const char *name, int hash, unsigned int access,
|
||||||
|
unsigned int sharing )
|
||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int flags;
|
unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||||
|
unsigned int existing_access = 0;
|
||||||
|
|
||||||
if ((flags = fcntl( fd, F_GETFL )) == -1)
|
for (file = file_hash[hash]; file; file = file->next)
|
||||||
{
|
{
|
||||||
perror( "fcntl" );
|
if (strcmp( file->name, name )) continue;
|
||||||
|
existing_sharing &= file->sharing;
|
||||||
|
existing_access |= file->access;
|
||||||
|
}
|
||||||
|
if ((access & GENERIC_READ) && !(existing_sharing & FILE_SHARE_READ)) return 0;
|
||||||
|
if ((access & GENERIC_WRITE) && !(existing_sharing & FILE_SHARE_WRITE)) return 0;
|
||||||
|
if ((existing_access & GENERIC_READ) && !(sharing & FILE_SHARE_READ)) return 0;
|
||||||
|
if ((existing_access & GENERIC_WRITE) && !(sharing & FILE_SHARE_WRITE)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct object *create_file( int fd, const char *name, unsigned int access,
|
||||||
|
unsigned int sharing, int create, unsigned int attrs )
|
||||||
|
{
|
||||||
|
struct file *file;
|
||||||
|
int hash = 0;
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
SET_ERROR( ERROR_INVALID_PARAMETER );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check sharing mode */
|
||||||
|
hash = get_name_hash( name );
|
||||||
|
if (!check_sharing( name, hash, access, sharing ))
|
||||||
|
{
|
||||||
|
SET_ERROR( ERROR_SHARING_VIOLATION );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(create)
|
||||||
|
{
|
||||||
|
case CREATE_NEW: flags = O_CREAT | O_EXCL; break;
|
||||||
|
case CREATE_ALWAYS: flags = O_CREAT | O_TRUNC; break;
|
||||||
|
case OPEN_ALWAYS: flags = O_CREAT; break;
|
||||||
|
case TRUNCATE_EXISTING: flags = O_TRUNC; break;
|
||||||
|
case OPEN_EXISTING: flags = 0; break;
|
||||||
|
default: SET_ERROR( ERROR_INVALID_PARAMETER ); return NULL;
|
||||||
|
}
|
||||||
|
switch(access & (GENERIC_READ | GENERIC_WRITE))
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case GENERIC_READ: flags |= O_RDONLY; break;
|
||||||
|
case GENERIC_WRITE: flags |= O_WRONLY; break;
|
||||||
|
case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fd = open( name, flags | O_NONBLOCK,
|
||||||
|
(attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666 )) == -1)
|
||||||
|
{
|
||||||
|
file_set_error();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Refuse to open a directory */
|
||||||
|
if (fstat( fd, &st ) == -1)
|
||||||
|
{
|
||||||
|
file_set_error();
|
||||||
|
close( fd );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (S_ISDIR(st.st_mode))
|
||||||
|
{
|
||||||
|
SET_ERROR( ERROR_ACCESS_DENIED );
|
||||||
|
close( fd );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((fd = dup(fd)) == -1)
|
||||||
|
{
|
||||||
|
file_set_error();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(file = mem_alloc( sizeof(*file) )))
|
||||||
|
{
|
||||||
|
close( fd );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!(file = mem_alloc( sizeof(*file) ))) return NULL;
|
if (name)
|
||||||
init_object( &file->obj, &file_ops, NULL );
|
|
||||||
file->fd = fd;
|
|
||||||
switch(flags & 3)
|
|
||||||
{
|
{
|
||||||
case O_RDONLY:
|
if (!(file->name = mem_alloc( strlen(name) + 1 )))
|
||||||
file->event = READ_EVENT;
|
{
|
||||||
break;
|
close( fd );
|
||||||
case O_WRONLY:
|
free( file );
|
||||||
file->event = WRITE_EVENT;
|
return NULL;
|
||||||
break;
|
}
|
||||||
case O_RDWR:
|
strcpy( file->name, name );
|
||||||
file->event = READ_EVENT | WRITE_EVENT;
|
file->next = file_hash[hash];
|
||||||
break;
|
file_hash[hash] = file;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file->name = NULL;
|
||||||
|
file->next = NULL;
|
||||||
|
}
|
||||||
|
init_object( &file->obj, &file_ops, NULL );
|
||||||
|
file->fd = fd;
|
||||||
|
file->access = access;
|
||||||
|
file->flags = attrs;
|
||||||
|
file->sharing = sharing;
|
||||||
CLEAR_ERROR();
|
CLEAR_ERROR();
|
||||||
return &file->obj;
|
return &file->obj;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +202,8 @@ static void file_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct file *file = (struct file *)obj;
|
struct file *file = (struct file *)obj;
|
||||||
assert( obj->ops == &file_ops );
|
assert( obj->ops == &file_ops );
|
||||||
printf( "File fd=%d\n", file->fd );
|
printf( "File fd=%d flags=%08x name='%s'\n",
|
||||||
|
file->fd, file->flags, file->name );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int file_add_queue( struct object *obj, struct wait_queue_entry *entry )
|
static int file_add_queue( struct object *obj, struct wait_queue_entry *entry )
|
||||||
|
@ -128,8 +243,8 @@ static int file_signaled( struct object *obj, struct thread *thread )
|
||||||
|
|
||||||
FD_ZERO( &read_fds );
|
FD_ZERO( &read_fds );
|
||||||
FD_ZERO( &write_fds );
|
FD_ZERO( &write_fds );
|
||||||
if (file->event & READ_EVENT) FD_SET( file->fd, &read_fds );
|
if (file->access & GENERIC_READ) FD_SET( file->fd, &read_fds );
|
||||||
if (file->event & WRITE_EVENT) FD_SET( file->fd, &write_fds );
|
if (file->access & GENERIC_WRITE) FD_SET( file->fd, &write_fds );
|
||||||
return select( file->fd + 1, &read_fds, &write_fds, NULL, &tv ) > 0;
|
return select( file->fd + 1, &read_fds, &write_fds, NULL, &tv ) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,12 +252,6 @@ static int file_get_read_fd( struct object *obj )
|
||||||
{
|
{
|
||||||
struct file *file = (struct file *)obj;
|
struct file *file = (struct file *)obj;
|
||||||
assert( obj->ops == &file_ops );
|
assert( obj->ops == &file_ops );
|
||||||
|
|
||||||
if (!(file->event & READ_EVENT)) /* FIXME: should not be necessary */
|
|
||||||
{
|
|
||||||
SET_ERROR( ERROR_ACCESS_DENIED );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return dup( file->fd );
|
return dup( file->fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,12 +259,6 @@ static int file_get_write_fd( struct object *obj )
|
||||||
{
|
{
|
||||||
struct file *file = (struct file *)obj;
|
struct file *file = (struct file *)obj;
|
||||||
assert( obj->ops == &file_ops );
|
assert( obj->ops == &file_ops );
|
||||||
|
|
||||||
if (!(file->event & WRITE_EVENT)) /* FIXME: should not be necessary */
|
|
||||||
{
|
|
||||||
SET_ERROR( ERROR_ACCESS_DENIED );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return dup( file->fd );
|
return dup( file->fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,11 +274,48 @@ static int file_flush( struct object *obj )
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_destroy( struct object *obj )
|
static int file_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||||
{
|
{
|
||||||
|
struct stat st;
|
||||||
struct file *file = (struct file *)obj;
|
struct file *file = (struct file *)obj;
|
||||||
assert( obj->ops == &file_ops );
|
assert( obj->ops == &file_ops );
|
||||||
|
|
||||||
|
if (fstat( file->fd, &st ) == -1)
|
||||||
|
{
|
||||||
|
file_set_error();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
|
||||||
|
S_ISSOCK(st.st_mode) || isatty(file->fd)) reply->type = FILE_TYPE_CHAR;
|
||||||
|
else reply->type = FILE_TYPE_DISK;
|
||||||
|
if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
else reply->attr = FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
if (!(st.st_mode & S_IWUSR)) reply->attr |= FILE_ATTRIBUTE_READONLY;
|
||||||
|
reply->access_time = st.st_atime;
|
||||||
|
reply->write_time = st.st_mtime;
|
||||||
|
reply->size_high = 0;
|
||||||
|
reply->size_low = S_ISDIR(st.st_mode) ? 0 : st.st_size;
|
||||||
|
reply->links = st.st_nlink;
|
||||||
|
reply->index_high = st.st_dev;
|
||||||
|
reply->index_low = st.st_ino;
|
||||||
|
reply->serial = 0; /* FIXME */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void file_destroy( struct object *obj )
|
||||||
|
{
|
||||||
|
struct file **pptr;
|
||||||
|
struct file *file = (struct file *)obj;
|
||||||
|
assert( obj->ops == &file_ops );
|
||||||
|
|
||||||
|
/* remove it from the hashing list */
|
||||||
|
pptr = &file_hash[get_name_hash( file->name )];
|
||||||
|
while (*pptr && *pptr != file) pptr = &(*pptr)->next;
|
||||||
|
assert( *pptr );
|
||||||
|
*pptr = (*pptr)->next;
|
||||||
|
|
||||||
close( file->fd );
|
close( file->fd );
|
||||||
|
free( file->name );
|
||||||
free( file );
|
free( file );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,31 +403,22 @@ int truncate_file( int handle )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_file_info( int handle, struct get_file_info_reply *reply )
|
int set_file_time( int handle, time_t access_time, time_t write_time )
|
||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
struct stat st;
|
struct utimbuf utimbuf;
|
||||||
|
|
||||||
if (!(file = get_file_obj( current->process, handle, 0 )))
|
if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
|
||||||
return 0;
|
return 0;
|
||||||
if (fstat( file->fd, &st ) == -1)
|
utimbuf.actime = access_time;
|
||||||
|
utimbuf.modtime = write_time;
|
||||||
|
if (utime( file->name, &utimbuf ) == -1)
|
||||||
{
|
{
|
||||||
file_set_error();
|
file_set_error();
|
||||||
release_object( file );
|
release_object( file );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY;
|
|
||||||
else reply->attr = FILE_ATTRIBUTE_ARCHIVE;
|
|
||||||
if (!(st.st_mode & S_IWUSR)) reply->attr |= FILE_ATTRIBUTE_READONLY;
|
|
||||||
reply->access_time = st.st_atime;
|
|
||||||
reply->write_time = st.st_mtime;
|
|
||||||
reply->size_high = 0;
|
|
||||||
reply->size_low = S_ISDIR(st.st_mode) ? 0 : st.st_size;
|
|
||||||
reply->links = st.st_nlink;
|
|
||||||
reply->index_high = st.st_dev;
|
|
||||||
reply->index_low = st.st_ino;
|
|
||||||
reply->serial = 0; /* FIXME */
|
|
||||||
|
|
||||||
release_object( file );
|
release_object( file );
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ static const struct object_ops mapping_ops =
|
||||||
no_read_fd,
|
no_read_fd,
|
||||||
no_write_fd,
|
no_write_fd,
|
||||||
no_flush,
|
no_flush,
|
||||||
|
no_get_file_info,
|
||||||
mapping_destroy
|
mapping_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,8 +94,9 @@ static void mapping_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct mapping *mapping = (struct mapping *)obj;
|
struct mapping *mapping = (struct mapping *)obj;
|
||||||
assert( obj->ops == &mapping_ops );
|
assert( obj->ops == &mapping_ops );
|
||||||
fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p\n",
|
fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p name='%s'\n",
|
||||||
mapping->size_high, mapping->size_low, mapping->protect, mapping->file );
|
mapping->size_high, mapping->size_low, mapping->protect,
|
||||||
|
mapping->file, get_object_name( &mapping->obj ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mapping_destroy( struct object *obj )
|
static void mapping_destroy( struct object *obj )
|
||||||
|
|
|
@ -37,6 +37,7 @@ static const struct object_ops mutex_ops =
|
||||||
no_read_fd,
|
no_read_fd,
|
||||||
no_write_fd,
|
no_write_fd,
|
||||||
no_flush,
|
no_flush,
|
||||||
|
no_get_file_info,
|
||||||
mutex_destroy
|
mutex_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -110,7 +111,8 @@ static void mutex_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct mutex *mutex = (struct mutex *)obj;
|
struct mutex *mutex = (struct mutex *)obj;
|
||||||
assert( obj->ops == &mutex_ops );
|
assert( obj->ops == &mutex_ops );
|
||||||
printf( "Mutex count=%u owner=%p\n", mutex->count, mutex->owner );
|
printf( "Mutex count=%u owner=%p name='%s'\n",
|
||||||
|
mutex->count, mutex->owner, get_object_name( &mutex->obj) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mutex_signaled( struct object *obj, struct thread *thread )
|
static int mutex_signaled( struct object *obj, struct thread *thread )
|
||||||
|
|
|
@ -110,6 +110,13 @@ struct object *create_named_object( const char *name, const struct object_ops *o
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return a pointer to the object name, or to an empty string */
|
||||||
|
const char *get_object_name( struct object *obj )
|
||||||
|
{
|
||||||
|
if (!obj->name) return "";
|
||||||
|
return obj->name->name;
|
||||||
|
}
|
||||||
|
|
||||||
/* grab an object (i.e. increment its refcount) and return the object */
|
/* grab an object (i.e. increment its refcount) and return the object */
|
||||||
struct object *grab_object( void *ptr )
|
struct object *grab_object( void *ptr )
|
||||||
{
|
{
|
||||||
|
@ -176,6 +183,12 @@ int no_flush( struct object *obj )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int no_get_file_info( struct object *obj, struct get_file_info_reply *info )
|
||||||
|
{
|
||||||
|
SET_ERROR( ERROR_INVALID_HANDLE );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void default_select_event( int fd, int event, void *private )
|
void default_select_event( int fd, int event, void *private )
|
||||||
{
|
{
|
||||||
struct object *obj = (struct object *)private;
|
struct object *obj = (struct object *)private;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
|
@ -35,6 +36,7 @@ static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entr
|
||||||
static int pipe_signaled( struct object *obj, struct thread *thread );
|
static int pipe_signaled( struct object *obj, struct thread *thread );
|
||||||
static int pipe_get_read_fd( struct object *obj );
|
static int pipe_get_read_fd( struct object *obj );
|
||||||
static int pipe_get_write_fd( struct object *obj );
|
static int pipe_get_write_fd( struct object *obj );
|
||||||
|
static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||||
static void pipe_destroy( struct object *obj );
|
static void pipe_destroy( struct object *obj );
|
||||||
|
|
||||||
static const struct object_ops pipe_ops =
|
static const struct object_ops pipe_ops =
|
||||||
|
@ -47,6 +49,7 @@ static const struct object_ops pipe_ops =
|
||||||
pipe_get_read_fd,
|
pipe_get_read_fd,
|
||||||
pipe_get_write_fd,
|
pipe_get_write_fd,
|
||||||
no_flush,
|
no_flush,
|
||||||
|
pipe_get_info,
|
||||||
pipe_destroy
|
pipe_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,8 +100,8 @@ static void pipe_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct pipe *pipe = (struct pipe *)obj;
|
struct pipe *pipe = (struct pipe *)obj;
|
||||||
assert( obj->ops == &pipe_ops );
|
assert( obj->ops == &pipe_ops );
|
||||||
printf( "Pipe %s-side fd=%d\n",
|
fprintf( stderr, "Pipe %s-side fd=%d\n",
|
||||||
(pipe->side == READ_SIDE) ? "read" : "write", pipe->fd );
|
(pipe->side == READ_SIDE) ? "read" : "write", pipe->fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
|
static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
|
||||||
|
@ -181,6 +184,13 @@ static int pipe_get_write_fd( struct object *obj )
|
||||||
return dup( pipe->fd );
|
return dup( pipe->fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||||
|
{
|
||||||
|
memset( reply, 0, sizeof(*reply) );
|
||||||
|
reply->type = FILE_TYPE_PIPE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void pipe_destroy( struct object *obj )
|
static void pipe_destroy( struct object *obj )
|
||||||
{
|
{
|
||||||
struct pipe *pipe = (struct pipe *)obj;
|
struct pipe *pipe = (struct pipe *)obj;
|
||||||
|
|
|
@ -77,6 +77,7 @@ static const struct object_ops process_ops =
|
||||||
no_read_fd,
|
no_read_fd,
|
||||||
no_write_fd,
|
no_write_fd,
|
||||||
no_flush,
|
no_flush,
|
||||||
|
no_get_file_info,
|
||||||
process_destroy
|
process_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -396,19 +396,16 @@ DECL_HANDLER(create_file)
|
||||||
{
|
{
|
||||||
struct create_file_reply reply = { -1 };
|
struct create_file_reply reply = { -1 };
|
||||||
struct object *obj;
|
struct object *obj;
|
||||||
int new_fd;
|
char *name = (char *)data;
|
||||||
|
if (!len) name = NULL;
|
||||||
|
else CHECK_STRING( "create_file", name, len );
|
||||||
|
|
||||||
if ((new_fd = dup(fd)) == -1)
|
if ((obj = create_file( fd, name, req->access,
|
||||||
{
|
req->sharing, req->create, req->attrs )) != NULL)
|
||||||
SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((obj = create_file( new_fd )) != NULL)
|
|
||||||
{
|
{
|
||||||
reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
|
reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
|
||||||
release_object( obj );
|
release_object( obj );
|
||||||
}
|
}
|
||||||
done:
|
|
||||||
send_reply( current, -1, 1, &reply, sizeof(reply) );
|
send_reply( current, -1, 1, &reply, sizeof(reply) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,11 +467,24 @@ DECL_HANDLER(flush_file)
|
||||||
send_reply( current, -1, 0 );
|
send_reply( current, -1, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set a file access and modification times */
|
||||||
|
DECL_HANDLER(set_file_time)
|
||||||
|
{
|
||||||
|
set_file_time( req->handle, req->access_time, req->write_time );
|
||||||
|
send_reply( current, -1, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/* get a file information */
|
/* get a file information */
|
||||||
DECL_HANDLER(get_file_info)
|
DECL_HANDLER(get_file_info)
|
||||||
{
|
{
|
||||||
|
struct object *obj;
|
||||||
struct get_file_info_reply reply;
|
struct get_file_info_reply reply;
|
||||||
get_file_info( req->handle, &reply );
|
|
||||||
|
if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
|
||||||
|
{
|
||||||
|
obj->ops->get_file_info( obj, &reply );
|
||||||
|
release_object( obj );
|
||||||
|
}
|
||||||
send_reply( current, -1, 1, &reply, sizeof(reply) );
|
send_reply( current, -1, 1, &reply, sizeof(reply) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ static const struct object_ops semaphore_ops =
|
||||||
no_read_fd,
|
no_read_fd,
|
||||||
no_write_fd,
|
no_write_fd,
|
||||||
no_flush,
|
no_flush,
|
||||||
|
no_get_file_info,
|
||||||
semaphore_destroy
|
semaphore_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,7 +97,8 @@ static void semaphore_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct semaphore *sem = (struct semaphore *)obj;
|
struct semaphore *sem = (struct semaphore *)obj;
|
||||||
assert( obj->ops == &semaphore_ops );
|
assert( obj->ops == &semaphore_ops );
|
||||||
printf( "Semaphore count=%d max=%d\n", sem->count, sem->max );
|
fprintf( stderr, "Semaphore count=%d max=%d name='%s'\n",
|
||||||
|
sem->count, sem->max, get_object_name( &sem->obj ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int semaphore_signaled( struct object *obj, struct thread *thread )
|
static int semaphore_signaled( struct object *obj, struct thread *thread )
|
||||||
|
|
|
@ -55,6 +55,7 @@ static const struct object_ops thread_ops =
|
||||||
no_read_fd,
|
no_read_fd,
|
||||||
no_write_fd,
|
no_write_fd,
|
||||||
no_flush,
|
no_flush,
|
||||||
|
no_get_file_info,
|
||||||
destroy_thread
|
destroy_thread
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -145,8 +146,8 @@ static void dump_thread( struct object *obj, int verbose )
|
||||||
struct thread *thread = (struct thread *)obj;
|
struct thread *thread = (struct thread *)obj;
|
||||||
assert( obj->ops == &thread_ops );
|
assert( obj->ops == &thread_ops );
|
||||||
|
|
||||||
printf( "Thread pid=%d fd=%d name='%s'\n",
|
fprintf( stderr, "Thread pid=%d fd=%d name='%s'\n",
|
||||||
thread->unix_pid, thread->client_fd, thread->name );
|
thread->unix_pid, thread->client_fd, thread->name );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int thread_signaled( struct object *obj, struct thread *thread )
|
static int thread_signaled( struct object *obj, struct thread *thread )
|
||||||
|
|
|
@ -214,8 +214,12 @@ static int dump_open_named_obj_reply( struct open_named_obj_reply *req, int len
|
||||||
static int dump_create_file_request( struct create_file_request *req, int len )
|
static int dump_create_file_request( struct create_file_request *req, int len )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " access=%08x,", req->access );
|
fprintf( stderr, " access=%08x,", req->access );
|
||||||
fprintf( stderr, " inherit=%d", req->inherit );
|
fprintf( stderr, " inherit=%d,", req->inherit );
|
||||||
return (int)sizeof(*req);
|
fprintf( stderr, " sharing=%08x,", req->sharing );
|
||||||
|
fprintf( stderr, " create=%d,", req->create );
|
||||||
|
fprintf( stderr, " attrs=%08x,", req->attrs );
|
||||||
|
fprintf( stderr, " name=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) );
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_create_file_reply( struct create_file_reply *req, int len )
|
static int dump_create_file_reply( struct create_file_reply *req, int len )
|
||||||
|
@ -258,6 +262,14 @@ static int dump_truncate_file_request( struct truncate_file_request *req, int le
|
||||||
return (int)sizeof(*req);
|
return (int)sizeof(*req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dump_set_file_time_request( struct set_file_time_request *req, int len )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d,", req->handle );
|
||||||
|
fprintf( stderr, " access_time=%ld,", req->access_time );
|
||||||
|
fprintf( stderr, " write_time=%ld", req->write_time );
|
||||||
|
return (int)sizeof(*req);
|
||||||
|
}
|
||||||
|
|
||||||
static int dump_flush_file_request( struct flush_file_request *req, int len )
|
static int dump_flush_file_request( struct flush_file_request *req, int len )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%d", req->handle );
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
|
@ -272,6 +284,7 @@ static int dump_get_file_info_request( struct get_file_info_request *req, int le
|
||||||
|
|
||||||
static int dump_get_file_info_reply( struct get_file_info_reply *req, int len )
|
static int dump_get_file_info_reply( struct get_file_info_reply *req, int len )
|
||||||
{
|
{
|
||||||
|
fprintf( stderr, " type=%d,", req->type );
|
||||||
fprintf( stderr, " attr=%d,", req->attr );
|
fprintf( stderr, " attr=%d,", req->attr );
|
||||||
fprintf( stderr, " access_time=%ld,", req->access_time );
|
fprintf( stderr, " access_time=%ld,", req->access_time );
|
||||||
fprintf( stderr, " write_time=%ld,", req->write_time );
|
fprintf( stderr, " write_time=%ld,", req->write_time );
|
||||||
|
@ -413,6 +426,8 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] =
|
||||||
(void(*)())dump_set_file_pointer_reply },
|
(void(*)())dump_set_file_pointer_reply },
|
||||||
{ (int(*)(void *,int))dump_truncate_file_request,
|
{ (int(*)(void *,int))dump_truncate_file_request,
|
||||||
(void(*)())0 },
|
(void(*)())0 },
|
||||||
|
{ (int(*)(void *,int))dump_set_file_time_request,
|
||||||
|
(void(*)())0 },
|
||||||
{ (int(*)(void *,int))dump_flush_file_request,
|
{ (int(*)(void *,int))dump_flush_file_request,
|
||||||
(void(*)())0 },
|
(void(*)())0 },
|
||||||
{ (int(*)(void *,int))dump_get_file_info_request,
|
{ (int(*)(void *,int))dump_get_file_info_request,
|
||||||
|
@ -456,6 +471,7 @@ static const char * const req_names[REQ_NB_REQUESTS] =
|
||||||
"get_write_fd",
|
"get_write_fd",
|
||||||
"set_file_pointer",
|
"set_file_pointer",
|
||||||
"truncate_file",
|
"truncate_file",
|
||||||
|
"set_file_time",
|
||||||
"flush_file",
|
"flush_file",
|
||||||
"get_file_info",
|
"get_file_info",
|
||||||
"create_pipe",
|
"create_pipe",
|
||||||
|
|
|
@ -42,11 +42,7 @@ const K32OBJ_OPS DEVICE_Ops =
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
K32OBJ header;
|
K32OBJ header;
|
||||||
|
|
||||||
struct VxDInfo *info;
|
struct VxDInfo *info;
|
||||||
char *devname;
|
|
||||||
int mode;
|
|
||||||
|
|
||||||
} DEVICE_OBJECT;
|
} DEVICE_OBJECT;
|
||||||
|
|
||||||
|
|
||||||
|
@ -270,7 +266,7 @@ LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
|
||||||
"<KERNEL32.101>" /* 0x0028 -- What does this do??? */
|
"<KERNEL32.101>" /* 0x0028 -- What does this do??? */
|
||||||
};
|
};
|
||||||
|
|
||||||
HANDLE32 DEVICE_Open(LPCSTR filename, DWORD access)
|
HANDLE32 DEVICE_Open(LPCSTR filename)
|
||||||
{
|
{
|
||||||
DEVICE_OBJECT *dev;
|
DEVICE_OBJECT *dev;
|
||||||
HANDLE32 handle;
|
HANDLE32 handle;
|
||||||
|
@ -281,8 +277,6 @@ HANDLE32 DEVICE_Open(LPCSTR filename, DWORD access)
|
||||||
|
|
||||||
dev->header.type = K32OBJ_DEVICE_IOCTL;
|
dev->header.type = K32OBJ_DEVICE_IOCTL;
|
||||||
dev->header.refcount = 1;
|
dev->header.refcount = 1;
|
||||||
dev->mode = access;
|
|
||||||
dev->devname = HEAP_strdupA(SystemHeap,0,filename);
|
|
||||||
dev->info = NULL;
|
dev->info = NULL;
|
||||||
|
|
||||||
for (i = 0; VxDList[i].name; i++)
|
for (i = 0; VxDList[i].name; i++)
|
||||||
|
@ -307,12 +301,6 @@ static void DEVICE_Destroy(K32OBJ *obj)
|
||||||
DEVICE_OBJECT *dev = (DEVICE_OBJECT *)obj;
|
DEVICE_OBJECT *dev = (DEVICE_OBJECT *)obj;
|
||||||
assert( obj->type == K32OBJ_DEVICE_IOCTL );
|
assert( obj->type == K32OBJ_DEVICE_IOCTL );
|
||||||
|
|
||||||
if ( dev->devname )
|
|
||||||
{
|
|
||||||
HeapFree( SystemHeap, 0, dev->devname );
|
|
||||||
dev->devname = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->type = K32OBJ_UNKNOWN;
|
obj->type = K32OBJ_UNKNOWN;
|
||||||
HeapFree( SystemHeap, 0, dev );
|
HeapFree( SystemHeap, 0, dev );
|
||||||
}
|
}
|
||||||
|
@ -360,7 +348,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
|
||||||
{
|
{
|
||||||
/* FIXME: Set appropriate error */
|
/* FIXME: Set appropriate error */
|
||||||
FIXME( win32, "Unimplemented control %ld for VxD device %s\n",
|
FIXME( win32, "Unimplemented control %ld for VxD device %s\n",
|
||||||
dwIoControlCode, dev->devname );
|
dwIoControlCode, dev->info->name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
185
win32/file.c
185
win32/file.c
|
@ -25,10 +25,6 @@
|
||||||
|
|
||||||
DWORD ErrnoToLastError(int errno_num);
|
DWORD ErrnoToLastError(int errno_num);
|
||||||
|
|
||||||
static int TranslateCreationFlags(DWORD create_flags);
|
|
||||||
static int TranslateAccessFlags(DWORD access_flags);
|
|
||||||
static int TranslateShareFlags(DWORD share_flags);
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ReadFileEx (KERNEL32.)
|
* ReadFileEx (KERNEL32.)
|
||||||
*/
|
*/
|
||||||
|
@ -51,187 +47,6 @@ BOOL32 WINAPI ReadFileEx(HFILE32 hFile, LPVOID lpBuffer, DWORD numtoread,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* CreateFile32A [KERNEL32.45] Creates or opens a file or other object
|
|
||||||
*
|
|
||||||
* Creates or opens an object, and returns a handle that can be used to
|
|
||||||
* access that object.
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
*
|
|
||||||
* filename [I] pointer to filename to be accessed
|
|
||||||
* access [I] access mode requested
|
|
||||||
* sharing [I] share mode
|
|
||||||
* security [I] pointer to security attributes
|
|
||||||
* creation [I] ?
|
|
||||||
* attributes [I] ?
|
|
||||||
* template [I] handle to file with attributes to copy
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* Success: Open handle to specified file
|
|
||||||
* Failure: INVALID_HANDLE_VALUE
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* Should call SetLastError() on failure.
|
|
||||||
*
|
|
||||||
* BUGS
|
|
||||||
*
|
|
||||||
* Doesn't support character devices, pipes, template files, or a
|
|
||||||
* lot of the 'attributes' flags yet.
|
|
||||||
*/
|
|
||||||
HFILE32 WINAPI CreateFile32A(LPCSTR filename, DWORD access, DWORD sharing,
|
|
||||||
LPSECURITY_ATTRIBUTES security, DWORD creation,
|
|
||||||
DWORD attributes, HANDLE32 template)
|
|
||||||
{
|
|
||||||
int access_flags, create_flags, share_flags;
|
|
||||||
HFILE32 to_dup = HFILE_ERROR32; /* handle to dup */
|
|
||||||
|
|
||||||
/* Translate the various flags to Unix-style.
|
|
||||||
*/
|
|
||||||
access_flags = TranslateAccessFlags(access);
|
|
||||||
create_flags = TranslateCreationFlags(creation);
|
|
||||||
share_flags = TranslateShareFlags(sharing);
|
|
||||||
|
|
||||||
if(template)
|
|
||||||
FIXME(file, "template handles not supported.\n");
|
|
||||||
|
|
||||||
if(!filename)
|
|
||||||
return HFILE_ERROR32;
|
|
||||||
/* If the name starts with '\\?\' or '\\.\', ignore the first 4 chars.
|
|
||||||
*/
|
|
||||||
if(!strncmp(filename, "\\\\?\\", 4) || !strncmp(filename, "\\\\.\\", 4))
|
|
||||||
{
|
|
||||||
if (filename[2] == '.')
|
|
||||||
return DEVICE_Open( filename+4, access_flags | create_flags );
|
|
||||||
|
|
||||||
filename += 4;
|
|
||||||
if (!strncmp(filename, "UNC", 3))
|
|
||||||
{
|
|
||||||
FIXME(file, "UNC name (%s) not supported.\n",filename);
|
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
||||||
return HFILE_ERROR32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the name still starts with '\\', it's a UNC name.
|
|
||||||
*/
|
|
||||||
if(!strncmp(filename, "\\\\", 2))
|
|
||||||
{
|
|
||||||
FIXME(file, "UNC names not supported.\n");
|
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
||||||
return HFILE_ERROR32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the name is either CONIN$ or CONOUT$, give them duplicated stdin
|
|
||||||
* or stdout, respectively. The lower case version is also allowed. Most likely
|
|
||||||
* this should be a case ignore string compare.
|
|
||||||
*/
|
|
||||||
if(!strcasecmp(filename, "CONIN$"))
|
|
||||||
to_dup = GetStdHandle( STD_INPUT_HANDLE );
|
|
||||||
else if(!strcasecmp(filename, "CONOUT$"))
|
|
||||||
to_dup = GetStdHandle( STD_OUTPUT_HANDLE );
|
|
||||||
|
|
||||||
if(to_dup != HFILE_ERROR32)
|
|
||||||
{
|
|
||||||
HFILE32 handle;
|
|
||||||
if (!DuplicateHandle( GetCurrentProcess(), to_dup, GetCurrentProcess(),
|
|
||||||
&handle, access, FALSE, 0 ))
|
|
||||||
handle = HFILE_ERROR32;
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
return FILE_Open( filename, access_flags | create_flags,share_flags );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* CreateFile32W (KERNEL32.48)
|
|
||||||
*/
|
|
||||||
HFILE32 WINAPI CreateFile32W(LPCWSTR filename, DWORD access, DWORD sharing,
|
|
||||||
LPSECURITY_ATTRIBUTES security, DWORD creation,
|
|
||||||
DWORD attributes, HANDLE32 template)
|
|
||||||
{
|
|
||||||
LPSTR afn = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
|
|
||||||
HFILE32 res = CreateFile32A( afn, access, sharing, security, creation,
|
|
||||||
attributes, template );
|
|
||||||
HeapFree( GetProcessHeap(), 0, afn );
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int TranslateAccessFlags(DWORD access_flags)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
switch(access_flags)
|
|
||||||
{
|
|
||||||
case GENERIC_READ:
|
|
||||||
rc = O_RDONLY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GENERIC_WRITE:
|
|
||||||
rc = O_WRONLY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case (GENERIC_READ | GENERIC_WRITE):
|
|
||||||
rc = O_RDWR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int TranslateCreationFlags(DWORD create_flags)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
switch(create_flags)
|
|
||||||
{
|
|
||||||
case CREATE_NEW:
|
|
||||||
rc = O_CREAT | O_EXCL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CREATE_ALWAYS:
|
|
||||||
rc = O_CREAT | O_TRUNC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPEN_EXISTING:
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPEN_ALWAYS:
|
|
||||||
rc = O_CREAT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TRUNCATE_EXISTING:
|
|
||||||
rc = O_TRUNC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
static int TranslateShareFlags(DWORD share_flags)
|
|
||||||
/*
|
|
||||||
OPEN_SHARE_DENYNONE FILE_SHARE_READ | FILE_SHARE_WRITE
|
|
||||||
OPEN_SHARE_DENYREAD FILE_SHARE_WRITE
|
|
||||||
OPEN_SHARE_DENYREADWRITE 0
|
|
||||||
OPEN_SHARE_DENYWRITE FILE_SHARE_READ
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
switch(share_flags)
|
|
||||||
{
|
|
||||||
case FILE_SHARE_READ | FILE_SHARE_WRITE:
|
|
||||||
return OF_SHARE_DENY_NONE;
|
|
||||||
case FILE_SHARE_WRITE:
|
|
||||||
return OF_SHARE_DENY_READ;
|
|
||||||
case FILE_SHARE_READ:
|
|
||||||
return OF_SHARE_DENY_WRITE;
|
|
||||||
case 0:
|
|
||||||
return OF_SHARE_EXCLUSIVE;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
FIXME(file,"unknown sharing flags 0x%04lx\n",share_flags);
|
|
||||||
return OF_SHARE_EXCLUSIVE;
|
|
||||||
}
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* SetFileAttributes16 (KERNEL.421)
|
* SetFileAttributes16 (KERNEL.421)
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue