dbgeng: Update to IDebugControl4 stub.
[wine.git] / dlls / kernel32 / path.c
blob2dd3eac3c2611757d4ca125b0570ecdf393662f7
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, %ld, %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, %ld, %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 OBJECT_ATTRIBUTES attr;
279 NTSTATUS status;
280 ULONG size = 256;
281 char *buffer;
283 if (!RtlDosPathNameToNtPathName_U( dosW, &nt_name, NULL, NULL )) return NULL;
284 InitializeObjectAttributes( &attr, &nt_name, 0, 0, NULL );
285 for (;;)
287 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
289 RtlFreeUnicodeString( &nt_name );
290 return NULL;
292 status = wine_nt_to_unix_file_name( &attr, buffer, &size, FILE_OPEN_IF );
293 if (status != STATUS_BUFFER_TOO_SMALL) break;
294 HeapFree( GetProcessHeap(), 0, buffer );
296 RtlFreeUnicodeString( &nt_name );
297 if (status && status != STATUS_NO_SUCH_FILE)
299 HeapFree( GetProcessHeap(), 0, buffer );
300 SetLastError( RtlNtStatusToDosError( status ) );
301 return NULL;
303 return buffer;
307 /***********************************************************************
308 * wine_get_dos_file_name (KERNEL32.@) Not a Windows API
310 * Return the full DOS file name for a given Unix path.
311 * Returned buffer must be freed by caller.
313 WCHAR * CDECL wine_get_dos_file_name( LPCSTR str )
315 UNICODE_STRING nt_name;
316 NTSTATUS status;
317 WCHAR *buffer;
318 ULONG len = strlen(str) + 1;
320 if (str[0] != '/') /* relative path name */
322 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
323 MultiByteToWideChar( CP_UNIXCP, 0, str, len, buffer, len );
324 status = RtlDosPathNameToNtPathName_U_WithStatus( buffer, &nt_name, NULL, NULL );
325 RtlFreeHeap( GetProcessHeap(), 0, buffer );
326 if (!set_ntstatus( status )) return NULL;
327 buffer = nt_name.Buffer;
328 len = nt_name.Length / sizeof(WCHAR) + 1;
330 else
332 len += 8; /* \??\unix prefix */
333 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
334 if (!set_ntstatus( wine_unix_to_nt_file_name( str, buffer, &len )))
336 HeapFree( GetProcessHeap(), 0, buffer );
337 return NULL;
340 if (buffer[5] == ':')
342 /* get rid of the \??\ prefix */
343 /* FIXME: should implement RtlNtPathNameToDosPathName and use that instead */
344 memmove( buffer, buffer + 4, (len - 4) * sizeof(WCHAR) );
346 else buffer[1] = '\\';
347 return buffer;
350 /*************************************************************************
351 * CreateSymbolicLinkA (KERNEL32.@)
353 BOOLEAN WINAPI CreateSymbolicLinkA(LPCSTR link, LPCSTR target, DWORD flags)
355 FIXME("(%s %s %ld): stub\n", debugstr_a(link), debugstr_a(target), flags);
356 return TRUE;
359 /*************************************************************************
360 * CreateHardLinkTransactedA (KERNEL32.@)
362 BOOL WINAPI CreateHardLinkTransactedA(LPCSTR link, LPCSTR target, LPSECURITY_ATTRIBUTES sa, HANDLE transaction)
364 FIXME("(%s %s %p %p): stub\n", debugstr_a(link), debugstr_a(target), sa, transaction);
365 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
366 return FALSE;
369 /*************************************************************************
370 * CreateHardLinkTransactedW (KERNEL32.@)
372 BOOL WINAPI CreateHardLinkTransactedW(LPCWSTR link, LPCWSTR target, LPSECURITY_ATTRIBUTES sa, HANDLE transaction)
374 FIXME("(%s %s %p %p): stub\n", debugstr_w(link), debugstr_w(target), sa, transaction);
375 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
376 return FALSE;
379 /*************************************************************************
380 * CheckNameLegalDOS8Dot3A (KERNEL32.@)
382 BOOL WINAPI CheckNameLegalDOS8Dot3A(const char *name, char *oemname, DWORD oemname_len,
383 BOOL *contains_spaces, BOOL *is_legal)
385 WCHAR *nameW;
387 TRACE("(%s %p %lu %p %p)\n", name, oemname,
388 oemname_len, contains_spaces, is_legal);
390 if (!name || !is_legal)
391 return FALSE;
393 if (!(nameW = FILE_name_AtoW( name, FALSE ))) return FALSE;
395 return CheckNameLegalDOS8Dot3W( nameW, oemname, oemname_len, contains_spaces, is_legal );
398 /*************************************************************************
399 * CheckNameLegalDOS8Dot3W (KERNEL32.@)
401 BOOL WINAPI CheckNameLegalDOS8Dot3W(const WCHAR *name, char *oemname, DWORD oemname_len,
402 BOOL *contains_spaces_ret, BOOL *is_legal)
404 OEM_STRING oem_str;
405 UNICODE_STRING nameW;
406 BOOLEAN contains_spaces;
408 TRACE("(%s %p %lu %p %p)\n", wine_dbgstr_w(name), oemname,
409 oemname_len, contains_spaces_ret, is_legal);
411 if (!name || !is_legal)
412 return FALSE;
414 RtlInitUnicodeString( &nameW, name );
416 if (oemname) {
417 oem_str.Length = oemname_len;
418 oem_str.MaximumLength = oemname_len;
419 oem_str.Buffer = oemname;
422 *is_legal = RtlIsNameLegalDOS8Dot3( &nameW, oemname ? &oem_str : NULL, &contains_spaces );
423 if (contains_spaces_ret) *contains_spaces_ret = contains_spaces;
425 return TRUE;
428 /*************************************************************************
429 * SetSearchPathMode (KERNEL32.@)
431 BOOL WINAPI SetSearchPathMode( DWORD flags )
433 return set_ntstatus( RtlSetSearchPathMode( flags ));