2 * File handling functions
4 * Copyright 1993 Erik Bos
5 * Copyright 1996, 2004 Alexandre Julliard
6 * Copyright 2003 Eric Pouech
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
30 #define WIN32_NO_STATUS
36 #include "kernel_private.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(file
);
41 #define MAX_PATHNAME_LEN 1024
43 static const WCHAR system_dir
[] = L
"C:\\windows\\system32";
45 /***********************************************************************
48 * copy a file name back to OEM/Ansi, but only if the buffer is large enough
50 static DWORD
copy_filename_WtoA( LPCWSTR nameW
, LPSTR buffer
, DWORD len
)
54 BOOL is_ansi
= AreFileApisANSI();
56 RtlInitUnicodeString( &strW
, nameW
);
58 ret
= is_ansi
? RtlUnicodeStringToAnsiSize(&strW
) : RtlUnicodeStringToOemSize(&strW
);
59 if (buffer
&& ret
<= len
)
64 str
.MaximumLength
= min( len
, UNICODE_STRING_MAX_CHARS
);
66 RtlUnicodeStringToAnsiString( &str
, &strW
, FALSE
);
68 RtlUnicodeStringToOemString( &str
, &strW
, FALSE
);
69 ret
= str
.Length
; /* length without terminating 0 */
74 /***********************************************************************
75 * GetShortPathNameA (KERNEL32.@)
77 DWORD WINAPI
GetShortPathNameA( LPCSTR longpath
, LPSTR shortpath
, DWORD shortlen
)
80 WCHAR shortpathW
[MAX_PATH
];
83 TRACE("%s\n", debugstr_a(longpath
));
85 if (!(longpathW
= FILE_name_AtoW( longpath
, FALSE
))) return 0;
87 ret
= GetShortPathNameW(longpathW
, shortpathW
, MAX_PATH
);
92 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
95 return copy_filename_WtoA( shortpathW
, shortpath
, shortlen
);
99 /**************************************************************************
100 * CopyFileA (KERNEL32.@)
102 BOOL WINAPI
CopyFileA( LPCSTR source
, LPCSTR dest
, BOOL fail_if_exists
)
104 WCHAR
*sourceW
, *destW
;
107 if (!(sourceW
= FILE_name_AtoW( source
, FALSE
))) return FALSE
;
108 if (!(destW
= FILE_name_AtoW( dest
, TRUE
))) return FALSE
;
110 ret
= CopyFileW( sourceW
, destW
, fail_if_exists
);
112 HeapFree( GetProcessHeap(), 0, destW
);
117 /**************************************************************************
118 * CopyFileExA (KERNEL32.@)
120 BOOL WINAPI
CopyFileExA(LPCSTR sourceFilename
, LPCSTR destFilename
,
121 LPPROGRESS_ROUTINE progressRoutine
, LPVOID appData
,
122 LPBOOL cancelFlagPointer
, DWORD copyFlags
)
124 WCHAR
*sourceW
, *destW
;
127 /* can't use the TEB buffer since we may have a callback routine */
128 if (!(sourceW
= FILE_name_AtoW( sourceFilename
, TRUE
))) return FALSE
;
129 if (!(destW
= FILE_name_AtoW( destFilename
, TRUE
)))
131 HeapFree( GetProcessHeap(), 0, sourceW
);
134 ret
= CopyFileExW(sourceW
, destW
, progressRoutine
, appData
,
135 cancelFlagPointer
, copyFlags
);
136 HeapFree( GetProcessHeap(), 0, sourceW
);
137 HeapFree( GetProcessHeap(), 0, destW
);
141 /**************************************************************************
142 * MoveFileTransactedA (KERNEL32.@)
144 BOOL WINAPI
MoveFileTransactedA(const char *source
, const char *dest
, LPPROGRESS_ROUTINE progress
, void *data
, DWORD flags
, HANDLE handle
)
146 FIXME("(%s, %s, %p, %p, %ld, %p) semi-stub\n", debugstr_a(source
), debugstr_a(dest
), progress
, data
, flags
, handle
);
148 return MoveFileWithProgressA(source
, dest
, progress
, data
, flags
);
151 /**************************************************************************
152 * MoveFileTransactedW (KERNEL32.@)
154 BOOL WINAPI
MoveFileTransactedW(const WCHAR
*source
, const WCHAR
*dest
, LPPROGRESS_ROUTINE progress
, void *data
, DWORD flags
, HANDLE handle
)
156 FIXME("(%s, %s, %p, %p, %ld, %p) semi-stub\n", debugstr_w(source
), debugstr_w(dest
), progress
, data
, flags
, handle
);
158 return MoveFileWithProgressW(source
, dest
, progress
, data
, flags
);
161 /*************************************************************************
162 * CreateFileTransactedA (KERNEL32.@)
164 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileTransactedA( LPCSTR name
, DWORD access
, DWORD sharing
,
165 LPSECURITY_ATTRIBUTES sa
, DWORD creation
,
166 DWORD attributes
, HANDLE
template,
167 HANDLE transaction
, PUSHORT version
,
170 FIXME("(%s %lx %lx %p %lx %lx %p %p %p %p): semi-stub\n", debugstr_a(name
), access
, sharing
, sa
,
171 creation
, attributes
, template, transaction
, version
, param
);
172 return CreateFileA(name
, access
, sharing
, sa
, creation
, attributes
, template);
175 /*************************************************************************
176 * CreateFileTransactedW (KERNEL32.@)
178 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileTransactedW( LPCWSTR name
, DWORD access
, DWORD sharing
,
179 LPSECURITY_ATTRIBUTES sa
, DWORD creation
,
180 DWORD attributes
, HANDLE
template, HANDLE transaction
,
181 PUSHORT version
, PVOID param
)
183 FIXME("(%s %lx %lx %p %lx %lx %p %p %p %p): semi-stub\n", debugstr_w(name
), access
, sharing
, sa
,
184 creation
, attributes
, template, transaction
, version
, param
);
185 return CreateFileW(name
, access
, sharing
, sa
, creation
, attributes
, template);
188 /***********************************************************************
189 * CreateDirectoryTransactedA (KERNEL32.@)
191 BOOL WINAPI DECLSPEC_HOTPATCH
CreateDirectoryTransactedA(LPCSTR
template, LPCSTR path
, LPSECURITY_ATTRIBUTES sa
, HANDLE transaction
)
193 FIXME("(%s %s %p %p): semi-stub\n", debugstr_a(template), debugstr_a(path
), sa
, transaction
);
194 return CreateDirectoryExA(template, path
, sa
);
197 /***********************************************************************
198 * CreateDirectoryTransactedW (KERNEL32.@)
200 BOOL WINAPI DECLSPEC_HOTPATCH
CreateDirectoryTransactedW(LPCWSTR
template, LPCWSTR path
, LPSECURITY_ATTRIBUTES sa
, HANDLE transaction
)
202 FIXME("(%s %s %p %p): semi-stub\n", debugstr_w(template), debugstr_w(path
), sa
, transaction
);
203 return CreateDirectoryExW(template, path
, sa
);
206 /***********************************************************************
207 * DeleteFileTransactedA (KERNEL32.@)
209 BOOL WINAPI DECLSPEC_HOTPATCH
DeleteFileTransactedA(LPCSTR path
, HANDLE transaction
)
211 FIXME("(%s %p): semi-stub\n", debugstr_a(path
), transaction
);
212 return DeleteFileA(path
);
215 /***********************************************************************
216 * DeleteFileTransactedW (KERNEL32.@)
218 BOOL WINAPI DECLSPEC_HOTPATCH
DeleteFileTransactedW(LPCWSTR path
, HANDLE transaction
)
220 FIXME("(%s %p): semi-stub\n", debugstr_w(path
), transaction
);
221 return DeleteFileW(path
);
224 /******************************************************************************
225 * FindFirstFileTransactedA (KERNEL32.@)
227 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileTransactedA( LPCSTR filename
, FINDEX_INFO_LEVELS level
,
228 LPVOID data
, FINDEX_SEARCH_OPS search_op
,
229 LPVOID filter
, DWORD flags
, HANDLE transaction
)
231 FIXME("(%s %d %p %d %p %lx %p): semi-stub\n", debugstr_a(filename
), level
, data
, search_op
, filter
, flags
, transaction
);
232 return FindFirstFileExA(filename
, level
, data
, search_op
, filter
, flags
);
235 /******************************************************************************
236 * FindFirstFileTransactedW (KERNEL32.@)
238 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileTransactedW( LPCWSTR filename
, FINDEX_INFO_LEVELS level
,
239 LPVOID data
, FINDEX_SEARCH_OPS search_op
,
240 LPVOID filter
, DWORD flags
, HANDLE transaction
)
242 FIXME("(%s %d %p %d %p %lx %p): semi-stub\n", debugstr_w(filename
), level
, data
, search_op
, filter
, flags
, transaction
);
243 return FindFirstFileExW(filename
, level
, data
, search_op
, filter
, flags
);
247 /**************************************************************************
248 * GetFileAttributesTransactedA (KERNEL32.@)
250 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileAttributesTransactedA(LPCSTR name
, GET_FILEEX_INFO_LEVELS level
, void *ptr
, HANDLE transaction
)
252 FIXME("(%s %p): semi-stub\n", debugstr_a(name
), transaction
);
253 return GetFileAttributesExA(name
, level
, ptr
);
256 /**************************************************************************
257 * GetFileAttributesTransactedW (KERNEL32.@)
259 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileAttributesTransactedW(LPCWSTR name
, GET_FILEEX_INFO_LEVELS level
, void *ptr
, HANDLE transaction
)
261 FIXME("(%s %p): semi-stub\n", debugstr_w(name
), transaction
);
262 return GetFileAttributesExW(name
, level
, ptr
);
265 /***********************************************************************
266 * RemoveDirectoryTransactedA (KERNEL32.@)
268 BOOL WINAPI DECLSPEC_HOTPATCH
RemoveDirectoryTransactedA(LPCSTR path
, HANDLE transaction
)
270 FIXME("(%s %p): semi-stub\n", debugstr_a(path
), transaction
);
271 return RemoveDirectoryA(path
);
274 /***********************************************************************
275 * RemoveDirectoryTransactedW (KERNEL32.@)
277 BOOL WINAPI DECLSPEC_HOTPATCH
RemoveDirectoryTransactedW(LPCWSTR path
, HANDLE transaction
)
279 FIXME("(%s %p): semi-stub\n", debugstr_w(path
), transaction
);
280 return RemoveDirectoryW(path
);
283 /**************************************************************************
284 * MoveFileWithProgressA (KERNEL32.@)
286 BOOL WINAPI
MoveFileWithProgressA( LPCSTR source
, LPCSTR dest
,
287 LPPROGRESS_ROUTINE fnProgress
,
288 LPVOID param
, DWORD flag
)
290 WCHAR
*sourceW
, *destW
;
293 if (!(sourceW
= FILE_name_AtoW( source
, FALSE
))) return FALSE
;
296 if (!(destW
= FILE_name_AtoW( dest
, TRUE
))) return FALSE
;
301 ret
= MoveFileWithProgressW( sourceW
, destW
, fnProgress
, param
, flag
);
302 HeapFree( GetProcessHeap(), 0, destW
);
306 /**************************************************************************
307 * MoveFileExA (KERNEL32.@)
309 BOOL WINAPI
MoveFileExA( LPCSTR source
, LPCSTR dest
, DWORD flag
)
311 return MoveFileWithProgressA( source
, dest
, NULL
, NULL
, flag
);
315 /**************************************************************************
316 * MoveFileW (KERNEL32.@)
318 * Move file or directory
320 BOOL WINAPI
MoveFileW( LPCWSTR source
, LPCWSTR dest
)
322 return MoveFileExW( source
, dest
, MOVEFILE_COPY_ALLOWED
);
326 /**************************************************************************
327 * MoveFileA (KERNEL32.@)
329 BOOL WINAPI
MoveFileA( LPCSTR source
, LPCSTR dest
)
331 return MoveFileExA( source
, dest
, MOVEFILE_COPY_ALLOWED
);
335 /***********************************************************************
336 * CreateDirectoryExA (KERNEL32.@)
338 BOOL WINAPI
CreateDirectoryExA( LPCSTR
template, LPCSTR path
, LPSECURITY_ATTRIBUTES sa
)
340 WCHAR
*pathW
, *templateW
= NULL
;
343 if (!(pathW
= FILE_name_AtoW( path
, FALSE
))) return FALSE
;
344 if (template && !(templateW
= FILE_name_AtoW( template, TRUE
))) return FALSE
;
346 ret
= CreateDirectoryExW( templateW
, pathW
, sa
);
347 HeapFree( GetProcessHeap(), 0, templateW
);
352 /***********************************************************************
353 * GetSystemDirectoryW (KERNEL32.@)
355 * See comment for GetWindowsDirectoryA.
357 UINT WINAPI
GetSystemDirectoryW( LPWSTR path
, UINT count
)
359 UINT len
= ARRAY_SIZE(system_dir
);
360 if (path
&& count
>= len
)
362 lstrcpyW( path
, system_dir
);
369 /***********************************************************************
370 * GetSystemDirectoryA (KERNEL32.@)
372 * See comment for GetWindowsDirectoryA.
374 UINT WINAPI
GetSystemDirectoryA( LPSTR path
, UINT count
)
376 return copy_filename_WtoA( system_dir
, path
, count
);
380 /***********************************************************************
381 * wine_get_unix_file_name (KERNEL32.@) Not a Windows API
383 * Return the full Unix file name for a given path.
384 * Returned buffer must be freed by caller.
386 char * CDECL
wine_get_unix_file_name( LPCWSTR dosW
)
388 UNICODE_STRING nt_name
;
389 OBJECT_ATTRIBUTES attr
;
394 if (!RtlDosPathNameToNtPathName_U( dosW
, &nt_name
, NULL
, NULL
)) return NULL
;
395 InitializeObjectAttributes( &attr
, &nt_name
, 0, 0, NULL
);
398 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
)))
400 RtlFreeUnicodeString( &nt_name
);
403 status
= wine_nt_to_unix_file_name( &attr
, buffer
, &size
, FILE_OPEN_IF
);
404 if (status
!= STATUS_BUFFER_TOO_SMALL
) break;
405 HeapFree( GetProcessHeap(), 0, buffer
);
407 RtlFreeUnicodeString( &nt_name
);
408 if (status
&& status
!= STATUS_NO_SUCH_FILE
)
410 HeapFree( GetProcessHeap(), 0, buffer
);
411 SetLastError( RtlNtStatusToDosError( status
) );
418 /***********************************************************************
419 * wine_get_dos_file_name (KERNEL32.@) Not a Windows API
421 * Return the full DOS file name for a given Unix path.
422 * Returned buffer must be freed by caller.
424 WCHAR
* CDECL
wine_get_dos_file_name( LPCSTR str
)
426 UNICODE_STRING nt_name
;
429 ULONG len
= strlen(str
) + 1;
431 if (str
[0] != '/') /* relative path name */
433 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
434 MultiByteToWideChar( CP_UNIXCP
, 0, str
, len
, buffer
, len
);
435 status
= RtlDosPathNameToNtPathName_U_WithStatus( buffer
, &nt_name
, NULL
, NULL
);
436 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
437 if (!set_ntstatus( status
)) return NULL
;
438 buffer
= nt_name
.Buffer
;
439 len
= nt_name
.Length
/ sizeof(WCHAR
) + 1;
443 len
+= 8; /* \??\unix prefix */
444 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
445 if (!set_ntstatus( wine_unix_to_nt_file_name( str
, buffer
, &len
)))
447 HeapFree( GetProcessHeap(), 0, buffer
);
451 if (buffer
[5] == ':')
453 /* get rid of the \??\ prefix */
454 /* FIXME: should implement RtlNtPathNameToDosPathName and use that instead */
455 memmove( buffer
, buffer
+ 4, (len
- 4) * sizeof(WCHAR
) );
457 else buffer
[1] = '\\';
461 /*************************************************************************
462 * CreateSymbolicLinkA (KERNEL32.@)
464 BOOLEAN WINAPI
CreateSymbolicLinkA(LPCSTR link
, LPCSTR target
, DWORD flags
)
466 FIXME("(%s %s %ld): stub\n", debugstr_a(link
), debugstr_a(target
), flags
);
470 /*************************************************************************
471 * CreateHardLinkTransactedA (KERNEL32.@)
473 BOOL WINAPI
CreateHardLinkTransactedA(LPCSTR link
, LPCSTR target
, LPSECURITY_ATTRIBUTES sa
, HANDLE transaction
)
475 FIXME("(%s %s %p %p): stub\n", debugstr_a(link
), debugstr_a(target
), sa
, transaction
);
476 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
480 /*************************************************************************
481 * CreateHardLinkTransactedW (KERNEL32.@)
483 BOOL WINAPI
CreateHardLinkTransactedW(LPCWSTR link
, LPCWSTR target
, LPSECURITY_ATTRIBUTES sa
, HANDLE transaction
)
485 FIXME("(%s %s %p %p): stub\n", debugstr_w(link
), debugstr_w(target
), sa
, transaction
);
486 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
490 /*************************************************************************
491 * CheckNameLegalDOS8Dot3A (KERNEL32.@)
493 BOOL WINAPI
CheckNameLegalDOS8Dot3A(const char *name
, char *oemname
, DWORD oemname_len
,
494 BOOL
*contains_spaces
, BOOL
*is_legal
)
498 TRACE("(%s %p %lu %p %p)\n", name
, oemname
,
499 oemname_len
, contains_spaces
, is_legal
);
501 if (!name
|| !is_legal
)
504 if (!(nameW
= FILE_name_AtoW( name
, FALSE
))) return FALSE
;
506 return CheckNameLegalDOS8Dot3W( nameW
, oemname
, oemname_len
, contains_spaces
, is_legal
);
509 /*************************************************************************
510 * CheckNameLegalDOS8Dot3W (KERNEL32.@)
512 BOOL WINAPI
CheckNameLegalDOS8Dot3W(const WCHAR
*name
, char *oemname
, DWORD oemname_len
,
513 BOOL
*contains_spaces_ret
, BOOL
*is_legal
)
516 UNICODE_STRING nameW
;
517 BOOLEAN contains_spaces
;
519 TRACE("(%s %p %lu %p %p)\n", wine_dbgstr_w(name
), oemname
,
520 oemname_len
, contains_spaces_ret
, is_legal
);
522 if (!name
|| !is_legal
)
525 RtlInitUnicodeString( &nameW
, name
);
528 oem_str
.Length
= oemname_len
;
529 oem_str
.MaximumLength
= oemname_len
;
530 oem_str
.Buffer
= oemname
;
533 *is_legal
= RtlIsNameLegalDOS8Dot3( &nameW
, oemname
? &oem_str
: NULL
, &contains_spaces
);
534 if (contains_spaces_ret
) *contains_spaces_ret
= contains_spaces
;
539 /*************************************************************************
540 * SetSearchPathMode (KERNEL32.@)
542 BOOL WINAPI
SetSearchPathMode( DWORD flags
)
544 return set_ntstatus( RtlSetSearchPathMode( flags
));