widl: Generate helper macros for WinRT implementation.
[wine/zf.git] / dlls / kernel32 / path.c
blob023dff826d60321db3a2281c4afce472dbefcefd
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 static const WCHAR system_dir[] = L"C:\\windows\\system32";
45 /***********************************************************************
46 * copy_filename_WtoA
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 )
52 UNICODE_STRING strW;
53 DWORD ret;
54 BOOL is_ansi = AreFileApisANSI();
56 RtlInitUnicodeString( &strW, nameW );
58 ret = is_ansi ? RtlUnicodeStringToAnsiSize(&strW) : RtlUnicodeStringToOemSize(&strW);
59 if (buffer && ret <= len)
61 ANSI_STRING str;
63 str.Buffer = buffer;
64 str.MaximumLength = min( len, UNICODE_STRING_MAX_CHARS );
65 if (is_ansi)
66 RtlUnicodeStringToAnsiString( &str, &strW, FALSE );
67 else
68 RtlUnicodeStringToOemString( &str, &strW, FALSE );
69 ret = str.Length; /* length without terminating 0 */
71 return ret;
74 /***********************************************************************
75 * GetShortPathNameA (KERNEL32.@)
77 DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen )
79 WCHAR *longpathW;
80 WCHAR shortpathW[MAX_PATH];
81 DWORD ret;
83 TRACE("%s\n", debugstr_a(longpath));
85 if (!(longpathW = FILE_name_AtoW( longpath, FALSE ))) return 0;
87 ret = GetShortPathNameW(longpathW, shortpathW, MAX_PATH);
89 if (!ret) return 0;
90 if (ret > MAX_PATH)
92 SetLastError(ERROR_FILENAME_EXCED_RANGE);
93 return 0;
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;
105 BOOL ret;
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 );
113 return ret;
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;
125 BOOL ret;
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 );
132 return FALSE;
134 ret = CopyFileExW(sourceW, destW, progressRoutine, appData,
135 cancelFlagPointer, copyFlags);
136 HeapFree( GetProcessHeap(), 0, sourceW );
137 HeapFree( GetProcessHeap(), 0, destW );
138 return ret;
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);
148 return FALSE;
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);
158 return FALSE;
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;
169 BOOL ret;
171 if (!(sourceW = FILE_name_AtoW( source, FALSE ))) return FALSE;
172 if (dest)
174 if (!(destW = FILE_name_AtoW( dest, TRUE ))) return FALSE;
176 else
177 destW = NULL;
179 ret = MoveFileWithProgressW( sourceW, destW, fnProgress, param, flag );
180 HeapFree( GetProcessHeap(), 0, destW );
181 return ret;
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;
219 BOOL ret;
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 );
226 return ret;
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 );
241 len--;
243 return len;
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;
278 NTSTATUS status;
279 SIZE_T size = 256;
280 char *buffer;
282 if (!RtlDosPathNameToNtPathName_U( dosW, &nt_name, NULL, NULL )) return NULL;
283 for (;;)
285 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
287 RtlFreeUnicodeString( &nt_name );
288 return NULL;
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 ) );
299 return NULL;
301 return buffer;
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;
314 NTSTATUS status;
315 WCHAR *buffer;
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;
328 else
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 );
335 return NULL;
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] = '\\';
345 return buffer;
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);
354 return TRUE;
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);
364 return FALSE;
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);
374 return FALSE;
377 /*************************************************************************
378 * CheckNameLegalDOS8Dot3A (KERNEL32.@)
380 BOOL WINAPI CheckNameLegalDOS8Dot3A(const char *name, char *oemname, DWORD oemname_len,
381 BOOL *contains_spaces, BOOL *is_legal)
383 WCHAR *nameW;
385 TRACE("(%s %p %u %p %p)\n", name, oemname,
386 oemname_len, contains_spaces, is_legal);
388 if (!name || !is_legal)
389 return FALSE;
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)
402 OEM_STRING oem_str;
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)
410 return FALSE;
412 RtlInitUnicodeString( &nameW, name );
414 if (oemname) {
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;
423 return TRUE;
426 /*************************************************************************
427 * SetSearchPathMode (KERNEL32.@)
429 BOOL WINAPI SetSearchPathMode( DWORD flags )
431 return set_ntstatus( RtlSetSearchPathMode( flags ));