2 * File handling functions
4 * Copyright 1993 John Burton
5 * Copyright 1996 Alexandre Julliard
15 #include <sys/errno.h>
16 #include <sys/types.h>
36 #if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
37 #define MAP_ANON MAP_ANONYMOUS
40 static BOOL32 FILE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
41 LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped);
42 static BOOL32 FILE_Write(K32OBJ *ptr, LPCVOID lpBuffer, DWORD nNumberOfChars,
43 LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped);
44 static void FILE_Destroy( K32OBJ *obj );
46 const K32OBJ_OPS FILE_Ops =
48 /* Object cannot be waited upon (FIXME: for now) */
52 NULL, /* remove_wait */
54 FILE_Write, /* write */
55 FILE_Destroy /* destroy */
58 struct DOS_FILE_LOCK {
59 struct DOS_FILE_LOCK * next;
63 FILE_OBJECT * dos_file;
67 typedef struct DOS_FILE_LOCK DOS_FILE_LOCK;
69 static DOS_FILE_LOCK *locks = NULL;
70 static void DOS_RemoveFileLocks(FILE_OBJECT *file);
72 /***********************************************************************
77 static HFILE32 FILE_Alloc( FILE_OBJECT **file )
80 *file = HeapAlloc( SystemHeap, 0, sizeof(FILE_OBJECT) );
83 DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
86 (*file)->header.type = K32OBJ_FILE;
87 (*file)->header.refcount = 0;
88 (*file)->unix_handle = -1;
89 (*file)->unix_name = NULL;
90 (*file)->type = FILE_TYPE_DISK;
92 handle = HANDLE_Alloc( PROCESS_Current(), &(*file)->header,
93 FILE_ALL_ACCESS | GENERIC_READ |
94 GENERIC_WRITE | GENERIC_EXECUTE /*FIXME*/, TRUE );
95 /* If the allocation failed, the object is already destroyed */
96 if (handle == INVALID_HANDLE_VALUE32) *file = NULL;
101 /* FIXME: lpOverlapped is ignored */
102 static BOOL32 FILE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
103 LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
105 FILE_OBJECT *file = (FILE_OBJECT *)ptr;
108 TRACE(file, "%p %p %ld\n", ptr, lpBuffer,
111 if (nNumberOfChars == 0) {
112 *lpNumberOfChars = 0; /* FIXME: does this change */
116 if ((result = read(file->unix_handle, lpBuffer, nNumberOfChars)) == -1)
121 *lpNumberOfChars = result;
126 * experimentation yields that WriteFile:
127 * o does not truncate on write of 0
128 * o always changes the *lpNumberOfChars to actual number of
130 * o write of 0 nNumberOfChars returns TRUE
132 static BOOL32 FILE_Write(K32OBJ *ptr, LPCVOID lpBuffer, DWORD nNumberOfChars,
133 LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
135 FILE_OBJECT *file = (FILE_OBJECT *)ptr;
138 TRACE(file, "%p %p %ld\n", ptr, lpBuffer,
141 *lpNumberOfChars = 0;
144 * I assume this loop around EAGAIN is here because
145 * win32 doesn't have interrupted system calls
150 result = write(file->unix_handle, lpBuffer, nNumberOfChars);
152 *lpNumberOfChars = result;
155 if (errno != EINTR) {
164 /***********************************************************************
167 * Destroy a DOS file.
169 static void FILE_Destroy( K32OBJ *ptr )
171 FILE_OBJECT *file = (FILE_OBJECT *)ptr;
172 assert( ptr->type == K32OBJ_FILE );
174 DOS_RemoveFileLocks(file);
176 if (file->unix_handle != -1) close( file->unix_handle );
177 if (file->unix_name) HeapFree( SystemHeap, 0, file->unix_name );
178 ptr->type = K32OBJ_UNKNOWN;
179 HeapFree( SystemHeap, 0, file );
183 /***********************************************************************
186 * Return the DOS file associated to a task file handle. FILE_ReleaseFile must
187 * be called to release the file.
189 static FILE_OBJECT *FILE_GetFile( HFILE32 handle )
191 return (FILE_OBJECT *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
192 K32OBJ_FILE, 0 /*FIXME*/ );
196 /***********************************************************************
199 * Release a DOS file obtained with FILE_GetFile.
201 static void FILE_ReleaseFile( FILE_OBJECT *file )
203 K32OBJ_DecCount( &file->header );
207 /***********************************************************************
210 * Return the Unix handle associated to a file handle.
212 int FILE_GetUnixHandle( HFILE32 hFile )
217 if (!(file = FILE_GetFile( hFile ))) return -1;
218 ret = file->unix_handle;
219 FILE_ReleaseFile( file );
224 /***********************************************************************
227 * Set the DOS error code from errno.
229 void FILE_SetDosError(void)
231 int save_errno = errno; /* errno gets overwritten by printf */
233 TRACE(file, "errno = %d %s\n", errno, strerror(errno));
237 DOS_ERROR( ER_ShareViolation, EC_Temporary, SA_Retry, EL_Disk );
240 DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
243 DOS_ERROR( ER_DiskFull, EC_MediaError, SA_Abort, EL_Disk );
248 DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
251 DOS_ERROR( ER_LockViolation, EC_AccessDenied, SA_Abort, EL_Disk );
254 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
257 DOS_ERROR( ER_CanNotMakeDir, EC_AccessDenied, SA_Abort, EL_Unknown );
261 DOS_ERROR( ER_NoMoreFiles, EC_MediaError, SA_Abort, EL_Unknown );
264 DOS_ERROR( ER_FileExists, EC_Exists, SA_Abort, EL_Disk );
268 DOS_ERROR( ER_SeekError, EC_NotFound, SA_Ignore, EL_Disk );
271 DOS_ERROR( ERROR_DIR_NOT_EMPTY, EC_Exists, SA_Ignore, EL_Disk );
274 perror( "int21: unknown errno" );
275 DOS_ERROR( ER_GeneralFailure, EC_SystemFailure, SA_Abort, EL_Unknown );
282 /***********************************************************************
285 * Duplicate a Unix handle into a task handle.
287 HFILE32 FILE_DupUnixHandle( int fd )
292 if ((handle = FILE_Alloc( &file )) != INVALID_HANDLE_VALUE32)
294 if ((file->unix_handle = dup(fd)) == -1)
297 CloseHandle( handle );
298 return INVALID_HANDLE_VALUE32;
305 /***********************************************************************
308 HFILE32 FILE_OpenUnixFile( const char *name, int mode )
314 if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
315 return INVALID_HANDLE_VALUE32;
317 if ((file->unix_handle = open( name, mode, 0666 )) == -1)
319 if (!Options.failReadOnly && (mode == O_RDWR))
320 file->unix_handle = open( name, O_RDONLY );
322 if ((file->unix_handle == -1) || (fstat( file->unix_handle, &st ) == -1))
325 CloseHandle( handle );
326 return INVALID_HANDLE_VALUE32;
328 if (S_ISDIR(st.st_mode))
330 DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
331 CloseHandle( handle );
332 return INVALID_HANDLE_VALUE32;
335 /* File opened OK, now fill the FILE_OBJECT */
337 file->unix_name = HEAP_strdupA( SystemHeap, 0, name );
342 /***********************************************************************
345 HFILE32 FILE_Open( LPCSTR path, INT32 mode )
347 DOS_FULL_NAME full_name;
348 const char *unixName;
350 TRACE(file, "'%s' %04x\n", path, mode );
352 if (!path) return HFILE_ERROR32;
354 if (DOSFS_IsDevice( path ))
358 TRACE(file, "opening device '%s'\n", path );
360 if (HFILE_ERROR32!=(ret=DOSFS_OpenDevice( path, mode )))
363 /* Do not silence this please. It is a critical error. -MM */
364 ERR(file, "Couldn't open device '%s'!\n",path);
365 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
366 return HFILE_ERROR32;
369 else /* check for filename, don't check for last entry if creating */
371 if (!DOSFS_GetFullName( path, !(mode & O_CREAT), &full_name ))
372 return HFILE_ERROR32;
373 unixName = full_name.long_name;
375 return FILE_OpenUnixFile( unixName, mode );
379 /***********************************************************************
382 static HFILE32 FILE_Create( LPCSTR path, int mode, int unique )
386 DOS_FULL_NAME full_name;
388 TRACE(file, "'%s' %04x %d\n", path, mode, unique );
390 if (!path) return INVALID_HANDLE_VALUE32;
392 if (DOSFS_IsDevice( path ))
394 WARN(file, "cannot create DOS device '%s'!\n", path);
395 DOS_ERROR( ER_AccessDenied, EC_NotFound, SA_Abort, EL_Disk );
396 return INVALID_HANDLE_VALUE32;
399 if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
400 return INVALID_HANDLE_VALUE32;
402 if (!DOSFS_GetFullName( path, FALSE, &full_name ))
404 CloseHandle( handle );
405 return INVALID_HANDLE_VALUE32;
407 if ((file->unix_handle = open( full_name.long_name,
408 O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0),
412 CloseHandle( handle );
413 return INVALID_HANDLE_VALUE32;
416 /* File created OK, now fill the FILE_OBJECT */
418 file->unix_name = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
423 /***********************************************************************
426 * Fill a file information from a struct stat.
428 static void FILE_FillInfo( struct stat *st, BY_HANDLE_FILE_INFORMATION *info )
430 if (S_ISDIR(st->st_mode))
431 info->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
433 info->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
434 if (!(st->st_mode & S_IWUSR))
435 info->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
437 DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftCreationTime, 0 );
438 DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftLastWriteTime, 0 );
439 DOSFS_UnixTimeToFileTime( st->st_atime, &info->ftLastAccessTime, 0 );
441 info->dwVolumeSerialNumber = 0; /* FIXME */
442 info->nFileSizeHigh = 0;
443 info->nFileSizeLow = S_ISDIR(st->st_mode) ? 0 : st->st_size;
444 info->nNumberOfLinks = st->st_nlink;
445 info->nFileIndexHigh = 0;
446 info->nFileIndexLow = st->st_ino;
450 /***********************************************************************
453 * Stat a Unix path name. Return TRUE if OK.
455 BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info )
459 if (!unixName || !info) return FALSE;
461 if (stat( unixName, &st ) == -1)
466 FILE_FillInfo( &st, info );
471 /***********************************************************************
472 * GetFileInformationByHandle (KERNEL32.219)
474 DWORD WINAPI GetFileInformationByHandle( HFILE32 hFile,
475 BY_HANDLE_FILE_INFORMATION *info )
483 if (!(file = FILE_GetFile( hFile ))) return 0;
484 if (fstat( file->unix_handle, &st ) == -1) FILE_SetDosError();
487 FILE_FillInfo( &st, info );
490 FILE_ReleaseFile( file );
495 /**************************************************************************
496 * GetFileAttributes16 (KERNEL.420)
498 DWORD WINAPI GetFileAttributes16( LPCSTR name )
500 return GetFileAttributes32A( name );
504 /**************************************************************************
505 * GetFileAttributes32A (KERNEL32.217)
507 DWORD WINAPI GetFileAttributes32A( LPCSTR name )
509 DOS_FULL_NAME full_name;
510 BY_HANDLE_FILE_INFORMATION info;
512 if (name == NULL) return -1;
514 if (!DOSFS_GetFullName( name, TRUE, &full_name )) return -1;
515 if (!FILE_Stat( full_name.long_name, &info )) return -1;
516 return info.dwFileAttributes;
520 /**************************************************************************
521 * GetFileAttributes32W (KERNEL32.218)
523 DWORD WINAPI GetFileAttributes32W( LPCWSTR name )
525 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
526 DWORD res = GetFileAttributes32A( nameA );
527 HeapFree( GetProcessHeap(), 0, nameA );
532 /***********************************************************************
533 * GetFileSize (KERNEL32.220)
535 DWORD WINAPI GetFileSize( HFILE32 hFile, LPDWORD filesizehigh )
537 BY_HANDLE_FILE_INFORMATION info;
538 if (!GetFileInformationByHandle( hFile, &info )) return 0;
539 if (filesizehigh) *filesizehigh = info.nFileSizeHigh;
540 return info.nFileSizeLow;
544 /***********************************************************************
545 * GetFileTime (KERNEL32.221)
547 BOOL32 WINAPI GetFileTime( HFILE32 hFile, FILETIME *lpCreationTime,
548 FILETIME *lpLastAccessTime,
549 FILETIME *lpLastWriteTime )
551 BY_HANDLE_FILE_INFORMATION info;
552 if (!GetFileInformationByHandle( hFile, &info )) return FALSE;
553 if (lpCreationTime) *lpCreationTime = info.ftCreationTime;
554 if (lpLastAccessTime) *lpLastAccessTime = info.ftLastAccessTime;
555 if (lpLastWriteTime) *lpLastWriteTime = info.ftLastWriteTime;
559 /***********************************************************************
560 * CompareFileTime (KERNEL32.28)
562 INT32 WINAPI CompareFileTime( LPFILETIME x, LPFILETIME y )
564 if (!x || !y) return -1;
566 if (x->dwHighDateTime > y->dwHighDateTime)
568 if (x->dwHighDateTime < y->dwHighDateTime)
570 if (x->dwLowDateTime > y->dwLowDateTime)
572 if (x->dwLowDateTime < y->dwLowDateTime)
577 /***********************************************************************
580 * dup() function for DOS handles.
582 HFILE32 FILE_Dup( HFILE32 hFile )
586 TRACE(file, "FILE_Dup for handle %d\n", hFile );
587 if (!DuplicateHandle( GetCurrentProcess(), hFile, GetCurrentProcess(),
588 &handle, FILE_ALL_ACCESS /* FIXME */, FALSE, 0 ))
589 handle = HFILE_ERROR32;
590 TRACE(file, "FILE_Dup return handle %d\n", handle );
595 /***********************************************************************
598 * dup2() function for DOS handles.
600 HFILE32 FILE_Dup2( HFILE32 hFile1, HFILE32 hFile2 )
604 TRACE(file, "FILE_Dup2 for handle %d\n", hFile1 );
605 /* FIXME: should use DuplicateHandle */
606 if (!(file = FILE_GetFile( hFile1 ))) return HFILE_ERROR32;
607 if (!HANDLE_SetObjPtr( PROCESS_Current(), hFile2, &file->header, 0 ))
608 hFile2 = HFILE_ERROR32;
609 FILE_ReleaseFile( file );
614 /***********************************************************************
615 * GetTempFileName16 (KERNEL.97)
617 UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
622 if (!(drive & ~TF_FORCEDRIVE)) /* drive 0 means current default drive */
623 drive |= DRIVE_GetCurrentDrive() + 'A';
625 if ((drive & TF_FORCEDRIVE) &&
626 !DRIVE_IsValid( toupper(drive & ~TF_FORCEDRIVE) - 'A' ))
628 drive &= ~TF_FORCEDRIVE;
629 WARN(file, "invalid drive %d specified\n", drive );
632 if (drive & TF_FORCEDRIVE)
633 sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE );
635 GetTempPath32A( 132, temppath );
636 return (UINT16)GetTempFileName32A( temppath, prefix, unique, buffer );
640 /***********************************************************************
641 * GetTempFileName32A (KERNEL32.290)
643 UINT32 WINAPI GetTempFileName32A( LPCSTR path, LPCSTR prefix, UINT32 unique,
646 DOS_FULL_NAME full_name;
649 UINT32 num = unique ? (unique & 0xffff) : time(NULL) & 0xffff;
651 if ( !path || !prefix || !buffer ) return 0;
653 strcpy( buffer, path );
654 p = buffer + strlen(buffer);
656 /* add a \, if there isn't one and path is more than just the drive letter ... */
657 if ( !((strlen(buffer) == 2) && (buffer[1] == ':'))
658 && ((p == buffer) || (p[-1] != '\\'))) *p++ = '\\';
661 for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
662 sprintf( p, "%04x.tmp", num );
664 /* Now try to create it */
670 HFILE32 handle = FILE_Create( buffer, 0666, TRUE );
671 if (handle != INVALID_HANDLE_VALUE32)
672 { /* We created it */
673 TRACE(file, "created %s\n",
675 CloseHandle( handle );
678 if (DOS_ExtendedError != ER_FileExists)
679 break; /* No need to go on */
681 sprintf( p, "%04x.tmp", num );
682 } while (num != (unique & 0xffff));
685 /* Get the full path name */
687 if (DOSFS_GetFullName( buffer, FALSE, &full_name ))
689 /* Check if we have write access in the directory */
690 if ((p = strrchr( full_name.long_name, '/' ))) *p = '\0';
691 if (access( full_name.long_name, W_OK ) == -1)
692 WARN(file, "returns '%s', which doesn't seem to be writeable.\n",
695 TRACE(file, "returning %s\n", buffer );
696 return unique ? unique : num;
700 /***********************************************************************
701 * GetTempFileName32W (KERNEL32.291)
703 UINT32 WINAPI GetTempFileName32W( LPCWSTR path, LPCWSTR prefix, UINT32 unique,
711 patha = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
712 prefixa = HEAP_strdupWtoA( GetProcessHeap(), 0, prefix );
713 ret = GetTempFileName32A( patha, prefixa, unique, buffera );
714 lstrcpyAtoW( buffer, buffera );
715 HeapFree( GetProcessHeap(), 0, patha );
716 HeapFree( GetProcessHeap(), 0, prefixa );
721 /***********************************************************************
724 * Implementation of OpenFile16() and OpenFile32().
726 static HFILE32 FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT32 mode,
731 WORD filedatetime[2];
732 DOS_FULL_NAME full_name;
736 if (!ofs) return HFILE_ERROR32;
739 ofs->cBytes = sizeof(OFSTRUCT);
741 if (mode & OF_REOPEN) name = ofs->szPathName;
744 ERR(file, "called with `name' set to NULL ! Please debug.\n");
745 return HFILE_ERROR32;
748 TRACE(file, "%s %04x\n", name, mode );
750 /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
751 Are there any cases where getting the path here is wrong?
752 Uwe Bonnes 1997 Apr 2 */
753 if (!GetFullPathName32A( name, sizeof(ofs->szPathName),
754 ofs->szPathName, NULL )) goto error;
756 /* OF_PARSE simply fills the structure */
760 ofs->fFixedDisk = (GetDriveType16( ofs->szPathName[0]-'A' )
762 TRACE(file, "(%s): OF_PARSE, res = '%s'\n",
763 name, ofs->szPathName );
767 /* OF_CREATE is completely different from all other options, so
770 if (mode & OF_CREATE)
772 if ((hFileRet = FILE_Create(name,0666,FALSE))== INVALID_HANDLE_VALUE32)
777 /* If OF_SEARCH is set, ignore the given path */
779 if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
781 /* First try the file name as is */
782 if (DOSFS_GetFullName( name, TRUE, &full_name )) goto found;
783 /* Now remove the path */
784 if (name[0] && (name[1] == ':')) name += 2;
785 if ((p = strrchr( name, '\\' ))) name = p + 1;
786 if ((p = strrchr( name, '/' ))) name = p + 1;
787 if (!name[0]) goto not_found;
790 /* Now look for the file */
792 if (!DIR_SearchPath( NULL, name, NULL, &full_name, win32 )) goto not_found;
795 TRACE(file, "found %s = %s\n",
796 full_name.long_name, full_name.short_name );
797 lstrcpyn32A( ofs->szPathName, full_name.short_name,
798 sizeof(ofs->szPathName) );
800 if (mode & OF_DELETE)
802 if (unlink( full_name.long_name ) == -1) goto not_found;
803 TRACE(file, "(%s): OF_DELETE return = OK\n", name);
810 unixMode = O_WRONLY; break;
812 unixMode = O_RDWR; break;
815 unixMode = O_RDONLY; break;
818 hFileRet = FILE_OpenUnixFile( full_name.long_name, unixMode );
819 if (hFileRet == HFILE_ERROR32) goto not_found;
820 GetFileTime( hFileRet, NULL, NULL, &filetime );
821 FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
822 if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
824 if (memcmp( ofs->reserved, filedatetime, sizeof(ofs->reserved) ))
826 CloseHandle( hFileRet );
827 WARN(file, "(%s): OF_VERIFY failed\n", name );
828 /* FIXME: what error here? */
829 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
833 memcpy( ofs->reserved, filedatetime, sizeof(ofs->reserved) );
835 success: /* We get here if the open was successful */
836 TRACE(file, "(%s): OK, return = %d\n", name, hFileRet );
837 if (mode & OF_EXIST) /* Return the handle, but close it first */
838 CloseHandle( hFileRet );
841 not_found: /* We get here if the file does not exist */
842 WARN(file, "'%s' not found\n", name );
843 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
846 error: /* We get here if there was an error opening the file */
847 ofs->nErrCode = DOS_ExtendedError;
848 WARN(file, "(%s): return = HFILE_ERROR error= %d\n",
849 name,ofs->nErrCode );
850 return HFILE_ERROR32;
854 /***********************************************************************
855 * OpenFile16 (KERNEL.74)
857 HFILE16 WINAPI OpenFile16( LPCSTR name, OFSTRUCT *ofs, UINT16 mode )
859 return FILE_DoOpenFile( name, ofs, mode, FALSE );
863 /***********************************************************************
864 * OpenFile32 (KERNEL32.396)
866 HFILE32 WINAPI OpenFile32( LPCSTR name, OFSTRUCT *ofs, UINT32 mode )
868 return FILE_DoOpenFile( name, ofs, mode, TRUE );
872 /***********************************************************************
873 * _lclose16 (KERNEL.81)
875 HFILE16 WINAPI _lclose16( HFILE16 hFile )
877 TRACE(file, "handle %d\n", hFile );
878 return CloseHandle( hFile ) ? 0 : HFILE_ERROR16;
882 /***********************************************************************
883 * _lclose32 (KERNEL32.592)
885 HFILE32 WINAPI _lclose32( HFILE32 hFile )
887 TRACE(file, "handle %d\n", hFile );
888 return CloseHandle( hFile ) ? 0 : HFILE_ERROR32;
892 /***********************************************************************
895 LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count )
899 TRACE(file, "%d %08lx %ld\n",
900 hFile, (DWORD)buffer, count );
902 /* Some programs pass a count larger than the allocated buffer */
903 maxlen = GetSelectorLimit( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1;
904 if (count > maxlen) count = maxlen;
905 return _lread32( hFile, PTR_SEG_TO_LIN(buffer), count );
909 /***********************************************************************
912 UINT16 WINAPI WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count )
914 return (UINT16)WIN16_hread( hFile, buffer, (LONG)count );
918 /***********************************************************************
919 * _lread32 (KERNEL32.596)
921 UINT32 WINAPI _lread32( HFILE32 handle, LPVOID buffer, UINT32 count )
925 BOOL32 result = FALSE;
927 TRACE( file, "%d %p %d\n", handle, buffer, count);
928 if (!(ptr = HANDLE_GetObjPtr( PROCESS_Current(), handle,
929 K32OBJ_UNKNOWN, 0))) return -1;
930 if (K32OBJ_OPS(ptr)->read)
931 result = K32OBJ_OPS(ptr)->read(ptr, buffer, count, &numWritten, NULL);
932 K32OBJ_DecCount( ptr );
933 if (!result) return -1;
934 return (UINT32)numWritten;
938 /***********************************************************************
939 * _lread16 (KERNEL.82)
941 UINT16 WINAPI _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count )
943 return (UINT16)_lread32( hFile, buffer, (LONG)count );
947 /***********************************************************************
948 * _lcreat16 (KERNEL.83)
950 HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr )
952 int mode = (attr & 1) ? 0444 : 0666;
953 TRACE(file, "%s %02x\n", path, attr );
954 return (HFILE16)FILE_Create( path, mode, FALSE );
958 /***********************************************************************
959 * _lcreat32 (KERNEL32.593)
961 HFILE32 WINAPI _lcreat32( LPCSTR path, INT32 attr )
963 int mode = (attr & 1) ? 0444 : 0666;
964 TRACE(file, "%s %02x\n", path, attr );
965 return FILE_Create( path, mode, FALSE );
969 /***********************************************************************
970 * _lcreat_uniq (Not a Windows API)
972 HFILE32 _lcreat_uniq( LPCSTR path, INT32 attr )
974 int mode = (attr & 1) ? 0444 : 0666;
975 TRACE(file, "%s %02x\n", path, attr );
976 return FILE_Create( path, mode, TRUE );
980 /***********************************************************************
981 * SetFilePointer (KERNEL32.492)
983 DWORD WINAPI SetFilePointer( HFILE32 hFile, LONG distance, LONG *highword,
989 if (highword && *highword)
991 FIXME(file, "64-bit offsets not supported yet\n");
992 SetLastError( ERROR_INVALID_PARAMETER );
995 TRACE(file, "handle %d offset %ld origin %ld\n",
996 hFile, distance, method );
998 if (!(file = FILE_GetFile( hFile ))) return 0xffffffff;
1001 case FILE_CURRENT: origin = SEEK_CUR; break;
1002 case FILE_END: origin = SEEK_END; break;
1003 default: origin = SEEK_SET; break;
1006 if ((result = lseek( file->unix_handle, distance, origin )) == -1)
1008 FILE_ReleaseFile( file );
1009 return (DWORD)result;
1013 /***********************************************************************
1014 * _llseek16 (KERNEL.84)
1016 LONG WINAPI _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
1018 return SetFilePointer( hFile, lOffset, NULL, nOrigin );
1022 /***********************************************************************
1023 * _llseek32 (KERNEL32.594)
1025 LONG WINAPI _llseek32( HFILE32 hFile, LONG lOffset, INT32 nOrigin )
1027 return SetFilePointer( hFile, lOffset, NULL, nOrigin );
1031 /***********************************************************************
1032 * _lopen16 (KERNEL.85)
1034 HFILE16 WINAPI _lopen16( LPCSTR path, INT16 mode )
1036 return _lopen32( path, mode );
1040 /***********************************************************************
1041 * _lopen32 (KERNEL32.595)
1043 HFILE32 WINAPI _lopen32( LPCSTR path, INT32 mode )
1047 TRACE(file, "('%s',%04x)\n", path, mode );
1052 unixMode = O_WRONLY;
1059 unixMode = O_RDONLY;
1062 return FILE_Open( path, unixMode );
1066 /***********************************************************************
1067 * _lwrite16 (KERNEL.86)
1069 UINT16 WINAPI _lwrite16( HFILE16 hFile, LPCSTR buffer, UINT16 count )
1071 return (UINT16)_hwrite32( hFile, buffer, (LONG)count );
1074 /***********************************************************************
1075 * _lwrite32 (KERNEL.86)
1077 UINT32 WINAPI _lwrite32( HFILE32 hFile, LPCSTR buffer, UINT32 count )
1079 return (UINT32)_hwrite32( hFile, buffer, (LONG)count );
1083 /***********************************************************************
1084 * _hread16 (KERNEL.349)
1086 LONG WINAPI _hread16( HFILE16 hFile, LPVOID buffer, LONG count)
1088 return _lread32( hFile, buffer, count );
1092 /***********************************************************************
1093 * _hread32 (KERNEL32.590)
1095 LONG WINAPI _hread32( HFILE32 hFile, LPVOID buffer, LONG count)
1097 return _lread32( hFile, buffer, count );
1101 /***********************************************************************
1102 * _hwrite16 (KERNEL.350)
1104 LONG WINAPI _hwrite16( HFILE16 hFile, LPCSTR buffer, LONG count )
1106 return _hwrite32( hFile, buffer, count );
1110 /***********************************************************************
1111 * _hwrite32 (KERNEL32.591)
1113 * experimenation yields that _lwrite:
1114 * o truncates the file at the current position with
1116 * o returns 0 on a 0 length write
1117 * o works with console handles
1120 LONG WINAPI _hwrite32( HFILE32 handle, LPCSTR buffer, LONG count )
1124 BOOL32 status = FALSE;
1126 TRACE(file, "%d %p %ld\n", handle, buffer, count );
1128 if (count == 0) { /* Expand or truncate at current position */
1129 FILE_OBJECT *file = FILE_GetFile(handle);
1131 if ( ftruncate(file->unix_handle,
1132 lseek( file->unix_handle, 0, SEEK_CUR)) == 0 ) {
1133 FILE_ReleaseFile(file);
1137 FILE_ReleaseFile(file);
1138 return HFILE_ERROR32;
1142 if (!(ioptr = HANDLE_GetObjPtr( PROCESS_Current(), handle,
1143 K32OBJ_UNKNOWN, 0 )))
1144 return HFILE_ERROR32;
1145 if (K32OBJ_OPS(ioptr)->write)
1146 status = K32OBJ_OPS(ioptr)->write(ioptr, buffer, count, &result, NULL);
1147 K32OBJ_DecCount( ioptr );
1148 if (!status) result = HFILE_ERROR32;
1153 /***********************************************************************
1154 * SetHandleCount16 (KERNEL.199)
1156 UINT16 WINAPI SetHandleCount16( UINT16 count )
1158 HGLOBAL16 hPDB = GetCurrentPDB();
1159 PDB *pdb = (PDB *)GlobalLock16( hPDB );
1160 BYTE *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
1162 TRACE(file, "(%d)\n", count );
1164 if (count < 20) count = 20; /* No point in going below 20 */
1165 else if (count > 254) count = 254;
1169 if (pdb->nbFiles > 20)
1171 memcpy( pdb->fileHandles, files, 20 );
1172 GlobalFree16( pdb->hFileHandles );
1173 pdb->fileHandlesPtr = (SEGPTR)MAKELONG( 0x18,
1174 GlobalHandleToSel( hPDB ) );
1175 pdb->hFileHandles = 0;
1179 else /* More than 20, need a new file handles table */
1182 HGLOBAL16 newhandle = GlobalAlloc16( GMEM_MOVEABLE, count );
1185 DOS_ERROR( ER_OutOfMemory, EC_OutOfResource, SA_Abort, EL_Memory );
1186 return pdb->nbFiles;
1188 newfiles = (BYTE *)GlobalLock16( newhandle );
1190 if (count > pdb->nbFiles)
1192 memcpy( newfiles, files, pdb->nbFiles );
1193 memset( newfiles + pdb->nbFiles, 0xff, count - pdb->nbFiles );
1195 else memcpy( newfiles, files, count );
1196 if (pdb->nbFiles > 20) GlobalFree16( pdb->hFileHandles );
1197 pdb->fileHandlesPtr = WIN16_GlobalLock16( newhandle );
1198 pdb->hFileHandles = newhandle;
1199 pdb->nbFiles = count;
1201 return pdb->nbFiles;
1205 /*************************************************************************
1206 * SetHandleCount32 (KERNEL32.494)
1208 UINT32 WINAPI SetHandleCount32( UINT32 count )
1210 return MIN( 256, count );
1214 /***********************************************************************
1215 * FlushFileBuffers (KERNEL32.133)
1217 BOOL32 WINAPI FlushFileBuffers( HFILE32 hFile )
1222 TRACE(file, "(%d)\n", hFile );
1223 if (!(file = FILE_GetFile( hFile ))) return FALSE;
1224 if (fsync( file->unix_handle ) != -1) ret = TRUE;
1230 FILE_ReleaseFile( file );
1235 /**************************************************************************
1236 * SetEndOfFile (KERNEL32.483)
1238 BOOL32 WINAPI SetEndOfFile( HFILE32 hFile )
1243 TRACE(file, "(%d)\n", hFile );
1244 if (!(file = FILE_GetFile( hFile ))) return FALSE;
1245 if (ftruncate( file->unix_handle,
1246 lseek( file->unix_handle, 0, SEEK_CUR ) ))
1251 FILE_ReleaseFile( file );
1256 /***********************************************************************
1257 * DeleteFile16 (KERNEL.146)
1259 BOOL16 WINAPI DeleteFile16( LPCSTR path )
1261 return DeleteFile32A( path );
1265 /***********************************************************************
1266 * DeleteFile32A (KERNEL32.71)
1268 BOOL32 WINAPI DeleteFile32A( LPCSTR path )
1270 DOS_FULL_NAME full_name;
1272 TRACE(file, "'%s'\n", path );
1274 if (DOSFS_IsDevice( path ))
1276 WARN(file, "cannot remove DOS device '%s'!\n", path);
1277 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
1281 if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
1282 if (unlink( full_name.long_name ) == -1)
1291 /***********************************************************************
1292 * DeleteFile32W (KERNEL32.72)
1294 BOOL32 WINAPI DeleteFile32W( LPCWSTR path )
1296 LPSTR xpath = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
1297 BOOL32 ret = DeleteFile32A( xpath );
1298 HeapFree( GetProcessHeap(), 0, xpath );
1303 /***********************************************************************
1306 BOOL32 FILE_SetFileType( HFILE32 hFile, DWORD type )
1308 FILE_OBJECT *file = FILE_GetFile( hFile );
1309 if (!file) return FALSE;
1311 FILE_ReleaseFile( file );
1316 /***********************************************************************
1319 LPVOID FILE_mmap( HFILE32 hFile, LPVOID start,
1320 DWORD size_high, DWORD size_low,
1321 DWORD offset_high, DWORD offset_low,
1322 int prot, int flags )
1325 FILE_OBJECT *file = FILE_GetFile( hFile );
1326 if (!file) return (LPVOID)-1;
1327 ret = FILE_dommap( file, start, size_high, size_low,
1328 offset_high, offset_low, prot, flags );
1329 FILE_ReleaseFile( file );
1334 /***********************************************************************
1337 LPVOID FILE_dommap( FILE_OBJECT *file, LPVOID start,
1338 DWORD size_high, DWORD size_low,
1339 DWORD offset_high, DWORD offset_low,
1340 int prot, int flags )
1346 if (size_high || offset_high)
1347 FIXME(file, "offsets larger than 4Gb not supported\n");
1354 static int fdzero = -1;
1358 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
1360 perror( "/dev/zero: open" );
1365 #endif /* MAP_ANON */
1366 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
1368 flags &= ~MAP_SHARED;
1371 flags |= MAP_PRIVATE;
1374 else fd = file->unix_handle;
1376 if ((ret = mmap( start, size_low, prot,
1377 flags, fd, offset_low )) != (LPVOID)-1)
1380 /* mmap() failed; if this is because the file offset is not */
1381 /* page-aligned (EINVAL), or because the underlying filesystem */
1382 /* does not support mmap() (ENOEXEC), we do it by hand. */
1384 if (!file) return ret;
1385 if ((errno != ENOEXEC) && (errno != EINVAL)) return ret;
1386 if (prot & PROT_WRITE)
1388 /* We cannot fake shared write mappings */
1390 if (flags & MAP_SHARED) return ret;
1393 if (!(flags & MAP_PRIVATE)) return ret;
1396 /* printf( "FILE_mmap: mmap failed (%d), faking it\n", errno );*/
1397 /* Reserve the memory with an anonymous mmap */
1398 ret = FILE_dommap( NULL, start, size_high, size_low, 0, 0,
1399 PROT_READ | PROT_WRITE, flags );
1400 if (ret == (LPVOID)-1) return ret;
1401 /* Now read in the file */
1402 if ((pos = lseek( fd, offset_low, SEEK_SET )) == -1)
1404 FILE_munmap( ret, size_high, size_low );
1407 read( fd, ret, size_low );
1408 lseek( fd, pos, SEEK_SET ); /* Restore the file pointer */
1409 mprotect( ret, size_low, prot ); /* Set the right protection */
1414 /***********************************************************************
1417 int FILE_munmap( LPVOID start, DWORD size_high, DWORD size_low )
1420 FIXME(file, "offsets larger than 4Gb not supported\n");
1421 return munmap( start, size_low );
1425 /***********************************************************************
1426 * GetFileType (KERNEL32.222)
1428 DWORD WINAPI GetFileType( HFILE32 hFile )
1430 FILE_OBJECT *file = FILE_GetFile(hFile);
1431 if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
1432 FILE_ReleaseFile( file );
1437 /**************************************************************************
1438 * MoveFileEx32A (KERNEL32.???)
1440 BOOL32 WINAPI MoveFileEx32A( LPCSTR fn1, LPCSTR fn2, DWORD flag )
1442 DOS_FULL_NAME full_name1, full_name2;
1443 int mode=0; /* mode == 1: use copy */
1445 TRACE(file, "(%s,%s,%04lx)\n", fn1, fn2, flag);
1447 if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
1448 if (fn2) { /* !fn2 means delete fn1 */
1449 if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
1450 /* Source name and target path are valid */
1451 if ( full_name1.drive != full_name2.drive)
1452 /* use copy, if allowed */
1453 if (!(flag & MOVEFILE_COPY_ALLOWED)) {
1454 /* FIXME: Use right error code */
1455 DOS_ERROR( ER_FileExists, EC_Exists, SA_Abort, EL_Disk );
1459 if (DOSFS_GetFullName( fn2, TRUE, &full_name2 ))
1460 /* target exists, check if we may overwrite */
1461 if (!(flag & MOVEFILE_REPLACE_EXISTING)) {
1462 /* FIXME: Use right error code */
1463 DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
1467 else /* fn2 == NULL means delete source */
1468 if (flag & MOVEFILE_DELAY_UNTIL_REBOOT) {
1469 if (flag & MOVEFILE_COPY_ALLOWED) {
1470 WARN(file, "Illegal flag\n");
1471 DOS_ERROR( ER_GeneralFailure, EC_SystemFailure, SA_Abort,
1475 /* FIXME: (bon@elektron.ikp.physik.th-darmstadt.de 970706)
1476 Perhaps we should queue these command and execute it
1477 when exiting... What about using on_exit(2)
1479 FIXME(file, "Please delete file '%s' when Wine has finished\n",
1480 full_name1.long_name);
1483 else if (unlink( full_name1.long_name ) == -1)
1488 else return TRUE; /* successfully deleted */
1490 if (flag & MOVEFILE_DELAY_UNTIL_REBOOT) {
1491 /* FIXME: (bon@elektron.ikp.physik.th-darmstadt.de 970706)
1492 Perhaps we should queue these command and execute it
1493 when exiting... What about using on_exit(2)
1495 FIXME(file,"Please move existing file '%s' to file '%s'"
1496 "when Wine has finished\n",
1497 full_name1.long_name, full_name2.long_name);
1501 if (!mode) /* move the file */
1502 if (rename( full_name1.long_name, full_name2.long_name ) == -1)
1508 else /* copy File */
1509 return CopyFile32A(fn1, fn2, (!(flag & MOVEFILE_REPLACE_EXISTING)));
1513 /**************************************************************************
1514 * MoveFileEx32W (KERNEL32.???)
1516 BOOL32 WINAPI MoveFileEx32W( LPCWSTR fn1, LPCWSTR fn2, DWORD flag )
1518 LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
1519 LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
1520 BOOL32 res = MoveFileEx32A( afn1, afn2, flag );
1521 HeapFree( GetProcessHeap(), 0, afn1 );
1522 HeapFree( GetProcessHeap(), 0, afn2 );
1527 /**************************************************************************
1528 * MoveFile32A (KERNEL32.387)
1530 * Move file or directory
1532 BOOL32 WINAPI MoveFile32A( LPCSTR fn1, LPCSTR fn2 )
1534 DOS_FULL_NAME full_name1, full_name2;
1537 TRACE(file, "(%s,%s)\n", fn1, fn2 );
1539 if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
1540 if (DOSFS_GetFullName( fn2, TRUE, &full_name2 ))
1541 /* The new name must not already exist */
1543 if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
1545 if (full_name1.drive == full_name2.drive) /* move */
1546 if (rename( full_name1.long_name, full_name2.long_name ) == -1)
1553 if (stat( full_name1.long_name, &fstat ))
1555 WARN(file, "Invalid source file %s\n",
1556 full_name1.long_name);
1560 if (S_ISDIR(fstat.st_mode)) {
1561 /* No Move for directories across file systems */
1562 /* FIXME: Use right error code */
1563 DOS_ERROR( ER_GeneralFailure, EC_SystemFailure, SA_Abort,
1568 return CopyFile32A(fn1, fn2, TRUE); /*fail, if exist */
1573 /**************************************************************************
1574 * MoveFile32W (KERNEL32.390)
1576 BOOL32 WINAPI MoveFile32W( LPCWSTR fn1, LPCWSTR fn2 )
1578 LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
1579 LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
1580 BOOL32 res = MoveFile32A( afn1, afn2 );
1581 HeapFree( GetProcessHeap(), 0, afn1 );
1582 HeapFree( GetProcessHeap(), 0, afn2 );
1587 /**************************************************************************
1588 * CopyFile32A (KERNEL32.36)
1590 BOOL32 WINAPI CopyFile32A( LPCSTR source, LPCSTR dest, BOOL32 fail_if_exists )
1593 BY_HANDLE_FILE_INFORMATION info;
1599 if ((h1 = _lopen32( source, OF_READ )) == HFILE_ERROR32) return FALSE;
1600 if (!GetFileInformationByHandle( h1, &info ))
1605 mode = (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
1606 if ((h2 = FILE_Create( dest, mode, fail_if_exists )) == HFILE_ERROR32)
1611 while ((count = _lread32( h1, buffer, sizeof(buffer) )) > 0)
1616 INT32 res = _lwrite32( h2, p, count );
1617 if (res <= 0) goto done;
1630 /**************************************************************************
1631 * CopyFile32W (KERNEL32.37)
1633 BOOL32 WINAPI CopyFile32W( LPCWSTR source, LPCWSTR dest, BOOL32 fail_if_exists)
1635 LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, source );
1636 LPSTR destA = HEAP_strdupWtoA( GetProcessHeap(), 0, dest );
1637 BOOL32 ret = CopyFile32A( sourceA, destA, fail_if_exists );
1638 HeapFree( GetProcessHeap(), 0, sourceA );
1639 HeapFree( GetProcessHeap(), 0, destA );
1644 /***********************************************************************
1645 * SetFileTime (KERNEL32.493)
1647 BOOL32 WINAPI SetFileTime( HFILE32 hFile,
1648 const FILETIME *lpCreationTime,
1649 const FILETIME *lpLastAccessTime,
1650 const FILETIME *lpLastWriteTime )
1652 FILE_OBJECT *file = FILE_GetFile(hFile);
1653 struct utimbuf utimbuf;
1655 if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
1656 TRACE(file,"(%s,%p,%p,%p)\n",
1662 if (lpLastAccessTime)
1663 utimbuf.actime = DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
1665 utimbuf.actime = 0; /* FIXME */
1666 if (lpLastWriteTime)
1667 utimbuf.modtime = DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
1669 utimbuf.modtime = 0; /* FIXME */
1670 if (-1==utime(file->unix_name,&utimbuf))
1672 FILE_ReleaseFile( file );
1676 FILE_ReleaseFile( file );
1680 /* Locks need to be mirrored because unix file locking is based
1681 * on the pid. Inside of wine there can be multiple WINE processes
1682 * that share the same unix pid.
1683 * Read's and writes should check these locks also - not sure
1684 * how critical that is at this point (FIXME).
1687 static BOOL32 DOS_AddLock(FILE_OBJECT *file, struct flock *f)
1689 DOS_FILE_LOCK *curr;
1692 processId = GetCurrentProcessId();
1694 /* check if lock overlaps a current lock for the same file */
1695 for (curr = locks; curr; curr = curr->next) {
1696 if (strcmp(curr->unix_name, file->unix_name) == 0) {
1697 if ((f->l_start == curr->base) && (f->l_len == curr->len))
1698 return TRUE;/* region is identic */
1699 if ((f->l_start < (curr->base + curr->len)) &&
1700 ((f->l_start + f->l_len) > curr->base)) {
1701 /* region overlaps */
1707 curr = HeapAlloc( SystemHeap, 0, sizeof(DOS_FILE_LOCK) );
1708 curr->processId = GetCurrentProcessId();
1709 curr->base = f->l_start;
1710 curr->len = f->l_len;
1711 curr->unix_name = HEAP_strdupA( SystemHeap, 0, file->unix_name);
1713 curr->dos_file = file;
1718 static void DOS_RemoveFileLocks(FILE_OBJECT *file)
1721 DOS_FILE_LOCK **curr;
1724 processId = GetCurrentProcessId();
1727 if ((*curr)->dos_file == file) {
1729 *curr = (*curr)->next;
1730 HeapFree( SystemHeap, 0, rem->unix_name );
1731 HeapFree( SystemHeap, 0, rem );
1734 curr = &(*curr)->next;
1738 static BOOL32 DOS_RemoveLock(FILE_OBJECT *file, struct flock *f)
1741 DOS_FILE_LOCK **curr;
1744 processId = GetCurrentProcessId();
1745 for (curr = &locks; *curr; curr = &(*curr)->next) {
1746 if ((*curr)->processId == processId &&
1747 (*curr)->dos_file == file &&
1748 (*curr)->base == f->l_start &&
1749 (*curr)->len == f->l_len) {
1750 /* this is the same lock */
1752 *curr = (*curr)->next;
1753 HeapFree( SystemHeap, 0, rem->unix_name );
1754 HeapFree( SystemHeap, 0, rem );
1758 /* no matching lock found */
1763 /**************************************************************************
1764 * LockFile (KERNEL32.511)
1766 BOOL32 WINAPI LockFile(
1767 HFILE32 hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
1768 DWORD nNumberOfBytesToLockLow,DWORD nNumberOfBytesToLockHigh )
1773 TRACE(file, "handle %d offsetlow=%ld offsethigh=%ld nbyteslow=%ld nbyteshigh=%ld\n",
1774 hFile, dwFileOffsetLow, dwFileOffsetHigh,
1775 nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
1777 if (dwFileOffsetHigh || nNumberOfBytesToLockHigh) {
1778 FIXME(file, "Unimplemented bytes > 32bits\n");
1782 f.l_start = dwFileOffsetLow;
1783 f.l_len = nNumberOfBytesToLockLow;
1784 f.l_whence = SEEK_SET;
1788 if (!(file = FILE_GetFile(hFile))) return FALSE;
1790 /* shadow locks internally */
1791 if (!DOS_AddLock(file, &f)) {
1792 DOS_ERROR( ER_LockViolation, EC_AccessDenied, SA_Ignore, EL_Disk );
1796 /* FIXME: Unix locking commented out for now, doesn't work with Excel */
1797 #ifdef USE_UNIX_LOCKS
1798 if (fcntl(file->unix_handle, F_SETLK, &f) == -1) {
1799 if (errno == EACCES || errno == EAGAIN) {
1800 DOS_ERROR( ER_LockViolation, EC_AccessDenied, SA_Ignore, EL_Disk );
1805 /* remove our internal copy of the lock */
1806 DOS_RemoveLock(file, &f);
1814 /**************************************************************************
1815 * UnlockFile (KERNEL32.703)
1817 BOOL32 WINAPI UnlockFile(
1818 HFILE32 hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
1819 DWORD nNumberOfBytesToUnlockLow,DWORD nNumberOfBytesToUnlockHigh )
1824 TRACE(file, "handle %d offsetlow=%ld offsethigh=%ld nbyteslow=%ld nbyteshigh=%ld\n",
1825 hFile, dwFileOffsetLow, dwFileOffsetHigh,
1826 nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
1828 if (dwFileOffsetHigh || nNumberOfBytesToUnlockHigh) {
1829 WARN(file, "Unimplemented bytes > 32bits\n");
1833 f.l_start = dwFileOffsetLow;
1834 f.l_len = nNumberOfBytesToUnlockLow;
1835 f.l_whence = SEEK_SET;
1839 if (!(file = FILE_GetFile(hFile))) return FALSE;
1841 DOS_RemoveLock(file, &f); /* ok if fails - may be another wine */
1843 /* FIXME: Unix locking commented out for now, doesn't work with Excel */
1844 #ifdef USE_UNIX_LOCKS
1845 if (fcntl(file->unix_handle, F_SETLK, &f) == -1) {