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, %d, %p)\n", debugstr_a(source
), debugstr_a(dest
), progress
, data
, flags
, handle
);
147 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
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, %d, %p)\n", debugstr_w(source
), debugstr_w(dest
), progress
, data
, flags
, handle
);
157 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
161 /**************************************************************************
162 * MoveFileWithProgressA (KERNEL32.@)
164 BOOL WINAPI
MoveFileWithProgressA( LPCSTR source
, LPCSTR dest
,
165 LPPROGRESS_ROUTINE fnProgress
,
166 LPVOID param
, DWORD flag
)
168 WCHAR
*sourceW
, *destW
;
171 if (!(sourceW
= FILE_name_AtoW( source
, FALSE
))) return FALSE
;
174 if (!(destW
= FILE_name_AtoW( dest
, TRUE
))) return FALSE
;
179 ret
= MoveFileWithProgressW( sourceW
, destW
, fnProgress
, param
, flag
);
180 HeapFree( GetProcessHeap(), 0, destW
);
184 /**************************************************************************
185 * MoveFileExA (KERNEL32.@)
187 BOOL WINAPI
MoveFileExA( LPCSTR source
, LPCSTR dest
, DWORD flag
)
189 return MoveFileWithProgressA( source
, dest
, NULL
, NULL
, flag
);
193 /**************************************************************************
194 * MoveFileW (KERNEL32.@)
196 * Move file or directory
198 BOOL WINAPI
MoveFileW( LPCWSTR source
, LPCWSTR dest
)
200 return MoveFileExW( source
, dest
, MOVEFILE_COPY_ALLOWED
);
204 /**************************************************************************
205 * MoveFileA (KERNEL32.@)
207 BOOL WINAPI
MoveFileA( LPCSTR source
, LPCSTR dest
)
209 return MoveFileExA( source
, dest
, MOVEFILE_COPY_ALLOWED
);
213 /***********************************************************************
214 * CreateDirectoryExA (KERNEL32.@)
216 BOOL WINAPI
CreateDirectoryExA( LPCSTR
template, LPCSTR path
, LPSECURITY_ATTRIBUTES sa
)
218 WCHAR
*pathW
, *templateW
= NULL
;
221 if (!(pathW
= FILE_name_AtoW( path
, FALSE
))) return FALSE
;
222 if (template && !(templateW
= FILE_name_AtoW( template, TRUE
))) return FALSE
;
224 ret
= CreateDirectoryExW( templateW
, pathW
, sa
);
225 HeapFree( GetProcessHeap(), 0, templateW
);
230 /***********************************************************************
231 * GetSystemDirectoryW (KERNEL32.@)
233 * See comment for GetWindowsDirectoryA.
235 UINT WINAPI
GetSystemDirectoryW( LPWSTR path
, UINT count
)
237 UINT len
= ARRAY_SIZE(system_dir
);
238 if (path
&& count
>= len
)
240 lstrcpyW( path
, system_dir
);
247 /***********************************************************************
248 * GetSystemDirectoryA (KERNEL32.@)
250 * See comment for GetWindowsDirectoryA.
252 UINT WINAPI
GetSystemDirectoryA( LPSTR path
, UINT count
)
254 return copy_filename_WtoA( system_dir
, path
, count
);
258 /***********************************************************************
259 * Wow64EnableWow64FsRedirection (KERNEL32.@)
261 * Microsoft C++ Redistributable installers are depending on all %eax bits being set.
263 DWORD
/*BOOLEAN*/ WINAPI
KERNEL32_Wow64EnableWow64FsRedirection( BOOLEAN enable
)
265 return set_ntstatus( RtlWow64EnableFsRedirection( enable
));
269 /***********************************************************************
270 * wine_get_unix_file_name (KERNEL32.@) Not a Windows API
272 * Return the full Unix file name for a given path.
273 * Returned buffer must be freed by caller.
275 char * CDECL
wine_get_unix_file_name( LPCWSTR dosW
)
277 UNICODE_STRING nt_name
;
282 if (!RtlDosPathNameToNtPathName_U( dosW
, &nt_name
, NULL
, NULL
)) return NULL
;
285 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
)))
287 RtlFreeUnicodeString( &nt_name
);
290 status
= wine_nt_to_unix_file_name( &nt_name
, buffer
, &size
, FILE_OPEN_IF
);
291 if (status
!= STATUS_BUFFER_TOO_SMALL
) break;
292 HeapFree( GetProcessHeap(), 0, buffer
);
294 RtlFreeUnicodeString( &nt_name
);
295 if (status
&& status
!= STATUS_NO_SUCH_FILE
)
297 HeapFree( GetProcessHeap(), 0, buffer
);
298 SetLastError( RtlNtStatusToDosError( status
) );
305 /***********************************************************************
306 * wine_get_dos_file_name (KERNEL32.@) Not a Windows API
308 * Return the full DOS file name for a given Unix path.
309 * Returned buffer must be freed by caller.
311 WCHAR
* CDECL
wine_get_dos_file_name( LPCSTR str
)
313 UNICODE_STRING nt_name
;
316 SIZE_T len
= strlen(str
) + 1;
318 if (str
[0] != '/') /* relative path name */
320 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
321 MultiByteToWideChar( CP_UNIXCP
, 0, str
, len
, buffer
, len
);
322 status
= RtlDosPathNameToNtPathName_U_WithStatus( buffer
, &nt_name
, NULL
, NULL
);
323 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
324 if (!set_ntstatus( status
)) return NULL
;
325 buffer
= nt_name
.Buffer
;
326 len
= nt_name
.Length
/ sizeof(WCHAR
) + 1;
330 len
+= 8; /* \??\unix prefix */
331 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
332 if (!set_ntstatus( wine_unix_to_nt_file_name( str
, buffer
, &len
)))
334 HeapFree( GetProcessHeap(), 0, buffer
);
338 if (buffer
[5] == ':')
340 /* get rid of the \??\ prefix */
341 /* FIXME: should implement RtlNtPathNameToDosPathName and use that instead */
342 memmove( buffer
, buffer
+ 4, (len
- 4) * sizeof(WCHAR
) );
344 else buffer
[1] = '\\';
348 /*************************************************************************
349 * CreateSymbolicLinkA (KERNEL32.@)
351 BOOLEAN WINAPI
CreateSymbolicLinkA(LPCSTR link
, LPCSTR target
, DWORD flags
)
353 FIXME("(%s %s %d): stub\n", debugstr_a(link
), debugstr_a(target
), flags
);
357 /*************************************************************************
358 * CreateHardLinkTransactedA (KERNEL32.@)
360 BOOL WINAPI
CreateHardLinkTransactedA(LPCSTR link
, LPCSTR target
, LPSECURITY_ATTRIBUTES sa
, HANDLE transaction
)
362 FIXME("(%s %s %p %p): stub\n", debugstr_a(link
), debugstr_a(target
), sa
, transaction
);
363 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
367 /*************************************************************************
368 * CreateHardLinkTransactedW (KERNEL32.@)
370 BOOL WINAPI
CreateHardLinkTransactedW(LPCWSTR link
, LPCWSTR target
, LPSECURITY_ATTRIBUTES sa
, HANDLE transaction
)
372 FIXME("(%s %s %p %p): stub\n", debugstr_w(link
), debugstr_w(target
), sa
, transaction
);
373 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
377 /*************************************************************************
378 * CheckNameLegalDOS8Dot3A (KERNEL32.@)
380 BOOL WINAPI
CheckNameLegalDOS8Dot3A(const char *name
, char *oemname
, DWORD oemname_len
,
381 BOOL
*contains_spaces
, BOOL
*is_legal
)
385 TRACE("(%s %p %u %p %p)\n", name
, oemname
,
386 oemname_len
, contains_spaces
, is_legal
);
388 if (!name
|| !is_legal
)
391 if (!(nameW
= FILE_name_AtoW( name
, FALSE
))) return FALSE
;
393 return CheckNameLegalDOS8Dot3W( nameW
, oemname
, oemname_len
, contains_spaces
, is_legal
);
396 /*************************************************************************
397 * CheckNameLegalDOS8Dot3W (KERNEL32.@)
399 BOOL WINAPI
CheckNameLegalDOS8Dot3W(const WCHAR
*name
, char *oemname
, DWORD oemname_len
,
400 BOOL
*contains_spaces_ret
, BOOL
*is_legal
)
403 UNICODE_STRING nameW
;
404 BOOLEAN contains_spaces
;
406 TRACE("(%s %p %u %p %p)\n", wine_dbgstr_w(name
), oemname
,
407 oemname_len
, contains_spaces_ret
, is_legal
);
409 if (!name
|| !is_legal
)
412 RtlInitUnicodeString( &nameW
, name
);
415 oem_str
.Length
= oemname_len
;
416 oem_str
.MaximumLength
= oemname_len
;
417 oem_str
.Buffer
= oemname
;
420 *is_legal
= RtlIsNameLegalDOS8Dot3( &nameW
, oemname
? &oem_str
: NULL
, &contains_spaces
);
421 if (contains_spaces_ret
) *contains_spaces_ret
= contains_spaces
;
426 /*************************************************************************
427 * SetSearchPathMode (KERNEL32.@)
429 BOOL WINAPI
SetSearchPathMode( DWORD flags
)
431 return set_ntstatus( RtlSetSearchPathMode( flags
));