diff --git a/files/dos_fs.c b/files/dos_fs.c index 7e49caed135..816f1b96a50 100644 --- a/files/dos_fs.c +++ b/files/dos_fs.c @@ -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; diff --git a/files/file.c b/files/file.c index 3fc8c5c60b5..dc17b99437e 100644 --- a/files/file.c +++ b/files/file.c @@ -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) - { - case O_WRONLY: - dosMode = OF_WRITE; - break; - case O_RDWR: - dosMode =OF_READWRITE; - break; - case O_RDONLY: - default: - dosMode = OF_READ; - break; - } - return dosMode; + switch(mode & 0x03) + { + 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; + } + switch(mode & 0x70) + { + 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; + } } -/*********************************************************************** - * 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 * @@ -352,58 +292,8 @@ 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;inbFiles;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)) - { - DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk ); - close( unix_handle ); - return INVALID_HANDLE_VALUE32; - } + 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 ); - /* 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 - * mode[I] mode how to open, in unix notation - * shareMode[I] the sharing mode in the win OpenFile notation + * 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 + * 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; + HANDLE32 to_dup = HFILE_ERROR32; - 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; - 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; /* 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 ); return HFILE_ERROR32; - } - else /* check for filename, don't check for last entry if creating */ - { - if (!DOSFS_GetFullName( path, !(mode & O_CREAT), &full_name )) - return HFILE_ERROR32; - unixName = full_name.long_name; - } - - dosMode = FILE_UnixToDosMode(mode)| shareMode; - 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; - + + /* 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; + + return FILE_CreateFile( full_name.long_name, access, sharing, + sa, creation, attributes, template ); } -/*********************************************************************** - * 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; - 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 */; - - 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; + 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 /_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 ); } @@ -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 */ @@ -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; - - if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */ - TRACE(file,"('%s',%p,%p,%p)\n", - file->unix_name, - lpCreationTime, - lpLastAccessTime, - lpLastWriteTime - ); + struct set_file_time_request req; + + 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 diff --git a/include/device.h b/include/device.h index b7a88fbf988..58834e762cd 100644 --- a/include/device.h +++ b/include/device.h @@ -1,4 +1,4 @@ #ifndef __WINE_DEVICE_H #define __WINE_DEVICE_H -extern HANDLE32 DEVICE_Open( LPCSTR name, DWORD flags); +extern HANDLE32 DEVICE_Open( LPCSTR name); #endif diff --git a/include/file.h b/include/file.h index dd2a71acd44..0bc6023fb69 100644 --- a/include/file.h +++ b/include/file.h @@ -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 ); diff --git a/include/server.h b/include/server.h index 2e1ab61eba7..2f386f2f33c 100644 --- a/include/server.h +++ b/include/server.h @@ -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 */ diff --git a/include/server/object.h b/include/server/object.h index 67320e274a1..b10682f6659 100644 --- a/include/server/object.h +++ b/include/server/object.h @@ -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) */ @@ -40,7 +41,9 @@ struct object_ops /* return a Unix fd that can be used to write to the object */ int (*get_write_fd)(struct object *); /* 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 */ 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); diff --git a/include/server/request.h b/include/server/request.h index 40cee6f5f0e..30b25b5cc1e 100644 --- a/include/server/request.h +++ b/include/server/request.h @@ -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) }, diff --git a/loader/ne/module.c b/loader/ne/module.c index 12da7861774..914584eed16 100644 --- a/loader/ne/module.c +++ b/loader/ne/module.c @@ -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 */ diff --git a/loader/pe_image.c b/loader/pe_image.c index 1fc779cfa33..0e7d7df56de 100644 --- a/loader/pe_image.c +++ b/loader/pe_image.c @@ -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; diff --git a/misc/crtdll.c b/misc/crtdll.c index eb3e40aacf1..e3523978f6d 100644 --- a/misc/crtdll.c +++ b/misc/crtdll.c @@ -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 ((handle = FILE_Open(path, flagmode,0)) != INVALID_HANDLE_VALUE32) + 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 = 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; } diff --git a/msdos/int21.c b/msdos/int21.c index da1402004f7..45a0c062e99 100644 --- a/msdos/int21.c +++ b/msdos/int21.c @@ -1635,9 +1635,18 @@ void WINAPI DOS3Call( CONTEXT *context ) break; 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); - break; + { + HANDLE32 handle; + 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 */ TRACE(int21,"FORCEDUP - FORCE DUPLICATE FILE HANDLE %d to %d\n", diff --git a/msdos/vxd.c b/msdos/vxd.c index 8fc01ce5b90..62cc284bbd6 100644 --- a/msdos/vxd.c +++ b/msdos/vxd.c @@ -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; diff --git a/ole/storage.c b/ole/storage.c index 83ce52ece49..1e9de4c645a 100644 --- a/ole/storage.c +++ b/ole/storage.c @@ -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) { diff --git a/scheduler/process.c b/scheduler/process.c index 6612990aa54..ee1155df2c2 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -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: - SetLastError( ERROR_INVALID_PARAMETER ); - return INVALID_HANDLE_VALUE32; + 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; } - 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; + SetLastError( ERROR_INVALID_PARAMETER ); + return INVALID_HANDLE_VALUE32; } diff --git a/server/change.c b/server/change.c index 6c7d38bb9f9..bae2f235505 100644 --- a/server/change.c +++ b/server/change.c @@ -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,8 +52,8 @@ 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", - change->subtree, change->filter ); + fprintf( stderr, "Change notification sub=%d filter=%08x\n", + change->subtree, change->filter ); } static int change_signaled( struct object *obj, struct thread *thread ) diff --git a/server/console.c b/server/console.c index f9f4ed75a41..b7cd57b30b9 100644 --- a/server/console.c +++ b/server/console.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -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,8 +123,8 @@ 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", - console->is_read ? "input" : "output", console->fd ); + fprintf( stderr, "Console %s fd=%d\n", + console->is_read ? "input" : "output", console->fd ); } 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 ); } +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; diff --git a/server/event.c b/server/event.c index 7a400ef4ed6..a6ca09968b1 100644 --- a/server/event.c +++ b/server/event.c @@ -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 ) diff --git a/server/file.c b/server/file.c index 2274fb6bf5a..760902d70cf 100644 --- a/server/file.c +++ b/server/file.c @@ -15,6 +15,7 @@ #include #include #include +#include #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; - 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; } - if (!(file = mem_alloc( sizeof(*file) ))) return NULL; - init_object( &file->obj, &file_ops, NULL ); - file->fd = fd; - switch(flags & 3) + if (name) { - 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; + 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 + { + 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 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; 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; + } diff --git a/server/mapping.c b/server/mapping.c index 2f3dac78914..ceabd5d9a7c 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -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 ) diff --git a/server/mutex.c b/server/mutex.c index 3d07481861e..62fe216dd99 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -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 ) diff --git a/server/object.c b/server/object.c index b702d8d22b0..4a40ac5936f 100644 --- a/server/object.c +++ b/server/object.c @@ -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; diff --git a/server/pipe.c b/server/pipe.c index 4113a68a883..1f92d1062a2 100644 --- a/server/pipe.c +++ b/server/pipe.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -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,8 +100,8 @@ 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", - (pipe->side == READ_SIDE) ? "read" : "write", pipe->fd ); + fprintf( stderr, "Pipe %s-side fd=%d\n", + (pipe->side == READ_SIDE) ? "read" : "write", pipe->fd ); } 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 ); } +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; diff --git a/server/process.c b/server/process.c index 24dbde53a2e..c9ba9c83f23 100644 --- a/server/process.c +++ b/server/process.c @@ -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 }; diff --git a/server/request.c b/server/request.c index 4a0dbc02b21..f1fc2fdd3a5 100644 --- a/server/request.c +++ b/server/request.c @@ -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) ); } diff --git a/server/semaphore.c b/server/semaphore.c index 8becaf03caa..deb06182969 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -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 ) diff --git a/server/thread.c b/server/thread.c index 76394b38c2d..21614c9e026 100644 --- a/server/thread.c +++ b/server/thread.c @@ -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,8 +146,8 @@ 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", - thread->unix_pid, thread->client_fd, thread->name ); + fprintf( stderr, "Thread pid=%d fd=%d name='%s'\n", + thread->unix_pid, thread->client_fd, thread->name ); } static int thread_signaled( struct object *obj, struct thread *thread ) diff --git a/server/trace.c b/server/trace.c index 152a6bf8526..ed257c4affb 100644 --- a/server/trace.c +++ b/server/trace.c @@ -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", diff --git a/win32/device.c b/win32/device.c index 75bab3a5d72..dcfdb38a2dd 100644 --- a/win32/device.c +++ b/win32/device.c @@ -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] = "" /* 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 diff --git a/win32/file.c b/win32/file.c index 40d5699b642..b142513957e 100644 --- a/win32/file.c +++ b/win32/file.c @@ -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) */