mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 23:02:59 +00:00
[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:
parent
25d5ac32b6
commit
7b19834435
1 changed files with 189 additions and 77 deletions
|
@ -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 */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue