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 /***********************************************************************
46 * copy a file name back to OEM/Ansi, but only if the buffer is large enough
48 static DWORD
copy_filename_WtoA( LPCWSTR nameW
, LPSTR buffer
, DWORD len
)
52 BOOL is_ansi
= AreFileApisANSI();
54 RtlInitUnicodeString( &strW
, nameW
);
56 ret
= is_ansi
? RtlUnicodeStringToAnsiSize(&strW
) : RtlUnicodeStringToOemSize(&strW
);
57 if (buffer
&& ret
<= len
)
62 str
.MaximumLength
= min( len
, UNICODE_STRING_MAX_CHARS
);
64 RtlUnicodeStringToAnsiString( &str
, &strW
, FALSE
);
66 RtlUnicodeStringToOemString( &str
, &strW
, FALSE
);
67 ret
= str
.Length
; /* length without terminating 0 */
72 /***********************************************************************
73 * GetShortPathNameA (KERNEL32.@)
75 DWORD WINAPI
GetShortPathNameA( LPCSTR longpath
, LPSTR shortpath
, DWORD shortlen
)
78 WCHAR shortpathW
[MAX_PATH
];
81 TRACE("%s\n", debugstr_a(longpath
));
83 if (!(longpathW
= FILE_name_AtoW( longpath
, FALSE
))) return 0;
85 ret
= GetShortPathNameW(longpathW
, shortpathW
, MAX_PATH
);
90 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
93 return copy_filename_WtoA( shortpathW
, shortpath
, shortlen
);
97 /**************************************************************************
98 * CopyFileA (KERNEL32.@)
100 BOOL WINAPI
CopyFileA( LPCSTR source
, LPCSTR dest
, BOOL fail_if_exists
)
102 WCHAR
*sourceW
, *destW
;
105 if (!(sourceW
= FILE_name_AtoW( source
, FALSE
))) return FALSE
;
106 if (!(destW
= FILE_name_AtoW( dest
, TRUE
))) return FALSE
;
108 ret
= CopyFileW( sourceW
, destW
, fail_if_exists
);
110 HeapFree( GetProcessHeap(), 0, destW
);
115 /**************************************************************************
116 * CopyFileExA (KERNEL32.@)
118 BOOL WINAPI
CopyFileExA(LPCSTR sourceFilename
, LPCSTR destFilename
,
119 LPPROGRESS_ROUTINE progressRoutine
, LPVOID appData
,
120 LPBOOL cancelFlagPointer
, DWORD copyFlags
)
122 WCHAR
*sourceW
, *destW
;
125 /* can't use the TEB buffer since we may have a callback routine */
126 if (!(sourceW
= FILE_name_AtoW( sourceFilename
, TRUE
))) return FALSE
;
127 if (!(destW
= FILE_name_AtoW( destFilename
, TRUE
)))
129 HeapFree( GetProcessHeap(), 0, sourceW
);
132 ret
= CopyFileExW(sourceW
, destW
, progressRoutine
, appData
,
133 cancelFlagPointer
, copyFlags
);
134 HeapFree( GetProcessHeap(), 0, sourceW
);
135 HeapFree( GetProcessHeap(), 0, destW
);
139 /**************************************************************************
140 * MoveFileTransactedA (KERNEL32.@)
142 BOOL WINAPI
MoveFileTransactedA(const char *source
, const char *dest
, LPPROGRESS_ROUTINE progress
, void *data
, DWORD flags
, HANDLE handle
)
144 FIXME("(%s, %s, %p, %p, %d, %p)\n", debugstr_a(source
), debugstr_a(dest
), progress
, data
, flags
, handle
);
145 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
149 /**************************************************************************
150 * MoveFileTransactedW (KERNEL32.@)
152 BOOL WINAPI
MoveFileTransactedW(const WCHAR
*source
, const WCHAR
*dest
, LPPROGRESS_ROUTINE progress
, void *data
, DWORD flags
, HANDLE handle
)
154 FIXME("(%s, %s, %p, %p, %d, %p)\n", debugstr_w(source
), debugstr_w(dest
), progress
, data
, flags
, handle
);
155 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
159 /**************************************************************************
160 * MoveFileWithProgressA (KERNEL32.@)
162 BOOL WINAPI
MoveFileWithProgressA( LPCSTR source
, LPCSTR dest
,
163 LPPROGRESS_ROUTINE fnProgress
,
164 LPVOID param
, DWORD flag
)
166 WCHAR
*sourceW
, *destW
;
169 if (!(sourceW
= FILE_name_AtoW( source
, FALSE
))) return FALSE
;
172 if (!(destW
= FILE_name_AtoW( dest
, TRUE
))) return FALSE
;
177 ret
= MoveFileWithProgressW( sourceW
, destW
, fnProgress
, param
, flag
);
178 HeapFree( GetProcessHeap(), 0, destW
);
182 /**************************************************************************
183 * MoveFileExA (KERNEL32.@)
185 BOOL WINAPI
MoveFileExA( LPCSTR source
, LPCSTR dest
, DWORD flag
)
187 return MoveFileWithProgressA( source
, dest
, NULL
, NULL
, flag
);
191 /**************************************************************************
192 * MoveFileW (KERNEL32.@)
194 * Move file or directory
196 BOOL WINAPI
MoveFileW( LPCWSTR source
, LPCWSTR dest
)
198 return MoveFileExW( source
, dest
, MOVEFILE_COPY_ALLOWED
);
202 /**************************************************************************
203 * MoveFileA (KERNEL32.@)
205 BOOL WINAPI
MoveFileA( LPCSTR source
, LPCSTR dest
)
207 return MoveFileExA( source
, dest
, MOVEFILE_COPY_ALLOWED
);
211 /***********************************************************************
212 * CreateDirectoryExA (KERNEL32.@)
214 BOOL WINAPI
CreateDirectoryExA( LPCSTR
template, LPCSTR path
, LPSECURITY_ATTRIBUTES sa
)
216 WCHAR
*pathW
, *templateW
= NULL
;
219 if (!(pathW
= FILE_name_AtoW( path
, FALSE
))) return FALSE
;
220 if (template && !(templateW
= FILE_name_AtoW( template, TRUE
))) return FALSE
;
222 ret
= CreateDirectoryExW( templateW
, pathW
, sa
);
223 HeapFree( GetProcessHeap(), 0, templateW
);
228 /***********************************************************************
229 * GetSystemDirectoryW (KERNEL32.@)
231 * See comment for GetWindowsDirectoryA.
233 UINT WINAPI
GetSystemDirectoryW( LPWSTR path
, UINT count
)
235 UINT len
= lstrlenW( DIR_System
) + 1;
236 if (path
&& count
>= len
)
238 lstrcpyW( path
, DIR_System
);
245 /***********************************************************************
246 * GetSystemDirectoryA (KERNEL32.@)
248 * See comment for GetWindowsDirectoryA.
250 UINT WINAPI
GetSystemDirectoryA( LPSTR path
, UINT count
)
252 return copy_filename_WtoA( DIR_System
, path
, count
);
256 /***********************************************************************
257 * Wow64EnableWow64FsRedirection (KERNEL32.@)
259 * Microsoft C++ Redistributable installers are depending on all %eax bits being set.
261 DWORD
/*BOOLEAN*/ WINAPI
KERNEL32_Wow64EnableWow64FsRedirection( BOOLEAN enable
)
263 return set_ntstatus( RtlWow64EnableFsRedirection( enable
));
267 /***********************************************************************
268 * wine_get_unix_file_name (KERNEL32.@) Not a Windows API
270 * Return the full Unix file name for a given path.
271 * Returned buffer must be freed by caller.
273 char * CDECL
wine_get_unix_file_name( LPCWSTR dosW
)
275 UNICODE_STRING nt_name
;
280 if (!RtlDosPathNameToNtPathName_U( dosW
, &nt_name
, NULL
, NULL
)) return NULL
;
283 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
)))
285 RtlFreeUnicodeString( &nt_name
);
288 status
= wine_nt_to_unix_file_name( &nt_name
, buffer
, &size
, FILE_OPEN_IF
);
289 if (status
!= STATUS_BUFFER_TOO_SMALL
) break;
290 HeapFree( GetProcessHeap(), 0, buffer
);
292 RtlFreeUnicodeString( &nt_name
);
293 if (status
&& status
!= STATUS_NO_SUCH_FILE
)
295 HeapFree( GetProcessHeap(), 0, buffer
);
296 SetLastError( RtlNtStatusToDosError( status
) );
303 /***********************************************************************
304 * wine_get_dos_file_name (KERNEL32.@) Not a Windows API
306 * Return the full DOS file name for a given Unix path.
307 * Returned buffer must be freed by caller.
309 WCHAR
* CDECL
wine_get_dos_file_name( LPCSTR str
)
311 UNICODE_STRING nt_name
;
314 SIZE_T len
= strlen(str
) + 1;
316 if (str
[0] != '/') /* relative path name */
318 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
319 MultiByteToWideChar( CP_UNIXCP
, 0, str
, len
, buffer
, len
);
320 status
= RtlDosPathNameToNtPathName_U_WithStatus( buffer
, &nt_name
, NULL
, NULL
);
321 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
322 if (!set_ntstatus( status
)) return NULL
;
323 buffer
= nt_name
.Buffer
;
324 len
= nt_name
.Length
/ sizeof(WCHAR
) + 1;
328 len
+= 8; /* \??\unix prefix */
329 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
330 if (!set_ntstatus( wine_unix_to_nt_file_name( str
, buffer
, &len
)))
332 HeapFree( GetProcessHeap(), 0, buffer
);
336 if (buffer
[5] == ':')
338 /* get rid of the \??\ prefix */
339 /* FIXME: should implement RtlNtPathNameToDosPathName and use that instead */
340 memmove( buffer
, buffer
+ 4, (len
- 4) * sizeof(WCHAR
) );
342 else buffer
[1] = '\\';
346 /*************************************************************************
347 * CreateSymbolicLinkA (KERNEL32.@)
349 BOOLEAN WINAPI
CreateSymbolicLinkA(LPCSTR link
, LPCSTR target
, DWORD flags
)
351 FIXME("(%s %s %d): stub\n", debugstr_a(link
), debugstr_a(target
), flags
);
355 /*************************************************************************
356 * CreateHardLinkTransactedA (KERNEL32.@)
358 BOOL WINAPI
CreateHardLinkTransactedA(LPCSTR link
, LPCSTR target
, LPSECURITY_ATTRIBUTES sa
, HANDLE transaction
)
360 FIXME("(%s %s %p %p): stub\n", debugstr_a(link
), debugstr_a(target
), sa
, transaction
);
361 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
365 /*************************************************************************
366 * CreateHardLinkTransactedW (KERNEL32.@)
368 BOOL WINAPI
CreateHardLinkTransactedW(LPCWSTR link
, LPCWSTR target
, LPSECURITY_ATTRIBUTES sa
, HANDLE transaction
)
370 FIXME("(%s %s %p %p): stub\n", debugstr_w(link
), debugstr_w(target
), sa
, transaction
);
371 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
375 /*************************************************************************
376 * CheckNameLegalDOS8Dot3A (KERNEL32.@)
378 BOOL WINAPI
CheckNameLegalDOS8Dot3A(const char *name
, char *oemname
, DWORD oemname_len
,
379 BOOL
*contains_spaces
, BOOL
*is_legal
)
383 TRACE("(%s %p %u %p %p)\n", name
, oemname
,
384 oemname_len
, contains_spaces
, is_legal
);
386 if (!name
|| !is_legal
)
389 if (!(nameW
= FILE_name_AtoW( name
, FALSE
))) return FALSE
;
391 return CheckNameLegalDOS8Dot3W( nameW
, oemname
, oemname_len
, contains_spaces
, is_legal
);
394 /*************************************************************************
395 * CheckNameLegalDOS8Dot3W (KERNEL32.@)
397 BOOL WINAPI
CheckNameLegalDOS8Dot3W(const WCHAR
*name
, char *oemname
, DWORD oemname_len
,
398 BOOL
*contains_spaces_ret
, BOOL
*is_legal
)
401 UNICODE_STRING nameW
;
402 BOOLEAN contains_spaces
;
404 TRACE("(%s %p %u %p %p)\n", wine_dbgstr_w(name
), oemname
,
405 oemname_len
, contains_spaces_ret
, is_legal
);
407 if (!name
|| !is_legal
)
410 RtlInitUnicodeString( &nameW
, name
);
413 oem_str
.Length
= oemname_len
;
414 oem_str
.MaximumLength
= oemname_len
;
415 oem_str
.Buffer
= oemname
;
418 *is_legal
= RtlIsNameLegalDOS8Dot3( &nameW
, oemname
? &oem_str
: NULL
, &contains_spaces
);
419 if (contains_spaces_ret
) *contains_spaces_ret
= contains_spaces
;
424 /*************************************************************************
425 * SetSearchPathMode (KERNEL32.@)
427 BOOL WINAPI
SetSearchPathMode( DWORD flags
)
429 return set_ntstatus( RtlSetSearchPathMode( flags
));