wow32: Use spec file imports.
[wine.git] / dlls / kernel32 / path.c
blobf4bdc08b87e00ce9483ffbca3b8cd0d13a784525
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) semi-stub\n", debugstr_a(source), debugstr_a(dest), progress, data, flags, handle);
148 return MoveFileWithProgressA(source, dest, progress, data, flags);
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) semi-stub\n", debugstr_w(source), debugstr_w(dest), progress, data, flags, handle);
158 return MoveFileWithProgressW(source, dest, progress, data, flags);
161 /*************************************************************************
162 * CreateFileTransactedA (KERNEL32.@)
164 HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileTransactedA( LPCSTR name, DWORD access, DWORD sharing,
165 LPSECURITY_ATTRIBUTES sa, DWORD creation,
166 DWORD attributes, HANDLE template,
167 HANDLE transaction, PUSHORT version,
168 PVOID param )
170 FIXME("(%s %lx %lx %p %lx %lx %p %p %p %p): semi-stub\n", debugstr_a(name), access, sharing, sa,
171 creation, attributes, template, transaction, version, param);
172 return CreateFileA(name, access, sharing, sa, creation, attributes, template);
175 /*************************************************************************
176 * CreateFileTransactedW (KERNEL32.@)
178 HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileTransactedW( LPCWSTR name, DWORD access, DWORD sharing,
179 LPSECURITY_ATTRIBUTES sa, DWORD creation,
180 DWORD attributes, HANDLE template, HANDLE transaction,
181 PUSHORT version, PVOID param )
183 FIXME("(%s %lx %lx %p %lx %lx %p %p %p %p): semi-stub\n", debugstr_w(name), access, sharing, sa,
184 creation, attributes, template, transaction, version, param);
185 return CreateFileW(name, access, sharing, sa, creation, attributes, template);
188 /***********************************************************************
189 * CreateDirectoryTransactedA (KERNEL32.@)
191 BOOL WINAPI DECLSPEC_HOTPATCH CreateDirectoryTransactedA(LPCSTR template, LPCSTR path, LPSECURITY_ATTRIBUTES sa, HANDLE transaction)
193 FIXME("(%s %s %p %p): semi-stub\n", debugstr_a(template), debugstr_a(path), sa, transaction);
194 return CreateDirectoryExA(template, path, sa);
197 /***********************************************************************
198 * CreateDirectoryTransactedW (KERNEL32.@)
200 BOOL WINAPI DECLSPEC_HOTPATCH CreateDirectoryTransactedW(LPCWSTR template, LPCWSTR path, LPSECURITY_ATTRIBUTES sa, HANDLE transaction)
202 FIXME("(%s %s %p %p): semi-stub\n", debugstr_w(template), debugstr_w(path), sa, transaction);
203 return CreateDirectoryExW(template, path, sa);
206 /***********************************************************************
207 * DeleteFileTransactedA (KERNEL32.@)
209 BOOL WINAPI DECLSPEC_HOTPATCH DeleteFileTransactedA(LPCSTR path, HANDLE transaction)
211 FIXME("(%s %p): semi-stub\n", debugstr_a(path), transaction);
212 return DeleteFileA(path);
215 /***********************************************************************
216 * DeleteFileTransactedW (KERNEL32.@)
218 BOOL WINAPI DECLSPEC_HOTPATCH DeleteFileTransactedW(LPCWSTR path, HANDLE transaction)
220 FIXME("(%s %p): semi-stub\n", debugstr_w(path), transaction);
221 return DeleteFileW(path);
224 /******************************************************************************
225 * FindFirstFileTransactedA (KERNEL32.@)
227 HANDLE WINAPI DECLSPEC_HOTPATCH FindFirstFileTransactedA( LPCSTR filename, FINDEX_INFO_LEVELS level,
228 LPVOID data, FINDEX_SEARCH_OPS search_op,
229 LPVOID filter, DWORD flags, HANDLE transaction )
231 FIXME("(%s %d %p %d %p %lx %p): semi-stub\n", debugstr_a(filename), level, data, search_op, filter, flags, transaction);
232 return FindFirstFileExA(filename, level, data, search_op, filter, flags);
235 /******************************************************************************
236 * FindFirstFileTransactedW (KERNEL32.@)
238 HANDLE WINAPI DECLSPEC_HOTPATCH FindFirstFileTransactedW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
239 LPVOID data, FINDEX_SEARCH_OPS search_op,
240 LPVOID filter, DWORD flags, HANDLE transaction )
242 FIXME("(%s %d %p %d %p %lx %p): semi-stub\n", debugstr_w(filename), level, data, search_op, filter, flags, transaction);
243 return FindFirstFileExW(filename, level, data, search_op, filter, flags);
247 /**************************************************************************
248 * GetFileAttributesTransactedA (KERNEL32.@)
250 DWORD WINAPI DECLSPEC_HOTPATCH GetFileAttributesTransactedA(LPCSTR name, GET_FILEEX_INFO_LEVELS level, void *ptr, HANDLE transaction)
252 FIXME("(%s %p): semi-stub\n", debugstr_a(name), transaction);
253 return GetFileAttributesExA(name, level, ptr);
256 /**************************************************************************
257 * GetFileAttributesTransactedW (KERNEL32.@)
259 DWORD WINAPI DECLSPEC_HOTPATCH GetFileAttributesTransactedW(LPCWSTR name, GET_FILEEX_INFO_LEVELS level, void *ptr, HANDLE transaction)
261 FIXME("(%s %p): semi-stub\n", debugstr_w(name), transaction);
262 return GetFileAttributesExW(name, level, ptr);
265 /***********************************************************************
266 * RemoveDirectoryTransactedA (KERNEL32.@)
268 BOOL WINAPI DECLSPEC_HOTPATCH RemoveDirectoryTransactedA(LPCSTR path, HANDLE transaction)
270 FIXME("(%s %p): semi-stub\n", debugstr_a(path), transaction);
271 return RemoveDirectoryA(path);
274 /***********************************************************************
275 * RemoveDirectoryTransactedW (KERNEL32.@)
277 BOOL WINAPI DECLSPEC_HOTPATCH RemoveDirectoryTransactedW(LPCWSTR path, HANDLE transaction)
279 FIXME("(%s %p): semi-stub\n", debugstr_w(path), transaction);
280 return RemoveDirectoryW(path);
283 /**************************************************************************
284 * MoveFileWithProgressA (KERNEL32.@)
286 BOOL WINAPI MoveFileWithProgressA( LPCSTR source, LPCSTR dest,
287 LPPROGRESS_ROUTINE fnProgress,
288 LPVOID param, DWORD flag )
290 WCHAR *sourceW, *destW;
291 BOOL ret;
293 if (!(sourceW = FILE_name_AtoW( source, FALSE ))) return FALSE;
294 if (dest)
296 if (!(destW = FILE_name_AtoW( dest, TRUE ))) return FALSE;
298 else
299 destW = NULL;
301 ret = MoveFileWithProgressW( sourceW, destW, fnProgress, param, flag );
302 HeapFree( GetProcessHeap(), 0, destW );
303 return ret;
306 /**************************************************************************
307 * MoveFileExA (KERNEL32.@)
309 BOOL WINAPI MoveFileExA( LPCSTR source, LPCSTR dest, DWORD flag )
311 return MoveFileWithProgressA( source, dest, NULL, NULL, flag );
315 /**************************************************************************
316 * MoveFileW (KERNEL32.@)
318 * Move file or directory
320 BOOL WINAPI MoveFileW( LPCWSTR source, LPCWSTR dest )
322 return MoveFileExW( source, dest, MOVEFILE_COPY_ALLOWED );
326 /**************************************************************************
327 * MoveFileA (KERNEL32.@)
329 BOOL WINAPI MoveFileA( LPCSTR source, LPCSTR dest )
331 return MoveFileExA( source, dest, MOVEFILE_COPY_ALLOWED );
335 /***********************************************************************
336 * CreateDirectoryExA (KERNEL32.@)
338 BOOL WINAPI CreateDirectoryExA( LPCSTR template, LPCSTR path, LPSECURITY_ATTRIBUTES sa )
340 WCHAR *pathW, *templateW = NULL;
341 BOOL ret;
343 if (!(pathW = FILE_name_AtoW( path, FALSE ))) return FALSE;
344 if (template && !(templateW = FILE_name_AtoW( template, TRUE ))) return FALSE;
346 ret = CreateDirectoryExW( templateW, pathW, sa );
347 HeapFree( GetProcessHeap(), 0, templateW );
348 return ret;
352 /***********************************************************************
353 * GetSystemDirectoryW (KERNEL32.@)
355 * See comment for GetWindowsDirectoryA.
357 UINT WINAPI GetSystemDirectoryW( LPWSTR path, UINT count )
359 UINT len = ARRAY_SIZE(system_dir);
360 if (path && count >= len)
362 lstrcpyW( path, system_dir );
363 len--;
365 return len;
369 /***********************************************************************
370 * GetSystemDirectoryA (KERNEL32.@)
372 * See comment for GetWindowsDirectoryA.
374 UINT WINAPI GetSystemDirectoryA( LPSTR path, UINT count )
376 return copy_filename_WtoA( system_dir, path, count );
380 /***********************************************************************
381 * wine_get_unix_file_name (KERNEL32.@) Not a Windows API
383 * Return the full Unix file name for a given path.
384 * Returned buffer must be freed by caller.
386 char * CDECL wine_get_unix_file_name( LPCWSTR dosW )
388 UNICODE_STRING nt_name;
389 OBJECT_ATTRIBUTES attr;
390 NTSTATUS status;
391 ULONG size = 256;
392 char *buffer;
394 if (!RtlDosPathNameToNtPathName_U( dosW, &nt_name, NULL, NULL )) return NULL;
395 InitializeObjectAttributes( &attr, &nt_name, 0, 0, NULL );
396 for (;;)
398 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
400 RtlFreeUnicodeString( &nt_name );
401 return NULL;
403 status = wine_nt_to_unix_file_name( &attr, buffer, &size, FILE_OPEN_IF );
404 if (status != STATUS_BUFFER_TOO_SMALL) break;
405 HeapFree( GetProcessHeap(), 0, buffer );
407 RtlFreeUnicodeString( &nt_name );
408 if (status && status != STATUS_NO_SUCH_FILE)
410 HeapFree( GetProcessHeap(), 0, buffer );
411 SetLastError( RtlNtStatusToDosError( status ) );
412 return NULL;
414 return buffer;
418 /***********************************************************************
419 * wine_get_dos_file_name (KERNEL32.@) Not a Windows API
421 * Return the full DOS file name for a given Unix path.
422 * Returned buffer must be freed by caller.
424 WCHAR * CDECL wine_get_dos_file_name( LPCSTR str )
426 UNICODE_STRING nt_name;
427 NTSTATUS status;
428 WCHAR *buffer;
429 ULONG len = strlen(str) + 1;
431 if (str[0] != '/') /* relative path name */
433 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
434 MultiByteToWideChar( CP_UNIXCP, 0, str, len, buffer, len );
435 status = RtlDosPathNameToNtPathName_U_WithStatus( buffer, &nt_name, NULL, NULL );
436 RtlFreeHeap( GetProcessHeap(), 0, buffer );
437 if (!set_ntstatus( status )) return NULL;
438 buffer = nt_name.Buffer;
439 len = nt_name.Length / sizeof(WCHAR) + 1;
441 else
443 len += 8; /* \??\unix prefix */
444 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
445 if (!set_ntstatus( wine_unix_to_nt_file_name( str, buffer, &len )))
447 HeapFree( GetProcessHeap(), 0, buffer );
448 return NULL;
451 if (buffer[5] == ':')
453 /* get rid of the \??\ prefix */
454 /* FIXME: should implement RtlNtPathNameToDosPathName and use that instead */
455 memmove( buffer, buffer + 4, (len - 4) * sizeof(WCHAR) );
457 else buffer[1] = '\\';
458 return buffer;
461 /*************************************************************************
462 * CreateSymbolicLinkA (KERNEL32.@)
464 BOOLEAN WINAPI CreateSymbolicLinkA(LPCSTR link, LPCSTR target, DWORD flags)
466 FIXME("(%s %s %ld): stub\n", debugstr_a(link), debugstr_a(target), flags);
467 return TRUE;
470 /*************************************************************************
471 * CreateHardLinkTransactedA (KERNEL32.@)
473 BOOL WINAPI CreateHardLinkTransactedA(LPCSTR link, LPCSTR target, LPSECURITY_ATTRIBUTES sa, HANDLE transaction)
475 FIXME("(%s %s %p %p): stub\n", debugstr_a(link), debugstr_a(target), sa, transaction);
476 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
477 return FALSE;
480 /*************************************************************************
481 * CreateHardLinkTransactedW (KERNEL32.@)
483 BOOL WINAPI CreateHardLinkTransactedW(LPCWSTR link, LPCWSTR target, LPSECURITY_ATTRIBUTES sa, HANDLE transaction)
485 FIXME("(%s %s %p %p): stub\n", debugstr_w(link), debugstr_w(target), sa, transaction);
486 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
487 return FALSE;
490 /*************************************************************************
491 * CheckNameLegalDOS8Dot3A (KERNEL32.@)
493 BOOL WINAPI CheckNameLegalDOS8Dot3A(const char *name, char *oemname, DWORD oemname_len,
494 BOOL *contains_spaces, BOOL *is_legal)
496 WCHAR *nameW;
498 TRACE("(%s %p %lu %p %p)\n", name, oemname,
499 oemname_len, contains_spaces, is_legal);
501 if (!name || !is_legal)
502 return FALSE;
504 if (!(nameW = FILE_name_AtoW( name, FALSE ))) return FALSE;
506 return CheckNameLegalDOS8Dot3W( nameW, oemname, oemname_len, contains_spaces, is_legal );
509 /*************************************************************************
510 * CheckNameLegalDOS8Dot3W (KERNEL32.@)
512 BOOL WINAPI CheckNameLegalDOS8Dot3W(const WCHAR *name, char *oemname, DWORD oemname_len,
513 BOOL *contains_spaces_ret, BOOL *is_legal)
515 OEM_STRING oem_str;
516 UNICODE_STRING nameW;
517 BOOLEAN contains_spaces;
519 TRACE("(%s %p %lu %p %p)\n", wine_dbgstr_w(name), oemname,
520 oemname_len, contains_spaces_ret, is_legal);
522 if (!name || !is_legal)
523 return FALSE;
525 RtlInitUnicodeString( &nameW, name );
527 if (oemname) {
528 oem_str.Length = oemname_len;
529 oem_str.MaximumLength = oemname_len;
530 oem_str.Buffer = oemname;
533 *is_legal = RtlIsNameLegalDOS8Dot3( &nameW, oemname ? &oem_str : NULL, &contains_spaces );
534 if (contains_spaces_ret) *contains_spaces_ret = contains_spaces;
536 return TRUE;
539 /*************************************************************************
540 * SetSearchPathMode (KERNEL32.@)
542 BOOL WINAPI SetSearchPathMode( DWORD flags )
544 return set_ntstatus( RtlSetSearchPathMode( flags ));