3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/file.c
6 * PURPOSE: Directory functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
12 /* INCLUDES *****************************************************************/
17 #include <kernel32/kernel32.h>
18 #include <kernel32/error.h>
21 #define FILE_RENAME_SIZE MAX_PATH +sizeof(FILE_RENAME_INFORMATION)
24 /* FUNCTIONS ****************************************************************/
32 LPCSTR lpExistingFileName,
36 return MoveFileExA (lpExistingFileName,
38 MOVEFILE_COPY_ALLOWED);
48 LPCSTR lpExistingFileName,
53 return MoveFileWithProgressA (lpExistingFileName,
66 MoveFileWithProgressA (
67 LPCSTR lpExistingFileName,
69 LPPROGRESS_ROUTINE lpProgressRoutine,
74 UNICODE_STRING ExistingFileNameU;
75 UNICODE_STRING NewFileNameU;
76 ANSI_STRING ExistingFileName;
77 ANSI_STRING NewFileName;
80 RtlInitAnsiString (&ExistingFileName,
81 (LPSTR)lpExistingFileName);
83 RtlInitAnsiString (&NewFileName,
84 (LPSTR)lpNewFileName);
86 /* convert ansi (or oem) string to unicode */
89 RtlAnsiStringToUnicodeString (&ExistingFileNameU,
92 RtlAnsiStringToUnicodeString (&NewFileNameU,
98 RtlOemStringToUnicodeString (&ExistingFileNameU,
101 RtlOemStringToUnicodeString (&NewFileNameU,
106 Result = MoveFileWithProgressW (ExistingFileNameU.Buffer,
112 RtlFreeHeap (RtlGetProcessHeap (),
114 ExistingFileNameU.Buffer);
115 RtlFreeHeap (RtlGetProcessHeap (),
117 NewFileNameU.Buffer);
129 LPCWSTR lpExistingFileName,
130 LPCWSTR lpNewFileName
133 return MoveFileExW (lpExistingFileName,
135 MOVEFILE_COPY_ALLOWED);
145 LPCWSTR lpExistingFileName,
146 LPCWSTR lpNewFileName,
150 return MoveFileWithProgressW (lpExistingFileName,
159 AdjustFileAttributes (
160 LPCWSTR ExistingFileName,
164 IO_STATUS_BLOCK IoStatusBlock;
165 FILE_BASIC_INFORMATION ExistingInfo,
170 WINBOOL Result = FALSE;
172 hFile = CreateFileW (ExistingFileName,
173 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
177 FILE_ATTRIBUTE_NORMAL,
179 if (INVALID_HANDLE_VALUE != hFile)
181 errCode = NtQueryInformationFile (hFile,
184 sizeof(FILE_BASIC_INFORMATION),
185 FileBasicInformation);
186 if (NT_SUCCESS (errCode))
188 if (0 != (ExistingInfo.FileAttributes & FILE_ATTRIBUTE_READONLY))
190 Attributes = ExistingInfo.FileAttributes;
191 ExistingInfo.FileAttributes &= ~ FILE_ATTRIBUTE_READONLY;
192 if (0 == (ExistingInfo.FileAttributes &
193 (FILE_ATTRIBUTE_HIDDEN |
194 FILE_ATTRIBUTE_SYSTEM |
195 FILE_ATTRIBUTE_ARCHIVE)))
197 ExistingInfo.FileAttributes |= FILE_ATTRIBUTE_NORMAL;
199 errCode = NtSetInformationFile (hFile,
202 sizeof(FILE_BASIC_INFORMATION),
203 FileBasicInformation);
204 if (!NT_SUCCESS(errCode))
206 DPRINT("Removing READONLY attribute from source failed with status 0x%08x\n", errCode);
208 ExistingInfo.FileAttributes = Attributes;
212 if (NT_SUCCESS(errCode))
214 hFile = CreateFileW (NewFileName,
215 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
219 FILE_ATTRIBUTE_NORMAL,
221 if (INVALID_HANDLE_VALUE != hFile)
223 errCode = NtQueryInformationFile(hFile,
226 sizeof(FILE_BASIC_INFORMATION),
227 FileBasicInformation);
228 if (NT_SUCCESS(errCode))
230 NewInfo.FileAttributes = (NewInfo.FileAttributes &
231 ~ (FILE_ATTRIBUTE_HIDDEN |
232 FILE_ATTRIBUTE_SYSTEM |
233 FILE_ATTRIBUTE_READONLY |
234 FILE_ATTRIBUTE_NORMAL)) |
235 (ExistingInfo.FileAttributes &
236 (FILE_ATTRIBUTE_HIDDEN |
237 FILE_ATTRIBUTE_SYSTEM |
238 FILE_ATTRIBUTE_READONLY |
239 FILE_ATTRIBUTE_NORMAL)) |
240 FILE_ATTRIBUTE_ARCHIVE;
241 NewInfo.CreationTime = ExistingInfo.CreationTime;
242 NewInfo.LastAccessTime = ExistingInfo.LastAccessTime;
243 NewInfo.LastWriteTime = ExistingInfo.LastWriteTime;
244 errCode = NtSetInformationFile (hFile,
247 sizeof(FILE_BASIC_INFORMATION),
248 FileBasicInformation);
249 if (NT_SUCCESS(errCode))
255 DPRINT("Setting attributes on dest file failed with status 0x%08x\n", errCode);
260 DPRINT("Obtaining attributes from dest file failed with status 0x%08x\n", errCode);
266 DPRINT("Opening dest file to set attributes failed with code %d\n", GetLastError());
272 DPRINT("Obtaining attributes from source file failed with status 0x%08x\n", errCode);
278 DPRINT("Opening source file to obtain attributes failed with code %d\n", GetLastError());
290 MoveFileWithProgressW (
291 LPCWSTR lpExistingFileName,
292 LPCWSTR lpNewFileName,
293 LPPROGRESS_ROUTINE lpProgressRoutine,
299 IO_STATUS_BLOCK IoStatusBlock;
300 FILE_RENAME_INFORMATION *FileRename;
301 USHORT Buffer[FILE_RENAME_SIZE];
306 hFile = CreateFileW (lpExistingFileName,
308 FILE_SHARE_WRITE|FILE_SHARE_READ,
311 FILE_ATTRIBUTE_NORMAL,
314 FileRename = (FILE_RENAME_INFORMATION *)Buffer;
315 if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == MOVEFILE_REPLACE_EXISTING)
316 FileRename->Replace = TRUE;
318 FileRename->Replace = FALSE;
320 FileRename->FileNameLength = wcslen (lpNewFileName);
321 memcpy (FileRename->FileName,
323 min(FileRename->FileNameLength, MAX_PATH));
325 errCode = NtSetInformationFile (hFile,
329 FileRenameInformation);
331 if (NT_SUCCESS(errCode))
335 /* FIXME file rename not yet implemented in all FSDs so it will always
336 * fail, even when the move is to the same device
339 else if (STATUS_NOT_SAME_DEVICE == errCode &&
340 MOVEFILE_COPY_ALLOWED == (dwFlags & MOVEFILE_COPY_ALLOWED))
345 Result = CopyFileExW (lpExistingFileName,
350 FileRename->Replace ? 0 : COPY_FILE_FAIL_IF_EXISTS) &&
351 AdjustFileAttributes(lpExistingFileName, lpNewFileName) &&
352 DeleteFileW (lpExistingFileName);
355 /* Delete of the existing file failed so the
356 * existing file is still there. Clean up the
357 * new file (if possible)
359 err = GetLastError();
360 if (! SetFileAttributesW (lpNewFileName, FILE_ATTRIBUTE_NORMAL))
362 DPRINT("Removing possible READONLY attrib from new file failed with code %d\n", GetLastError());
364 if (! DeleteFileW (lpNewFileName))
366 DPRINT("Deleting new file during cleanup failed with code %d\n", GetLastError());
371 /* See FIXME above */
375 SetLastErrorByStatus (errCode);