2 * File handling functions
4 * Copyright 1993 John Burton
5 * Copyright 1996, 2004 Alexandre Julliard
6 * Copyright 2008 Jeff Zaroyko
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
31 #define WIN32_NO_STATUS
37 #include "ddk/ntddk.h"
38 #include "kernel_private.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(file
);
46 /***********************************************************************
49 * Wrapper for CreateFile that takes OF_* mode flags.
51 static HANDLE
create_file_OF( LPCSTR path
, INT mode
)
53 DWORD access
, sharing
, creation
;
57 creation
= CREATE_ALWAYS
;
58 access
= GENERIC_READ
| GENERIC_WRITE
;
62 creation
= OPEN_EXISTING
;
65 case OF_READ
: access
= GENERIC_READ
; break;
66 case OF_WRITE
: access
= GENERIC_WRITE
; break;
67 case OF_READWRITE
: access
= GENERIC_READ
| GENERIC_WRITE
; break;
68 default: access
= 0; break;
74 case OF_SHARE_EXCLUSIVE
: sharing
= 0; break;
75 case OF_SHARE_DENY_WRITE
: sharing
= FILE_SHARE_READ
; break;
76 case OF_SHARE_DENY_READ
: sharing
= FILE_SHARE_WRITE
; break;
77 case OF_SHARE_DENY_NONE
:
79 default: sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
; break;
81 return CreateFileA( path
, access
, sharing
, NULL
, creation
, FILE_ATTRIBUTE_NORMAL
, 0 );
85 /***********************************************************************
88 * Convert a file name to Unicode, taking into account the OEM/Ansi API mode.
90 * If alloc is FALSE uses the TEB static buffer, so it can only be used when
91 * there is no possibility for the function to do that twice, taking into
92 * account any called function.
94 WCHAR
*FILE_name_AtoW( LPCSTR name
, BOOL alloc
)
97 UNICODE_STRING strW
, *pstrW
;
100 RtlInitAnsiString( &str
, name
);
101 pstrW
= alloc
? &strW
: &NtCurrentTeb()->StaticUnicodeString
;
102 if (!AreFileApisANSI())
103 status
= RtlOemStringToUnicodeString( pstrW
, &str
, alloc
);
105 status
= RtlAnsiStringToUnicodeString( pstrW
, &str
, alloc
);
106 if (status
== STATUS_SUCCESS
) return pstrW
->Buffer
;
108 if (status
== STATUS_BUFFER_OVERFLOW
)
109 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
111 SetLastError( RtlNtStatusToDosError(status
) );
116 /***********************************************************************
119 * Convert a file name back to OEM/Ansi. Returns number of bytes copied.
121 DWORD
FILE_name_WtoA( LPCWSTR src
, INT srclen
, LPSTR dest
, INT destlen
)
125 if (srclen
< 0) srclen
= lstrlenW( src
) + 1;
128 if (!AreFileApisANSI())
131 strW
.Buffer
= (WCHAR
*)src
;
132 strW
.Length
= srclen
* sizeof(WCHAR
);
133 ret
= RtlUnicodeStringToOemSize( &strW
) - 1;
136 RtlUnicodeToMultiByteSize( &ret
, src
, srclen
* sizeof(WCHAR
) );
140 if (!AreFileApisANSI())
141 RtlUnicodeToOemN( dest
, destlen
, &ret
, src
, srclen
* sizeof(WCHAR
) );
143 RtlUnicodeToMultiByteN( dest
, destlen
, &ret
, src
, srclen
* sizeof(WCHAR
) );
149 /***********************************************************************
150 * _hread (KERNEL32.@)
152 LONG WINAPI
_hread( HFILE hFile
, LPVOID buffer
, LONG count
)
154 return _lread( hFile
, buffer
, count
);
158 /***********************************************************************
159 * _hwrite (KERNEL32.@)
161 * experimentation yields that _lwrite:
162 * o truncates the file at the current position with
164 * o returns 0 on a 0 length write
165 * o works with console handles
168 LONG WINAPI
_hwrite( HFILE handle
, LPCSTR buffer
, LONG count
)
172 TRACE("%d %p %d\n", handle
, buffer
, count
);
176 /* Expand or truncate at current position */
177 if (!SetEndOfFile( LongToHandle(handle
) )) return HFILE_ERROR
;
180 if (!WriteFile( LongToHandle(handle
), buffer
, count
, &result
, NULL
))
186 /***********************************************************************
187 * _lclose (KERNEL32.@)
189 HFILE WINAPI
_lclose( HFILE hFile
)
191 TRACE("handle %d\n", hFile
);
192 return CloseHandle( LongToHandle(hFile
) ) ? 0 : HFILE_ERROR
;
196 /***********************************************************************
197 * _lcreat (KERNEL32.@)
199 HFILE WINAPI
_lcreat( LPCSTR path
, INT attr
)
203 /* Mask off all flags not explicitly allowed by the doc */
204 attr
&= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
;
205 TRACE("%s %02x\n", path
, attr
);
206 hfile
= CreateFileA( path
, GENERIC_READ
| GENERIC_WRITE
,
207 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
208 CREATE_ALWAYS
, attr
, 0 );
209 return HandleToLong(hfile
);
213 /***********************************************************************
214 * _lopen (KERNEL32.@)
216 HFILE WINAPI
_lopen( LPCSTR path
, INT mode
)
220 TRACE("(%s,%04x)\n", debugstr_a(path
), mode
);
221 hfile
= create_file_OF( path
, mode
& ~OF_CREATE
);
222 return HandleToLong(hfile
);
225 /***********************************************************************
226 * _lread (KERNEL32.@)
228 UINT WINAPI
_lread( HFILE handle
, LPVOID buffer
, UINT count
)
231 if (!ReadFile( LongToHandle(handle
), buffer
, count
, &result
, NULL
))
237 /***********************************************************************
238 * _llseek (KERNEL32.@)
240 LONG WINAPI
_llseek( HFILE hFile
, LONG lOffset
, INT nOrigin
)
242 return SetFilePointer( LongToHandle(hFile
), lOffset
, NULL
, nOrigin
);
246 /***********************************************************************
247 * _lwrite (KERNEL32.@)
249 UINT WINAPI
_lwrite( HFILE hFile
, LPCSTR buffer
, UINT count
)
251 return (UINT
)_hwrite( hFile
, buffer
, (LONG
)count
);
255 /**************************************************************************
256 * SetFileCompletionNotificationModes (KERNEL32.@)
258 BOOL WINAPI
SetFileCompletionNotificationModes( HANDLE file
, UCHAR flags
)
260 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info
;
264 return set_ntstatus( NtSetInformationFile( file
, &io
, &info
, sizeof(info
),
265 FileIoCompletionNotificationInformation
));
269 /*************************************************************************
270 * SetHandleCount (KERNEL32.@)
272 UINT WINAPI
SetHandleCount( UINT count
)
278 /***********************************************************************
279 * DosDateTimeToFileTime (KERNEL32.@)
281 BOOL WINAPI
DosDateTimeToFileTime( WORD fatdate
, WORD fattime
, FILETIME
*ft
)
286 fields
.Year
= (fatdate
>> 9) + 1980;
287 fields
.Month
= ((fatdate
>> 5) & 0x0f);
288 fields
.Day
= (fatdate
& 0x1f);
289 fields
.Hour
= (fattime
>> 11);
290 fields
.Minute
= (fattime
>> 5) & 0x3f;
291 fields
.Second
= (fattime
& 0x1f) * 2;
292 fields
.Milliseconds
= 0;
293 if (!RtlTimeFieldsToTime( &fields
, &time
)) return FALSE
;
294 ft
->dwLowDateTime
= time
.u
.LowPart
;
295 ft
->dwHighDateTime
= time
.u
.HighPart
;
300 /***********************************************************************
301 * FileTimeToDosDateTime (KERNEL32.@)
303 BOOL WINAPI
FileTimeToDosDateTime( const FILETIME
*ft
, WORD
*fatdate
, WORD
*fattime
)
308 if (!fatdate
|| !fattime
)
310 SetLastError( ERROR_INVALID_PARAMETER
);
313 time
.u
.LowPart
= ft
->dwLowDateTime
;
314 time
.u
.HighPart
= ft
->dwHighDateTime
;
315 RtlTimeToTimeFields( &time
, &fields
);
316 if (fields
.Year
< 1980)
318 SetLastError( ERROR_INVALID_PARAMETER
);
321 *fattime
= (fields
.Hour
<< 11) + (fields
.Minute
<< 5) + (fields
.Second
/ 2);
322 *fatdate
= ((fields
.Year
- 1980) << 9) + (fields
.Month
<< 5) + fields
.Day
;
327 /**************************************************************************
328 * Operations on file names *
329 **************************************************************************/
332 /**************************************************************************
333 * ReplaceFileA (KERNEL32.@)
335 BOOL WINAPI
ReplaceFileA(LPCSTR lpReplacedFileName
,LPCSTR lpReplacementFileName
,
336 LPCSTR lpBackupFileName
, DWORD dwReplaceFlags
,
337 LPVOID lpExclude
, LPVOID lpReserved
)
339 WCHAR
*replacedW
, *replacementW
, *backupW
= NULL
;
342 /* This function only makes sense when the first two parameters are defined */
343 if (!lpReplacedFileName
|| !(replacedW
= FILE_name_AtoW( lpReplacedFileName
, TRUE
)))
345 SetLastError(ERROR_INVALID_PARAMETER
);
348 if (!lpReplacementFileName
|| !(replacementW
= FILE_name_AtoW( lpReplacementFileName
, TRUE
)))
350 HeapFree( GetProcessHeap(), 0, replacedW
);
351 SetLastError(ERROR_INVALID_PARAMETER
);
354 /* The backup parameter, however, is optional */
355 if (lpBackupFileName
)
357 if (!(backupW
= FILE_name_AtoW( lpBackupFileName
, TRUE
)))
359 HeapFree( GetProcessHeap(), 0, replacedW
);
360 HeapFree( GetProcessHeap(), 0, replacementW
);
361 SetLastError(ERROR_INVALID_PARAMETER
);
365 ret
= ReplaceFileW( replacedW
, replacementW
, backupW
, dwReplaceFlags
, lpExclude
, lpReserved
);
366 HeapFree( GetProcessHeap(), 0, replacedW
);
367 HeapFree( GetProcessHeap(), 0, replacementW
);
368 HeapFree( GetProcessHeap(), 0, backupW
);
373 /***********************************************************************
374 * OpenVxDHandle (KERNEL32.@)
376 * This function is supposed to return the corresponding Ring 0
377 * ("kernel") handle for a Ring 3 handle in Win9x.
378 * Evidently, Wine will have problems with this. But we try anyway,
381 HANDLE WINAPI
OpenVxDHandle(HANDLE hHandleRing3
)
383 FIXME( "(%p), stub! (returning Ring 3 handle instead of Ring 0)\n", hHandleRing3
);
388 /****************************************************************************
389 * DeviceIoControl (KERNEL32.@)
391 BOOL WINAPI
KERNEL32_DeviceIoControl( HANDLE handle
, DWORD code
, void *in_buff
, DWORD in_count
,
392 void *out_buff
, DWORD out_count
, DWORD
*returned
,
393 OVERLAPPED
*overlapped
)
395 TRACE( "(%p,%#x,%p,%d,%p,%d,%p,%p)\n",
396 handle
, code
, in_buff
, in_count
, out_buff
, out_count
, returned
, overlapped
);
398 /* Check if this is a user defined control code for a VxD */
400 if (HIWORD( code
) == 0 && (GetVersion() & 0x80000000))
402 typedef BOOL (WINAPI
*DeviceIoProc
)(DWORD
, LPVOID
, DWORD
, LPVOID
, DWORD
, LPDWORD
, LPOVERLAPPED
);
403 static DeviceIoProc (*vxd_get_proc
)(HANDLE
);
404 DeviceIoProc proc
= NULL
;
406 if (!vxd_get_proc
) vxd_get_proc
= (void *)GetProcAddress( GetModuleHandleW(L
"krnl386.exe16"),
407 "__wine_vxd_get_proc" );
408 if (vxd_get_proc
) proc
= vxd_get_proc( handle
);
409 if (proc
) return proc( code
, in_buff
, in_count
, out_buff
, out_count
, returned
, overlapped
);
412 return DeviceIoControl( handle
, code
, in_buff
, in_count
, out_buff
, out_count
, returned
, overlapped
);
416 /***********************************************************************
417 * OpenFile (KERNEL32.@)
419 HFILE WINAPI
OpenFile( LPCSTR name
, OFSTRUCT
*ofs
, UINT mode
)
423 WORD filedatetime
[2];
426 if (!ofs
) return HFILE_ERROR
;
428 TRACE("%s %s %s %s%s%s%s%s%s%s%s%s\n",name
,
429 ((mode
& 0x3 )==OF_READ
)?"OF_READ":
430 ((mode
& 0x3 )==OF_WRITE
)?"OF_WRITE":
431 ((mode
& 0x3 )==OF_READWRITE
)?"OF_READWRITE":"unknown",
432 ((mode
& 0x70 )==OF_SHARE_COMPAT
)?"OF_SHARE_COMPAT":
433 ((mode
& 0x70 )==OF_SHARE_DENY_NONE
)?"OF_SHARE_DENY_NONE":
434 ((mode
& 0x70 )==OF_SHARE_DENY_READ
)?"OF_SHARE_DENY_READ":
435 ((mode
& 0x70 )==OF_SHARE_DENY_WRITE
)?"OF_SHARE_DENY_WRITE":
436 ((mode
& 0x70 )==OF_SHARE_EXCLUSIVE
)?"OF_SHARE_EXCLUSIVE":"unknown",
437 ((mode
& OF_PARSE
)==OF_PARSE
)?"OF_PARSE ":"",
438 ((mode
& OF_DELETE
)==OF_DELETE
)?"OF_DELETE ":"",
439 ((mode
& OF_VERIFY
)==OF_VERIFY
)?"OF_VERIFY ":"",
440 ((mode
& OF_SEARCH
)==OF_SEARCH
)?"OF_SEARCH ":"",
441 ((mode
& OF_CANCEL
)==OF_CANCEL
)?"OF_CANCEL ":"",
442 ((mode
& OF_CREATE
)==OF_CREATE
)?"OF_CREATE ":"",
443 ((mode
& OF_PROMPT
)==OF_PROMPT
)?"OF_PROMPT ":"",
444 ((mode
& OF_EXIST
)==OF_EXIST
)?"OF_EXIST ":"",
445 ((mode
& OF_REOPEN
)==OF_REOPEN
)?"OF_REOPEN ":""
449 ofs
->cBytes
= sizeof(OFSTRUCT
);
451 if (mode
& OF_REOPEN
) name
= ofs
->szPathName
;
453 if (!name
) return HFILE_ERROR
;
455 TRACE("%s %04x\n", name
, mode
);
457 /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
458 Are there any cases where getting the path here is wrong?
459 Uwe Bonnes 1997 Apr 2 */
460 len
= GetFullPathNameA( name
, sizeof(ofs
->szPathName
), ofs
->szPathName
, NULL
);
461 if (!len
) goto error
;
462 if (len
>= sizeof(ofs
->szPathName
))
464 SetLastError(ERROR_INVALID_DATA
);
468 /* OF_PARSE simply fills the structure */
472 ofs
->fFixedDisk
= (GetDriveTypeA( ofs
->szPathName
) != DRIVE_REMOVABLE
);
473 TRACE("(%s): OF_PARSE, res = '%s'\n", name
, ofs
->szPathName
);
477 /* OF_CREATE is completely different from all other options, so
480 if (mode
& OF_CREATE
)
482 if ((handle
= create_file_OF( name
, mode
)) == INVALID_HANDLE_VALUE
)
487 /* Now look for the file */
489 len
= SearchPathA( NULL
, name
, NULL
, sizeof(ofs
->szPathName
), ofs
->szPathName
, NULL
);
490 if (!len
) goto error
;
491 if (len
>= sizeof(ofs
->szPathName
))
493 SetLastError(ERROR_INVALID_DATA
);
497 TRACE("found %s\n", debugstr_a(ofs
->szPathName
) );
499 if (mode
& OF_DELETE
)
501 if (!DeleteFileA( ofs
->szPathName
)) goto error
;
502 TRACE("(%s): OF_DELETE return = OK\n", name
);
506 handle
= LongToHandle(_lopen( ofs
->szPathName
, mode
));
507 if (handle
== INVALID_HANDLE_VALUE
) goto error
;
509 GetFileTime( handle
, NULL
, NULL
, &filetime
);
510 FileTimeToDosDateTime( &filetime
, &filedatetime
[0], &filedatetime
[1] );
511 if ((mode
& OF_VERIFY
) && (mode
& OF_REOPEN
))
513 if (ofs
->Reserved1
!= filedatetime
[0] || ofs
->Reserved2
!= filedatetime
[1] )
515 CloseHandle( handle
);
516 WARN("(%s): OF_VERIFY failed\n", name
);
517 /* FIXME: what error here? */
518 SetLastError( ERROR_FILE_NOT_FOUND
);
522 ofs
->Reserved1
= filedatetime
[0];
523 ofs
->Reserved2
= filedatetime
[1];
525 TRACE("(%s): OK, return = %p\n", name
, handle
);
526 if (mode
& OF_EXIST
) /* Return TRUE instead of a handle */
528 CloseHandle( handle
);
531 return HandleToLong(handle
);
533 error
: /* We get here if there was an error opening the file */
534 ofs
->nErrCode
= GetLastError();
535 WARN("(%s): return = HFILE_ERROR error= %d\n", name
,ofs
->nErrCode
);