Author: ion Date: Wed May 23 16:51:22 2012 New Revision: 56650
URL: http://svn.reactos.org/svn/reactos?rev=56650&view=rev Log: [KERNEL32]: Reimplement DeleteFileA and W to handle the new ansi-Unicode functions, as well as to handle the same cases that Pierre implemented in the directory functions (dealing with reparse points and tags).
Modified: trunk/reactos/dll/win32/kernel32/client/file/delete.c
Modified: trunk/reactos/dll/win32/kernel32/client/file/delete.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/f... ============================================================================== --- trunk/reactos/dll/win32/kernel32/client/file/delete.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/client/file/delete.c [iso-8859-1] Wed May 23 16:51:22 2012 @@ -14,7 +14,6 @@ #include <k32.h> #define NDEBUG #include <reactos/debug.h> -DEBUG_CHANNEL(kernel32file);
/* FUNCTIONS ****************************************************************/
@@ -23,101 +22,214 @@ */ BOOL WINAPI -DeleteFileA ( - LPCSTR lpFileName - ) +DeleteFileA(IN LPCSTR lpFileName) { - PWCHAR FileNameW; - - if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) - return FALSE; - - return DeleteFileW (FileNameW); + PUNICODE_STRING FileName; + + /* Convert the string to unicode, and call the wide function */ + FileName = Basep8BitStringToStaticUnicodeString(lpFileName); + if (FileName) return DeleteFileW(FileName->Buffer); + return FALSE; } -
/* * @implemented */ BOOL WINAPI -DeleteFileW ( - LPCWSTR lpFileName - ) +DeleteFileW(IN LPCWSTR lpFileName) { - FILE_DISPOSITION_INFORMATION FileDispInfo; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING NtPathU; - HANDLE FileHandle; - NTSTATUS Status; - - TRACE("DeleteFileW (lpFileName %S)\n",lpFileName); - - if (!RtlDosPathNameToNtPathName_U (lpFileName, - &NtPathU, - NULL, - NULL)) - { - SetLastError(ERROR_PATH_NOT_FOUND); - return FALSE; - } - - TRACE("NtPathU '%wZ'\n", &NtPathU); - - InitializeObjectAttributes(&ObjectAttributes, - &NtPathU, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtCreateFile (&FileHandle, - DELETE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, - FILE_NON_DIRECTORY_FILE, - NULL, - 0); - - RtlFreeHeap(RtlGetProcessHeap(), - 0, - NtPathU.Buffer); - - if (!NT_SUCCESS(Status)) - { - WARN("Status 0x%08x\n", Status); - BaseSetLastNTError (Status); - return FALSE; - } - - FileDispInfo.DeleteFile = TRUE; - - Status = NtSetInformationFile (FileHandle, - &IoStatusBlock, - &FileDispInfo, - sizeof(FILE_DISPOSITION_INFORMATION), - FileDispositionInformation); - if (!NT_SUCCESS(Status)) - { - WARN("Status 0x%08x\n", Status); - NtClose (FileHandle); - BaseSetLastNTError (Status); - return FALSE; - } - - Status = NtClose (FileHandle); - if (!NT_SUCCESS (Status)) - { - WARN("Status 0x%08x\n", Status); - BaseSetLastNTError (Status); - return FALSE; - } - - return TRUE; + FILE_DISPOSITION_INFORMATION FileDispInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE FileHandle; + NTSTATUS Status; + RTL_RELATIVE_NAME_U RelativeName; + PWCHAR PathBuffer; + FILE_ATTRIBUTE_TAG_INFORMATION FileTagInformation; + + /* Convert to NT path and get the relative name too */ + if (!RtlDosPathNameToNtPathName_U(lpFileName, + &NtPathU, + NULL, + &RelativeName)) + { + /* Bail out if the path name makes no sense */ + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + /* Save the path buffer in case we free it later */ + PathBuffer = NtPathU.Buffer; + + /* If we have a relative name... */ + if (RelativeName.RelativeName.Length) + { + /* Do a relative open with only the relative path set */ + NtPathU = RelativeName.RelativeName; + } + else + { + /* Do a full path open with no containing directory */ + RelativeName.ContainingDirectory = NULL; + } + + /* Now open the directory name that was passed in */ + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + RelativeName.ContainingDirectory, + NULL); + Status = NtOpenFile(&FileHandle, + DELETE | FILE_READ_ATTRIBUTES, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_NON_DIRECTORY_FILE | + FILE_OPEN_FOR_BACKUP_INTENT | + FILE_OPEN_REPARSE_POINT); + if (NT_SUCCESS(Status)) + { + /* Check if there's a reparse point associated with this file handle */ + Status = NtQueryInformationFile(FileHandle, + &IoStatusBlock, + &FileTagInformation, + sizeof(FileTagInformation), + FileAttributeTagInformation); + if ((NT_SUCCESS(Status)) && + (FileTagInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && + (FileTagInformation.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)) + { + /* There is, so now try to open it with reparse behavior */ + NtClose(FileHandle); + Status = NtOpenFile(&FileHandle, + DELETE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_DELETE | + FILE_SHARE_READ | + FILE_SHARE_WRITE, + FILE_NON_DIRECTORY_FILE | + FILE_OPEN_FOR_BACKUP_INTENT); + if (!NT_SUCCESS(Status)) + { + /* We failed -- maybe whoever is handling this tag isn't there */ + if (Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED) + { + /* Try to open it for delete, without reparse behavior */ + Status = NtOpenFile(&FileHandle, + DELETE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | + FILE_SHARE_WRITE | + FILE_SHARE_DELETE, + FILE_NON_DIRECTORY_FILE | + FILE_OPEN_FOR_BACKUP_INTENT | + FILE_OPEN_REPARSE_POINT); + } + + if (!NT_SUCCESS(Status)) + { + RtlReleaseRelativeName(&RelativeName); + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + BaseSetLastNTError(Status); + return FALSE; + } + } + } + else if (!(NT_SUCCESS(Status)) && + (Status != STATUS_NOT_IMPLEMENTED) && + (Status != STATUS_INVALID_PARAMETER)) + { + /* We had some critical error querying the attributes, bail out */ + RtlReleaseRelativeName(&RelativeName); + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + NtClose(FileHandle); + BaseSetLastNTError(Status); + return FALSE; + } + } + else + { + /* It's possible that FILE_OPEN_REPARSE_POINT was not understood */ + if (Status == STATUS_INVALID_PARAMETER) + { + /* Try opening the file normally, with reparse behavior */ + Status = NtOpenFile(&FileHandle, + DELETE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_DELETE | + FILE_SHARE_READ | + FILE_SHARE_WRITE, + FILE_NON_DIRECTORY_FILE | + FILE_OPEN_FOR_BACKUP_INTENT); + if (!NT_SUCCESS(Status)) + { + /* This failed too, fail */ + RtlReleaseRelativeName(&RelativeName); + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + BaseSetLastNTError(Status); + return FALSE; + } + } + else + { + /* Maybe we didn't have READ_ATTRIBUTE rights? */ + if (Status != STATUS_ACCESS_DENIED) + { + /* Nope, it was something else, let's fail */ + RtlReleaseRelativeName(&RelativeName); + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + BaseSetLastNTError(Status); + return FALSE; + } + + /* Let's try again, without querying attributes */ + Status = NtOpenFile(&FileHandle, + DELETE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_DELETE | + FILE_SHARE_READ | + FILE_SHARE_WRITE, + FILE_NON_DIRECTORY_FILE | + FILE_OPEN_FOR_BACKUP_INTENT | + FILE_OPEN_REPARSE_POINT); + if (!NT_SUCCESS(Status)) + { + /* This failed too, so bail out */ + RtlReleaseRelativeName(&RelativeName); + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + BaseSetLastNTError(Status); + return FALSE; + } + } + } + + /* Ready to delete the file, so cleanup temporary data */ + RtlReleaseRelativeName(&RelativeName); + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + + /* Ask for the file to be deleted */ + FileDispInfo.DeleteFile = TRUE; + Status = NtSetInformationFile(FileHandle, + &IoStatusBlock, + &FileDispInfo, + sizeof(FILE_DISPOSITION_INFORMATION), + FileDispositionInformation); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + /* Deletion failed, tell the caller */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Tell the caller deletion worked */ + return TRUE; }
/* EOF */