kernel32: Use wide-char string literals.
[wine.git] / dlls / kernel32 / path.c
blob8b4158b29d658b2c9098eae56e01ad0758b2cb35
1 /*
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
24 #include <errno.h>
25 #include <stdio.h>
26 #include <stdarg.h>
28 #include "winerror.h"
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "winternl.h"
36 #include "kernel_private.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(file);
41 #define MAX_PATHNAME_LEN 1024
43 /***********************************************************************
44 * copy_filename_WtoA
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 )
50 UNICODE_STRING strW;
51 DWORD ret;
52 BOOL is_ansi = AreFileApisANSI();
54 RtlInitUnicodeString( &strW, nameW );
56 ret = is_ansi ? RtlUnicodeStringToAnsiSize(&strW) : RtlUnicodeStringToOemSize(&strW);
57 if (buffer && ret <= len)
59 ANSI_STRING str;
61 str.Buffer = buffer;
62 str.MaximumLength = min( len, UNICODE_STRING_MAX_CHARS );
63 if (is_ansi)
64 RtlUnicodeStringToAnsiString( &str, &strW, FALSE );
65 else
66 RtlUnicodeStringToOemString( &str, &strW, FALSE );
67 ret = str.Length; /* length without terminating 0 */
69 return ret;
72 /***********************************************************************
73 * GetShortPathNameA (KERNEL32.@)
75 DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen )
77 WCHAR *longpathW;
78 WCHAR shortpathW[MAX_PATH];
79 DWORD ret;
81 TRACE("%s\n", debugstr_a(longpath));
83 if (!(longpathW = FILE_name_AtoW( longpath, FALSE ))) return 0;
85 ret = GetShortPathNameW(longpathW, shortpathW, MAX_PATH);
87 if (!ret) return 0;
88 if (ret > MAX_PATH)
90 SetLastError(ERROR_FILENAME_EXCED_RANGE);
91 return 0;
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;
103 BOOL ret;
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 );
111 return ret;
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;
123 BOOL ret;
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 );
130 return FALSE;
132 ret = CopyFileExW(sourceW, destW, progressRoutine, appData,
133 cancelFlagPointer, copyFlags);
134 HeapFree( GetProcessHeap(), 0, sourceW );
135 HeapFree( GetProcessHeap(), 0, destW );
136 return ret;
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);
146 return FALSE;
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);
156 return FALSE;
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;
167 BOOL ret;
169 if (!(sourceW = FILE_name_AtoW( source, FALSE ))) return FALSE;
170 if (dest)
172 if (!(destW = FILE_name_AtoW( dest, TRUE ))) return FALSE;
174 else
175 destW = NULL;
177 ret = MoveFileWithProgressW( sourceW, destW, fnProgress, param, flag );
178 HeapFree( GetProcessHeap(), 0, destW );
179 return ret;
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;
217 BOOL ret;
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 );
224 return ret;
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 );
239 len--;
241 return len;
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;
276 NTSTATUS status;
277 SIZE_T size = 256;
278 char *buffer;
280 if (!RtlDosPathNameToNtPathName_U( dosW, &nt_name, NULL, NULL )) return NULL;
281 for (;;)
283 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
285 RtlFreeUnicodeString( &nt_name );
286 return NULL;
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 ) );
297 return NULL;
299 return buffer;
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;
312 NTSTATUS status;
313 WCHAR *buffer;
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;
326 else
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 );
333 return NULL;
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] = '\\';
343 return buffer;
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);
352 return TRUE;
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);
362 return FALSE;
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);
372 return FALSE;
375 /*************************************************************************
376 * CheckNameLegalDOS8Dot3A (KERNEL32.@)
378 BOOL WINAPI CheckNameLegalDOS8Dot3A(const char *name, char *oemname, DWORD oemname_len,
379 BOOL *contains_spaces, BOOL *is_legal)
381 WCHAR *nameW;
383 TRACE("(%s %p %u %p %p)\n", name, oemname,
384 oemname_len, contains_spaces, is_legal);
386 if (!name || !is_legal)
387 return FALSE;
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)
400 OEM_STRING oem_str;
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)
408 return FALSE;
410 RtlInitUnicodeString( &nameW, name );
412 if (oemname) {
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;
421 return TRUE;
424 /*************************************************************************
425 * SetSearchPathMode (KERNEL32.@)
427 BOOL WINAPI SetSearchPathMode( DWORD flags )
429 return set_ntstatus( RtlSetSearchPathMode( flags ));