Commit 0562539d authored by Alexandre Julliard's avatar Alexandre Julliard

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).
parent 74304fc3
......@@ -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.
*/
HFILE32 DOSFS_OpenDevice( const char *name, int unixmode )
HFILE32 DOSFS_OpenDevice( const char *name, DWORD access )
{
int i;
const char *p;
FILE_OBJECT *file;
HFILE32 handle;
if (!name) return (HFILE32)NULL; /* if FILE_DupUnixHandle was used */
if (name[0] && (name[1] == ':')) name += 2;
......@@ -627,15 +625,17 @@ HFILE32 DOSFS_OpenDevice( const char *name, int unixmode )
if (!*p || (*p == '.')) {
/* got it */
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")) {
HFILE32 to_dup;
HFILE32 handle;
switch (unixmode) {
case O_RDONLY:
switch (access & (GENERIC_READ|GENERIC_WRITE)) {
case GENERIC_READ:
to_dup = GetStdHandle( STD_INPUT_HANDLE );
break;
case O_WRONLY:
case GENERIC_WRITE:
to_dup = GetStdHandle( STD_OUTPUT_HANDLE );
break;
default:
......@@ -651,8 +651,10 @@ HFILE32 DOSFS_OpenDevice( const char *name, int unixmode )
if (!strcmp(DOSFS_Devices[i].name,"SCSIMGR$") ||
!strcmp(DOSFS_Devices[i].name,"HPSCAN"))
{
int fd = open( "/dev/null", unixmode );
return FILE_Alloc( &file, fd, DOSFS_Devices[i].name );
/* FIXME: should keep the name somewhere */
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);
return HFILE_ERROR32;
......
......@@ -27,6 +27,7 @@
#include "windows.h"
#include "winerror.h"
#include "drive.h"
#include "device.h"
#include "file.h"
#include "global.h"
#include "heap.h"
......@@ -66,43 +67,6 @@ typedef struct DOS_FILE_LOCK DOS_FILE_LOCK;
static DOS_FILE_LOCK *locks = NULL;
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
* unixmode[I]
* RETURNS
* dosmode
* Convert OF_* mode into flags for CreateFile.
*/
static int FILE_UnixToDosMode(int unixMode)
static void FILE_ConvertOFMode( INT32 mode, DWORD *access, DWORD *sharing )
{
int dosMode;
switch(unixMode & 3)
switch(mode & 0x03)
{
case O_WRONLY:
dosMode = OF_WRITE;
break;
case O_RDWR:
dosMode =OF_READWRITE;
break;
case O_RDONLY:
default:
dosMode = OF_READ;
break;
case OF_READ: *access = GENERIC_READ; break;
case OF_WRITE: *access = GENERIC_WRITE; break;
case OF_READWRITE: *access = GENERIC_READ | GENERIC_WRITE; break;
default: *access = 0; break;
}
return dosMode;
}
/***********************************************************************
* FILE_DOSToUnixMode
*
* PARAMS
* dosMode[I]
* RETURNS
* unixmode
*/
static int FILE_DOSToUnixMode(int dosMode)
{
int unixMode;
switch(dosMode & 3)
switch(mode & 0x70)
{
case OF_WRITE:
unixMode = O_WRONLY; break;
case OF_READWRITE:
unixMode = O_RDWR; break;
case OF_READ:
default:
unixMode = O_RDONLY; break;
case OF_SHARE_EXCLUSIVE: *sharing = 0; break;
case OF_SHARE_DENY_WRITE: *sharing = FILE_SHARE_READ; break;
case OF_SHARE_DENY_READ: *sharing = FILE_SHARE_WRITE; break;
case OF_SHARE_DENY_NONE:
case OF_SHARE_COMPAT:
default: *sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; break;
}
return unixMode;
}
#if 0
/***********************************************************************
* FILE_ShareDeny
*
......@@ -352,59 +292,9 @@ fail_error05:
DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
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
*
......@@ -468,164 +358,213 @@ void FILE_SetDosError(void)
*
* 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;
int unix_handle;
struct create_file_request req;
struct create_file_reply reply;
if ((unix_handle = dup(fd)) == -1)
{
FILE_SetDosError();
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;
struct stat st;
struct create_file_request req;
struct create_file_reply reply;
if ((unix_handle = open( name, mode, 0666 )) == -1)
{
if (!Options.failReadOnly && (mode == O_RDWR))
unix_handle = open( name, O_RDONLY );
}
if ((unix_handle == -1) || (fstat( unix_handle, &st ) == -1))
{
FILE_SetDosError();
return INVALID_HANDLE_VALUE32;
}
if (S_ISDIR(st.st_mode))
req.access = access;
req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
req.sharing = sharing;
req.create = creation;
req.attrs = attributes;
CLIENT_SendRequest( REQ_CREATE_FILE, -1, 2,
&req, sizeof(req),
filename, strlen(filename) + 1 );
CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
/* If write access failed, retry without GENERIC_WRITE */
if ((reply.handle == -1) && !Options.failReadOnly &&
(access & GENERIC_WRITE) && (GetLastError() == ERROR_ACCESS_DENIED))
{
DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
close( unix_handle );
return INVALID_HANDLE_VALUE32;
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;
/* File opened OK, now allocate a handle */
/* Now build the FILE_OBJECT */
return FILE_Alloc( &file, unix_handle, name );
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
*
* Creates or opens an object, and returns a handle that can be used to
* access that object.
*
* PARAMS
*
* path[I] name of file to open
* mode[I] mode how to open, in unix notation
* shareMode[I] the sharing mode in the win OpenFile notation
* 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;
const char *unixName;
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 (!path) return HFILE_ERROR32;
if (DOSFS_GetDevice( path ))
{
HFILE32 ret;
TRACE(file, "opening device '%s'\n", path );
if (HFILE_ERROR32!=(ret=DOSFS_OpenDevice( path, mode )))
return ret;
HANDLE32 to_dup = HFILE_ERROR32;
/* Do not silence this please. It is a critical error. -MM */
ERR(file, "Couldn't open device '%s'!\n",path);
DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
return HFILE_ERROR32;
}
else /* check for filename, don't check for last entry if creating */
if (!filename)
{
if (!DOSFS_GetFullName( path, !(mode & O_CREAT), &full_name ))
SetLastError( ERROR_INVALID_PARAMETER );
return HFILE_ERROR32;
unixName = full_name.long_name;
}
dosMode = FILE_UnixToDosMode(mode)| shareMode;
fileInUse = FILE_InUse(full_name.long_name,&oldMode);
if(fileInUse)
/* If the name starts with '\\?\', ignore the first 4 chars. */
if (!strncmp(filename, "\\\\?\\", 4))
{
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))))
filename += 4;
if (!strncmp(filename, "UNC\\", 4))
{
file->mode=dosMode;
FILE_ReleaseFile(file);
FIXME( file, "UNC name (%s) not supported.\n", filename );
SetLastError( ERROR_PATH_NOT_FOUND );
return HFILE_ERROR32;
}
}
return hFileRet;
}
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;
}
/***********************************************************************
* FILE_Create
/* 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.
*/
static HFILE32 FILE_Create( LPCSTR path, int mode, int unique )
{
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;
int unix_handle;
FILE_OBJECT *file;
DOS_FULL_NAME full_name;
BOOL32 fileInUse = FALSE;
int oldMode,dosMode; /* FIXME: Do we really need unixmode as argument for
FILE_Create */;
if (!DuplicateHandle( GetCurrentProcess(), to_dup, GetCurrentProcess(),
&handle, access, FALSE, 0 ))
handle = HFILE_ERROR32;
return handle;
}
TRACE(file, "'%s' %04x %d\n", path, mode, unique );
if (DOSFS_GetDevice( filename ))
{
HFILE32 ret;
if (!path) return INVALID_HANDLE_VALUE32;
TRACE(file, "opening device '%s'\n", filename );
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 (HFILE_ERROR32!=(ret=DOSFS_OpenDevice( filename, access )))
return ret;
/* Do not silence this please. It is a critical error. -MM */
ERR(file, "Couldn't open device '%s'!\n",filename);
DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
return HFILE_ERROR32;
}
if (!DOSFS_GetFullName( path, FALSE, &full_name )) return INVALID_HANDLE_VALUE32;
/* check for filename, don't check for last entry if creating */
if (!DOSFS_GetFullName( filename,
(creation == OPEN_EXISTING) || (creation == TRUNCATE_EXISTING), &full_name ))
return HFILE_ERROR32;
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;
}
return FILE_CreateFile( full_name.long_name, access, sharing,
sa, creation, attributes, template );
}
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;
/*************************************************************************
* CreateFile32W (KERNEL32.48)
*/
HFILE32 WINAPI CreateFile32W( LPCWSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation,
DWORD attributes, HANDLE32 template)
{
LPSTR afn = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
HFILE32 res = CreateFile32A( afn, access, sharing, sa, creation, attributes, template );
HeapFree( GetProcessHeap(), 0, afn );
return res;
}
......@@ -789,23 +728,6 @@ INT32 WINAPI CompareFileTime( LPFILETIME x, LPFILETIME y )
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
......@@ -886,7 +808,8 @@ UINT32 WINAPI GetTempFileName32A( LPCSTR path, LPCSTR prefix, UINT32 unique,
{
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)
{ /* We created it */
TRACE(file, "created %s\n",
......@@ -949,14 +872,11 @@ static HFILE32 FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT32 mode,
FILETIME filetime;
WORD filedatetime[2];
DOS_FULL_NAME full_name;
DWORD access, sharing;
char *p;
int unixMode, oldMode;
FILE_OBJECT *file;
BOOL32 fileInUse = FALSE;
if (!ofs) return HFILE_ERROR32;
ofs->cBytes = sizeof(OFSTRUCT);
ofs->nErrCode = 0;
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 */
if (!GetFullPathName32A( name, sizeof(ofs->szPathName),
ofs->szPathName, NULL )) goto error;
FILE_ConvertOFMode( mode, &access, &sharing );
/* 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 ((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 success;
}
......@@ -1018,13 +941,6 @@ found:
lstrcpyn32A( ofs->szPathName, full_name.short_name,
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)
/* Some InstallShield version uses OF_SHARE_EXCLUSIVE
on the file <tempdir>/_ins0432._mp to determine how
......@@ -1054,16 +970,9 @@ found:
return 1;
}
unixMode=FILE_DOSToUnixMode(mode);
hFileRet = FILE_OpenUnixFile( full_name.long_name, unixMode );
hFileRet = FILE_CreateFile( full_name.long_name, access, sharing,
NULL, OPEN_EXISTING, 0, -1 );
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 );
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 )
{
int mode = (attr & 1) ? 0444 : 0666;
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 )
{
int mode = (attr & 1) ? 0444 : 0666;
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 )
{
int mode = (attr & 1) ? 0444 : 0666;
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 )
{
INT32 unixMode;
DWORD access, sharing;
TRACE(file, "('%s',%04x)\n", path, mode );
unixMode= FILE_DOSToUnixMode(mode);
return FILE_Open( path, unixMode , (mode & 0x70));
FILE_ConvertOFMode( mode, &access, &sharing );
return CreateFile32A( path, access, sharing, NULL, OPEN_EXISTING, 0, -1 );
}
......@@ -1573,19 +1482,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
*/
LPVOID FILE_dommap( int unix_handle, LPVOID start,
......@@ -1681,10 +1577,16 @@ int FILE_munmap( LPVOID start, DWORD size_high, DWORD size_low )
*/
DWORD WINAPI GetFileType( HFILE32 hFile )
{
FILE_OBJECT *file = FILE_GetFile(hFile, 0, NULL);
if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
FILE_ReleaseFile( file );
return file->type;
struct get_file_info_request req;
struct get_file_info_reply reply;
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;
}
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 );
return FALSE;
......@@ -1959,33 +1863,22 @@ BOOL32 WINAPI SetFileTime( HFILE32 hFile,
const FILETIME *lpLastAccessTime,
const FILETIME *lpLastWriteTime )
{
FILE_OBJECT *file = FILE_GetFile(hFile, 0, NULL);
struct utimbuf utimbuf;
struct set_file_time_request req;
if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
TRACE(file,"('%s',%p,%p,%p)\n",
file->unix_name,
lpCreationTime,
lpLastAccessTime,
lpLastWriteTime
);
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
K32OBJ_FILE, GENERIC_WRITE )) == -1)
return FALSE;
if (lpLastAccessTime)
utimbuf.actime = DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
req.access_time = DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
else
utimbuf.actime = 0; /* FIXME */
req.access_time = 0; /* FIXME */
if (lpLastWriteTime)
utimbuf.modtime = DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
req.write_time = DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
else
utimbuf.modtime = 0; /* FIXME */
if (-1==utime(file->unix_name,&utimbuf))
{
MSG("Couldn't set the time for file '%s'. Insufficient permissions !?\n", file->unix_name);
FILE_ReleaseFile( file );
FILE_SetDosError();
return FALSE;
}
FILE_ReleaseFile( file );
return TRUE;
req.write_time = 0; /* FIXME */
CLIENT_SendRequest( REQ_SET_FILE_TIME, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitReply( NULL, NULL, 0 );
}
/* Locks need to be mirrored because unix file locking is based
......
#ifndef __WINE_DEVICE_H
#define __WINE_DEVICE_H
extern HANDLE32 DEVICE_Open( LPCSTR name, DWORD flags);
extern HANDLE32 DEVICE_Open( LPCSTR name);
#endif
......@@ -17,9 +17,7 @@
typedef struct
{
K32OBJ header;
int mode;
char *unix_name;
DWORD type; /* Type for win32 apps */
} FILE_OBJECT;
/* Definition of a full DOS file name */
......@@ -60,15 +58,13 @@ typedef struct
extern FILE_OBJECT *FILE_GetFile( HFILE32 handle, DWORD access,
int *server_handle );
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 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 HFILE32 FILE_Dup( HFILE32 hFile );
extern HFILE32 FILE_Dup2( HFILE32 hFile1, HFILE32 hFile2 );
extern HFILE32 FILE_Open( LPCSTR path, INT32 mode ,INT32 sharemode);
extern HFILE32 FILE_OpenUnixFile( LPCSTR path, INT32 mode );
extern BOOL32 FILE_SetFileType( HFILE32 hFile, DWORD type );
extern HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation,
DWORD attributes, HANDLE32 template );
extern LPVOID FILE_dommap( int unix_handle, LPVOID start,
DWORD size_high, DWORD size_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 BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer );
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,
INT32 long_len, LPSTR short_buf,
BOOL32 ignore_case );
......
......@@ -255,6 +255,10 @@ struct create_file_request
{
unsigned int access; /* wanted access rights */
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
{
......@@ -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 */
struct flush_file_request
{
......@@ -312,6 +325,7 @@ struct get_file_info_request
};
struct get_file_info_reply
{
int type; /* file type */
int attr; /* file attributes */
time_t access_time; /* last access time */
time_t write_time; /* last write time */
......
......@@ -23,6 +23,7 @@ struct thread;
struct file;
struct wait_queue_entry;
/* operations valid on all objects */
struct object_ops
{
/* dump the object (for debugging) */
......@@ -41,6 +42,8 @@ struct object_ops
int (*get_write_fd)(struct object *);
/* flush the object buffers */
int (*flush)(struct object *);
/* get file information */
int (*get_file_info)(struct object *,struct get_file_info_reply *);
/* destroy on refcount == 0 */
void (*destroy)(struct object *);
};
......@@ -57,8 +60,8 @@ struct object
extern void *mem_alloc( size_t size ); /* malloc wrapper */
extern struct object *create_named_object( const char *name, const struct object_ops *ops,
size_t size );
extern int init_object( struct object *obj, const struct object_ops *ops,
const char *name );
extern int init_object( struct object *obj, const struct object_ops *ops, const char *name );
extern const char *get_object_name( struct object *obj );
/* grab/release_object can take any pointer, but you better make sure */
/* that the thing pointed to starts with a struct object... */
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_write_fd( 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 );
/* request handlers */
......@@ -172,13 +176,14 @@ extern int release_semaphore( int handle, unsigned int count, unsigned int *prev
/* 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,
unsigned int access );
extern int file_get_mmap_fd( struct file *file );
extern int set_file_pointer( int handle, int *low, int *high, int whence );
extern int truncate_file( int handle );
extern int 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);
......
......@@ -28,6 +28,7 @@ enum request
REQ_GET_WRITE_FD,
REQ_SET_FILE_POINTER,
REQ_TRUNCATE_FILE,
REQ_SET_FILE_TIME,
REQ_FLUSH_FILE,
REQ_GET_FILE_INFO,
REQ_CREATE_PIPE,
......@@ -67,6 +68,7 @@ DECL_HANDLER(get_read_fd);
DECL_HANDLER(get_write_fd);
DECL_HANDLER(set_file_pointer);
DECL_HANDLER(truncate_file);
DECL_HANDLER(set_file_time);
DECL_HANDLER(flush_file);
DECL_HANDLER(get_file_info);
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_set_file_pointer, sizeof(struct set_file_pointer_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_get_file_info, sizeof(struct get_file_info_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 )
{
DOS_FULL_NAME full_name;
char *name;
static HANDLE32 cachedfd = -1;
......@@ -408,8 +407,8 @@ HANDLE32 NE_OpenFile( NE_MODULE *pModule )
CloseHandle( cachedfd );
pCachedModule = pModule;
name = NE_MODULE_NAME( pModule );
if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
(cachedfd = FILE_OpenUnixFile( full_name.long_name, O_RDONLY )) == -1)
if ((cachedfd = CreateFile32A( name, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, -1 )) == -1)
MSG( "Can't open file '%s' for module %04x\n", name, pModule->self );
else
/* FIXME: should not be necessary */
......
......@@ -475,7 +475,7 @@ static HMODULE32 PE_LoadImage( LPCSTR name, OFSTRUCT *ofs )
if (!strchr( p, '.' )) strcat( dllname, ".DLL" );
/* Open PE file */
hFile = OpenFile32( dllname, ofs, OF_READ );
hFile = OpenFile32( dllname, ofs, OF_READ | OF_SHARE_DENY_WRITE );
if ( hFile == HFILE_ERROR32 )
{
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)
return hModule32;
if (PE_HEADER(hModule32)->FileHeader.Characteristics & IMAGE_FILE_DLL)
return 11;
return 20; /* FIXME: not the right error code */
/* Create 16-bit dummy module */
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);
#endif
INT32 flagmode=0;
DWORD access = 0, creation = 0;
if ((strchr(mode,'r')&&strchr(mode,'a'))||
(strchr(mode,'r')&&strchr(mode,'w'))||
(strchr(mode,'w')&&strchr(mode,'a')))
return NULL;
if (strstr(mode,"r+")) flagmode=O_RDWR;
else if (strchr(mode,'r')) flagmode = O_RDONLY;
else if (strstr(mode,"w+")) flagmode= O_RDWR | O_TRUNC | O_CREAT;
else if (strchr(mode,'w')) flagmode = O_WRONLY | O_TRUNC | O_CREAT;
else if (strstr(mode,"a+")) flagmode= O_RDWR | O_CREAT | O_APPEND;
else if (strchr(mode,'w')) flagmode = O_RDWR | O_CREAT | O_APPEND;
else if (strchr(mode,'b'))
TRACE(crtdll, "%s in BINARY mode\n",path);
if (mode[0] == 'r')
{
access = GENERIC_READ;
creation = OPEN_EXISTING;
if (mode[1] == '+') access |= GENERIC_WRITE;
}
else if (mode[0] == 'w')
{
access = GENERIC_WRITE;
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 = FILE_Open(path, flagmode,0)) != INVALID_HANDLE_VALUE32)
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->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 ret=0;
int wineflags=0;
DWORD access = 0, creation = 0;
HFILE32 ret;
/* FIXME:
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
Probably lcc is wrong here, but at least a hack to get is going
*/
wineflags = (flags & 3);
if (flags & 0x0008 ) wineflags |= O_APPEND;
if (flags & 0x0100 ) wineflags |= O_CREAT;
if (flags & 0x0200 ) wineflags |= O_TRUNC;
if (flags & 0x0400 ) wineflags |= O_EXCL;
if (flags & 0xf0f4 )
switch(flags & 3)
{
case O_RDONLY: access |= GENERIC_READ; break;
case O_WRONLY: access |= GENERIC_WRITE; break;
case O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
}
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);
/* End Fixme */
ret = FILE_Open(path,wineflags,0);
TRACE(crtdll,"CRTDLL_open file %s mode 0x%04x (lccmode 0x%04x) got dfh %d\n",
path,wineflags,flags,ret);
ret = CreateFile32A( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, creation, FILE_ATTRIBUTE_NORMAL, -1 );
TRACE(crtdll,"CRTDLL_open file %s mode 0x%04x got handle %d\n", path,flags,ret);
return ret;
}
......
......@@ -1635,9 +1635,18 @@ void WINAPI DOS3Call( CONTEXT *context )
break;
case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
{
HANDLE32 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);
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 */
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_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);
UINT32 i;
......
......@@ -1378,7 +1378,8 @@ HRESULT WINAPI IStorage16_fnCreateStream(
FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
_create_istream16(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.HighPart = 0;
......@@ -1430,7 +1431,8 @@ HRESULT WINAPI IStorage16_fnOpenStorage(
FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
_create_istorage16(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);
newpps = STORAGE_look_for_named_pps(lpstg->hf,this->stde.pps_dir,name);
if (newpps==-1) {
......@@ -1464,7 +1466,8 @@ HRESULT WINAPI IStorage16_fnOpenStream(
FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
_create_istream16(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);
newpps = STORAGE_look_for_named_pps(lpstr->hf,this->stde.pps_dir,name);
if (newpps==-1) {
......
......@@ -108,12 +108,9 @@ static BOOL32 PROCESS_BuildEnvDB( PDB32 *pdb )
/* Allocate the standard handles */
pdb->env_db->hStdin = FILE_DupUnixHandle( 0 );
pdb->env_db->hStdout = FILE_DupUnixHandle( 1 );
pdb->env_db->hStderr = FILE_DupUnixHandle( 2 );
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 );
pdb->env_db->hStdin = FILE_DupUnixHandle( 0, GENERIC_READ );
pdb->env_db->hStdout = FILE_DupUnixHandle( 1, GENERIC_WRITE );
pdb->env_db->hStderr = FILE_DupUnixHandle( 2, GENERIC_WRITE );
/* Build the command-line */
......@@ -661,46 +658,19 @@ DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
/***********************************************************************
* GetStdHandle (KERNEL32.276)
*
* FIXME: These should be allocated when a console is created, or inherited
* from the parent.
*/
HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
{
HFILE32 hFile;
int fd;
PDB32 *pdb = PROCESS_Current();
switch(std_handle)
{
case STD_INPUT_HANDLE:
if (pdb->env_db->hStdin) return pdb->env_db->hStdin;
fd = 0;
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:
case STD_INPUT_HANDLE: return pdb->env_db->hStdin;
case STD_OUTPUT_HANDLE: return pdb->env_db->hStdout;
case STD_ERROR_HANDLE: return pdb->env_db->hStderr;
}
SetLastError( ERROR_INVALID_PARAMETER );
return INVALID_HANDLE_VALUE32;
}
hFile = FILE_DupUnixHandle( fd );
if (hFile != HFILE_ERROR32)
{
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_write_fd,
no_flush,
no_get_file_info,
change_destroy
};
......@@ -51,7 +52,7 @@ static void change_dump( struct object *obj, int verbose )
{
struct change *change = (struct change *)obj;
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 );
}
......
......@@ -9,6 +9,7 @@
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.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_get_read_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 const struct object_ops console_ops =
......@@ -47,6 +49,7 @@ static const struct object_ops console_ops =
console_get_read_fd,
console_get_write_fd,
no_flush,
console_get_info,
console_destroy
};
......@@ -120,7 +123,7 @@ static void console_dump( struct object *obj, int verbose )
{
struct console *console = (struct console *)obj;
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 );
}
......@@ -194,6 +197,13 @@ static int console_get_write_fd( struct object *obj )
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 )
{
struct console *console = (struct console *)obj;
......
......@@ -34,6 +34,7 @@ static const struct object_ops event_ops =
no_read_fd,
no_write_fd,
no_flush,
no_get_file_info,
event_destroy
};
......@@ -103,7 +104,9 @@ static void event_dump( struct object *obj, int verbose )
{
struct event *event = (struct event *)obj;
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 )
......
......@@ -15,6 +15,7 @@
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#include "winerror.h"
#include "winnt.h"
......@@ -23,10 +24,18 @@
struct file
{
struct object obj; /* object header */
struct file *next; /* next file in hashing list */
char *name; /* file name */
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 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 );
......@@ -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_write_fd( 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 const struct object_ops file_ops =
......@@ -46,6 +56,7 @@ static const struct object_ops file_ops =
file_get_read_fd,
file_get_write_fd,
file_flush,
file_get_info,
file_destroy
};
......@@ -55,31 +66,134 @@ static const struct select_ops select_ops =
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;
unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
unsigned int existing_access = 0;
for (file = file_hash[hash]; file; file = file->next)
{
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 ((flags = fcntl( fd, F_GETFL )) == -1)
if (!name)
{
perror( "fcntl" );
SET_ERROR( ERROR_INVALID_PARAMETER );
return NULL;
}
if (!(file = mem_alloc( sizeof(*file) ))) return NULL;
init_object( &file->obj, &file_ops, NULL );
file->fd = fd;
switch(flags & 3)
/* 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;
}
if (name)
{
if (!(file->name = mem_alloc( strlen(name) + 1 )))
{
close( fd );
free( file );
return NULL;
}
strcpy( file->name, name );
file->next = file_hash[hash];
file_hash[hash] = file;
}
else
{
case O_RDONLY:
file->event = READ_EVENT;
break;
case O_WRONLY:
file->event = WRITE_EVENT;
break;
case O_RDWR:
file->event = READ_EVENT | WRITE_EVENT;
break;
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();
return &file->obj;
}
......@@ -88,7 +202,8 @@ static void file_dump( struct object *obj, int verbose )
{
struct file *file = (struct file *)obj;
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 )
......@@ -128,8 +243,8 @@ static int file_signaled( struct object *obj, struct thread *thread )
FD_ZERO( &read_fds );
FD_ZERO( &write_fds );
if (file->event & READ_EVENT) FD_SET( file->fd, &read_fds );
if (file->event & WRITE_EVENT) FD_SET( file->fd, &write_fds );
if (file->access & GENERIC_READ) FD_SET( file->fd, &read_fds );
if (file->access & GENERIC_WRITE) FD_SET( file->fd, &write_fds );
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;
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 );
}
......@@ -150,12 +259,6 @@ static int file_get_write_fd( struct object *obj )
{
struct file *file = (struct file *)obj;
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 );
}
......@@ -171,11 +274,48 @@ static int file_flush( struct object *obj )
return ret;
}
static int file_get_info( struct object *obj, struct get_file_info_reply *reply )
{
struct stat st;
struct file *file = (struct file *)obj;
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 );
free( file->name );
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 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;
if (fstat( file->fd, &st ) == -1)
utimbuf.actime = access_time;
utimbuf.modtime = write_time;
if (utime( file->name, &utimbuf ) == -1)
{
file_set_error();
release_object( file );
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 );
return 1;
}
......@@ -35,6 +35,7 @@ static const struct object_ops mapping_ops =
no_read_fd,
no_write_fd,
no_flush,
no_get_file_info,
mapping_destroy
};
......@@ -93,8 +94,9 @@ static void mapping_dump( struct object *obj, int verbose )
{
struct mapping *mapping = (struct mapping *)obj;
assert( obj->ops == &mapping_ops );
fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p\n",
mapping->size_high, mapping->size_low, mapping->protect, mapping->file );
fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p name='%s'\n",
mapping->size_high, mapping->size_low, mapping->protect,
mapping->file, get_object_name( &mapping->obj ) );
}
static void mapping_destroy( struct object *obj )
......
......@@ -37,6 +37,7 @@ static const struct object_ops mutex_ops =
no_read_fd,
no_write_fd,
no_flush,
no_get_file_info,
mutex_destroy
};
......@@ -110,7 +111,8 @@ static void mutex_dump( struct object *obj, int verbose )
{
struct mutex *mutex = (struct mutex *)obj;
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 )
......
......@@ -110,6 +110,13 @@ struct object *create_named_object( const char *name, const struct object_ops *o
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 */
struct object *grab_object( void *ptr )
{
......@@ -176,6 +183,12 @@ int no_flush( struct object *obj )
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 )
{
struct object *obj = (struct object *)private;
......
......@@ -6,6 +6,7 @@
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.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_get_read_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 const struct object_ops pipe_ops =
......@@ -47,6 +49,7 @@ static const struct object_ops pipe_ops =
pipe_get_read_fd,
pipe_get_write_fd,
no_flush,
pipe_get_info,
pipe_destroy
};
......@@ -97,7 +100,7 @@ static void pipe_dump( struct object *obj, int verbose )
{
struct pipe *pipe = (struct pipe *)obj;
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 );
}
......@@ -181,6 +184,13 @@ static int pipe_get_write_fd( struct object *obj )
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 )
{
struct pipe *pipe = (struct pipe *)obj;
......
......@@ -77,6 +77,7 @@ static const struct object_ops process_ops =
no_read_fd,
no_write_fd,
no_flush,
no_get_file_info,
process_destroy
};
......
......@@ -396,19 +396,16 @@ DECL_HANDLER(create_file)
{
struct create_file_reply reply = { -1 };
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)
{
SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
goto done;
}
if ((obj = create_file( new_fd )) != NULL)
if ((obj = create_file( fd, name, req->access,
req->sharing, req->create, req->attrs )) != NULL)
{
reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
release_object( obj );
}
done:
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
......@@ -470,11 +467,24 @@ DECL_HANDLER(flush_file)
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 */
DECL_HANDLER(get_file_info)
{
struct object *obj;
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) );
}
......
......@@ -34,6 +34,7 @@ static const struct object_ops semaphore_ops =
no_read_fd,
no_write_fd,
no_flush,
no_get_file_info,
semaphore_destroy
};
......@@ -96,7 +97,8 @@ static void semaphore_dump( struct object *obj, int verbose )
{
struct semaphore *sem = (struct semaphore *)obj;
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 )
......
......@@ -55,6 +55,7 @@ static const struct object_ops thread_ops =
no_read_fd,
no_write_fd,
no_flush,
no_get_file_info,
destroy_thread
};
......@@ -145,7 +146,7 @@ static void dump_thread( struct object *obj, int verbose )
struct thread *thread = (struct thread *)obj;
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 );
}
......
......@@ -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 )
{
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d", req->inherit );
return (int)sizeof(*req);
fprintf( stderr, " inherit=%d,", req->inherit );
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 )
......@@ -258,6 +262,14 @@ static int dump_truncate_file_request( struct truncate_file_request *req, int le
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 )
{
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 )
{
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " attr=%d,", req->attr );
fprintf( stderr, " access_time=%ld,", req->access_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 },
{ (int(*)(void *,int))dump_truncate_file_request,
(void(*)())0 },
{ (int(*)(void *,int))dump_set_file_time_request,
(void(*)())0 },
{ (int(*)(void *,int))dump_flush_file_request,
(void(*)())0 },
{ (int(*)(void *,int))dump_get_file_info_request,
......@@ -456,6 +471,7 @@ static const char * const req_names[REQ_NB_REQUESTS] =
"get_write_fd",
"set_file_pointer",
"truncate_file",
"set_file_time",
"flush_file",
"get_file_info",
"create_pipe",
......
......@@ -42,11 +42,7 @@ const K32OBJ_OPS DEVICE_Ops =
typedef struct
{
K32OBJ header;
struct VxDInfo *info;
char *devname;
int mode;
} DEVICE_OBJECT;
......@@ -270,7 +266,7 @@ LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
"<KERNEL32.101>" /* 0x0028 -- What does this do??? */
};
HANDLE32 DEVICE_Open(LPCSTR filename, DWORD access)
HANDLE32 DEVICE_Open(LPCSTR filename)
{
DEVICE_OBJECT *dev;
HANDLE32 handle;
......@@ -281,8 +277,6 @@ HANDLE32 DEVICE_Open(LPCSTR filename, DWORD access)
dev->header.type = K32OBJ_DEVICE_IOCTL;
dev->header.refcount = 1;
dev->mode = access;
dev->devname = HEAP_strdupA(SystemHeap,0,filename);
dev->info = NULL;
for (i = 0; VxDList[i].name; i++)
......@@ -307,12 +301,6 @@ static void DEVICE_Destroy(K32OBJ *obj)
DEVICE_OBJECT *dev = (DEVICE_OBJECT *)obj;
assert( obj->type == K32OBJ_DEVICE_IOCTL );
if ( dev->devname )
{
HeapFree( SystemHeap, 0, dev->devname );
dev->devname = NULL;
}
obj->type = K32OBJ_UNKNOWN;
HeapFree( SystemHeap, 0, dev );
}
......@@ -360,7 +348,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
{
/* FIXME: Set appropriate error */
FIXME( win32, "Unimplemented control %ld for VxD device %s\n",
dwIoControlCode, dev->devname );
dwIoControlCode, dev->info->name );
}
}
else
......
......@@ -25,10 +25,6 @@
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.)
*/
......@@ -51,187 +47,6 @@ BOOL32 WINAPI ReadFileEx(HFILE32 hFile, LPVOID lpBuffer, DWORD numtoread,
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)
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment