[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).

svn path=/trunk/; revision=56650
This commit is contained in:
Alex Ionescu 2012-05-23 16:51:22 +00:00
parent 25d5ac32b6
commit 7b19834435

View file

@ -14,7 +14,6 @@
#include <k32.h> #include <k32.h>
#define NDEBUG #define NDEBUG
#include <reactos/debug.h> #include <reactos/debug.h>
DEBUG_CHANNEL(kernel32file);
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
@ -23,101 +22,214 @@ DEBUG_CHANNEL(kernel32file);
*/ */
BOOL BOOL
WINAPI WINAPI
DeleteFileA ( DeleteFileA(IN LPCSTR lpFileName)
LPCSTR lpFileName
)
{ {
PWCHAR FileNameW; PUNICODE_STRING FileName;
if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) /* Convert the string to unicode, and call the wide function */
return FALSE; FileName = Basep8BitStringToStaticUnicodeString(lpFileName);
if (FileName) return DeleteFileW(FileName->Buffer);
return DeleteFileW (FileNameW); return FALSE;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
DeleteFileW ( DeleteFileW(IN LPCWSTR lpFileName)
LPCWSTR lpFileName
)
{ {
FILE_DISPOSITION_INFORMATION FileDispInfo; FILE_DISPOSITION_INFORMATION FileDispInfo;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING NtPathU; UNICODE_STRING NtPathU;
HANDLE FileHandle; HANDLE FileHandle;
NTSTATUS Status; NTSTATUS Status;
RTL_RELATIVE_NAME_U RelativeName;
PWCHAR PathBuffer;
FILE_ATTRIBUTE_TAG_INFORMATION FileTagInformation;
TRACE("DeleteFileW (lpFileName %S)\n",lpFileName); /* 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;
}
if (!RtlDosPathNameToNtPathName_U (lpFileName, /* Save the path buffer in case we free it later */
&NtPathU, PathBuffer = NtPathU.Buffer;
NULL,
NULL))
{
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
TRACE("NtPathU \'%wZ\'\n", &NtPathU); /* 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;
}
InitializeObjectAttributes(&ObjectAttributes, /* Now open the directory name that was passed in */
&NtPathU, InitializeObjectAttributes(&ObjectAttributes,
OBJ_CASE_INSENSITIVE, &NtPathU,
NULL, OBJ_CASE_INSENSITIVE,
NULL); 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);
}
Status = NtCreateFile (&FileHandle, if (!NT_SUCCESS(Status))
DELETE, {
&ObjectAttributes, RtlReleaseRelativeName(&RelativeName);
&IoStatusBlock, RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
NULL, BaseSetLastNTError(Status);
FILE_ATTRIBUTE_NORMAL, return FALSE;
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, }
FILE_OPEN, }
FILE_NON_DIRECTORY_FILE, }
NULL, else if (!(NT_SUCCESS(Status)) &&
0); (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;
}
RtlFreeHeap(RtlGetProcessHeap(), /* Let's try again, without querying attributes */
0, Status = NtOpenFile(&FileHandle,
NtPathU.Buffer); 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;
}
}
}
if (!NT_SUCCESS(Status)) /* Ready to delete the file, so cleanup temporary data */
{ RtlReleaseRelativeName(&RelativeName);
WARN("Status 0x%08x\n", Status); RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
BaseSetLastNTError (Status);
return FALSE;
}
FileDispInfo.DeleteFile = TRUE; /* 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;
}
Status = NtSetInformationFile (FileHandle, /* Tell the caller deletion worked */
&IoStatusBlock, return TRUE;
&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;
} }
/* EOF */ /* EOF */