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 ****************************************************************/
29 LPCSTR lpExistingFileName,
33 return MoveFileExA (lpExistingFileName,
35 MOVEFILE_COPY_ALLOWED);
42 LPCSTR lpExistingFileName,
47 return MoveFileWithProgressA (lpExistingFileName,
57 MoveFileWithProgressA (
58 LPCSTR lpExistingFileName,
60 LPPROGRESS_ROUTINE lpProgressRoutine,
65 UNICODE_STRING ExistingFileNameU;
66 UNICODE_STRING NewFileNameU;
67 ANSI_STRING ExistingFileName;
68 ANSI_STRING NewFileName;
71 RtlInitAnsiString (&ExistingFileName,
72 (LPSTR)lpExistingFileName);
74 RtlInitAnsiString (&NewFileName,
75 (LPSTR)lpNewFileName);
77 /* convert ansi (or oem) string to unicode */
80 RtlAnsiStringToUnicodeString (&ExistingFileNameU,
83 RtlAnsiStringToUnicodeString (&NewFileNameU,
89 RtlOemStringToUnicodeString (&ExistingFileNameU,
92 RtlOemStringToUnicodeString (&NewFileNameU,
97 Result = MoveFileWithProgressW (ExistingFileNameU.Buffer,
103 RtlFreeHeap (RtlGetProcessHeap (),
105 ExistingFileNameU.Buffer);
106 RtlFreeHeap (RtlGetProcessHeap (),
108 NewFileNameU.Buffer);
117 LPCWSTR lpExistingFileName,
118 LPCWSTR lpNewFileName
121 return MoveFileExW (lpExistingFileName,
123 MOVEFILE_COPY_ALLOWED);
130 LPCWSTR lpExistingFileName,
131 LPCWSTR lpNewFileName,
135 return MoveFileWithProgressW (lpExistingFileName,
144 AdjustFileAttributes (
145 LPCWSTR ExistingFileName,
149 IO_STATUS_BLOCK IoStatusBlock;
150 FILE_BASIC_INFORMATION ExistingInfo,
155 WINBOOL Result = FALSE;
157 hFile = CreateFileW (ExistingFileName,
158 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
162 FILE_ATTRIBUTE_NORMAL,
164 if (INVALID_HANDLE_VALUE != hFile)
166 errCode = NtQueryInformationFile (hFile,
169 sizeof(FILE_BASIC_INFORMATION),
170 FileBasicInformation);
171 if (NT_SUCCESS (errCode))
173 if (0 != (ExistingInfo.FileAttributes & FILE_ATTRIBUTE_READONLY))
175 Attributes = ExistingInfo.FileAttributes;
176 ExistingInfo.FileAttributes &= ~ FILE_ATTRIBUTE_READONLY;
177 if (0 == (ExistingInfo.FileAttributes &
178 (FILE_ATTRIBUTE_HIDDEN |
179 FILE_ATTRIBUTE_SYSTEM |
180 FILE_ATTRIBUTE_ARCHIVE)))
182 ExistingInfo.FileAttributes |= FILE_ATTRIBUTE_NORMAL;
184 errCode = NtSetInformationFile (hFile,
187 sizeof(FILE_BASIC_INFORMATION),
188 FileBasicInformation);
189 if (!NT_SUCCESS(errCode))
191 DPRINT("Removing READONLY attribute from source failed with status 0x%08x\n", errCode);
193 ExistingInfo.FileAttributes = Attributes;
197 if (NT_SUCCESS(errCode))
199 hFile = CreateFileW (NewFileName,
200 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
204 FILE_ATTRIBUTE_NORMAL,
206 if (INVALID_HANDLE_VALUE != hFile)
208 errCode = NtQueryInformationFile(hFile,
211 sizeof(FILE_BASIC_INFORMATION),
212 FileBasicInformation);
213 if (NT_SUCCESS(errCode))
215 NewInfo.FileAttributes = (NewInfo.FileAttributes &
216 ~ (FILE_ATTRIBUTE_HIDDEN |
217 FILE_ATTRIBUTE_SYSTEM |
218 FILE_ATTRIBUTE_READONLY |
219 FILE_ATTRIBUTE_NORMAL)) |
220 (ExistingInfo.FileAttributes &
221 (FILE_ATTRIBUTE_HIDDEN |
222 FILE_ATTRIBUTE_SYSTEM |
223 FILE_ATTRIBUTE_READONLY |
224 FILE_ATTRIBUTE_NORMAL)) |
225 FILE_ATTRIBUTE_ARCHIVE;
226 NewInfo.CreationTime = ExistingInfo.CreationTime;
227 NewInfo.LastAccessTime = ExistingInfo.LastAccessTime;
228 NewInfo.LastWriteTime = ExistingInfo.LastWriteTime;
229 errCode = NtSetInformationFile (hFile,
232 sizeof(FILE_BASIC_INFORMATION),
233 FileBasicInformation);
234 if (NT_SUCCESS(errCode))
240 DPRINT("Setting attributes on dest file failed with status 0x%08x\n", errCode);
245 DPRINT("Obtaining attributes from dest file failed with status 0x%08x\n", errCode);
251 DPRINT("Opening dest file to set attributes failed with code %d\n", GetLastError());
257 DPRINT("Obtaining attributes from source file failed with status 0x%08x\n", errCode);
263 DPRINT("Opening source file to obtain attributes failed with code %d\n", GetLastError());
272 MoveFileWithProgressW (
273 LPCWSTR lpExistingFileName,
274 LPCWSTR lpNewFileName,
275 LPPROGRESS_ROUTINE lpProgressRoutine,
281 IO_STATUS_BLOCK IoStatusBlock;
282 FILE_RENAME_INFORMATION *FileRename;
283 USHORT Buffer[FILE_RENAME_SIZE];
288 hFile = CreateFileW (lpExistingFileName,
290 FILE_SHARE_WRITE|FILE_SHARE_READ,
293 FILE_ATTRIBUTE_NORMAL,
296 FileRename = (FILE_RENAME_INFORMATION *)Buffer;
297 if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == MOVEFILE_REPLACE_EXISTING)
298 FileRename->Replace = TRUE;
300 FileRename->Replace = FALSE;
302 FileRename->FileNameLength = wcslen (lpNewFileName);
303 memcpy (FileRename->FileName,
305 min(FileRename->FileNameLength, MAX_PATH));
307 errCode = NtSetInformationFile (hFile,
311 FileRenameInformation);
313 if (NT_SUCCESS(errCode))
317 /* FIXME file rename not yet implemented in all FSDs so it will always
318 * fail, even when the move is to the same device
321 else if (STATUS_NOT_SAME_DEVICE == errCode &&
322 MOVEFILE_COPY_ALLOWED == (dwFlags & MOVEFILE_COPY_ALLOWED))
327 Result = CopyFileExW (lpExistingFileName,
332 FileRename->Replace ? 0 : COPY_FILE_FAIL_IF_EXISTS) &&
333 AdjustFileAttributes(lpExistingFileName, lpNewFileName) &&
334 DeleteFileW (lpExistingFileName);
337 /* Delete of the existing file failed so the
338 * existing file is still there. Clean up the
339 * new file (if possible)
341 err = GetLastError();
342 if (! SetFileAttributesW (lpNewFileName, FILE_ATTRIBUTE_NORMAL))
344 DPRINT("Removing possible READONLY attrib from new file failed with code %d\n", GetLastError());
346 if (! DeleteFileW (lpNewFileName))
348 DPRINT("Deleting new file during cleanup failed with code %d\n", GetLastError());
353 /* See FIXME above */
357 SetLastErrorByStatus (errCode);