mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[KERNEL32]
Simplify overcomplicated function CreateHardlinkW(), and SEHify it. svn path=/trunk/; revision=53823
This commit is contained in:
parent
2c440bd22d
commit
acee43d271
1 changed files with 108 additions and 162 deletions
|
@ -2,11 +2,10 @@
|
|||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/file/hardlink.c
|
||||
* FILE: dll/win32/kernel32/client/file/hardlink.c
|
||||
* PURPOSE: Hardlink functions
|
||||
* PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
|
||||
* UPDATE HISTORY:
|
||||
* Created 13/03/2004
|
||||
* Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -27,170 +26,111 @@ CreateHardLinkW(LPCWSTR lpFileName,
|
|||
LPCWSTR lpExistingFileName,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
||||
{
|
||||
UNICODE_STRING LinkTarget, LinkName;
|
||||
LPVOID lpSecurityDescriptor;
|
||||
PFILE_LINK_INFORMATION LinkInformation;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
NTSTATUS Status;
|
||||
BOOL Ret = FALSE;
|
||||
NTSTATUS Status;
|
||||
BOOL Ret = FALSE;
|
||||
ULONG NeededSize;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE hTarget = INVALID_HANDLE_VALUE;
|
||||
PFILE_LINK_INFORMATION LinkInformation = NULL;
|
||||
UNICODE_STRING LinkTarget = {0, 0, NULL}, LinkName = {0, 0, NULL};
|
||||
|
||||
if(!lpFileName || !lpExistingFileName)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
TRACE("CreateHardLinkW: %S, %S, %p\n", lpFileName, lpExistingFileName, lpSecurityAttributes);
|
||||
|
||||
lpSecurityDescriptor = (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL);
|
||||
|
||||
if(RtlDetermineDosPathNameType_U((LPWSTR)lpFileName) == 1 ||
|
||||
RtlDetermineDosPathNameType_U((LPWSTR)lpExistingFileName) == 1)
|
||||
{
|
||||
WARN("CreateHardLinkW() cannot handle UNC Paths!\n");
|
||||
SetLastError(ERROR_INVALID_NAME);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(RtlDosPathNameToNtPathName_U(lpExistingFileName, &LinkTarget, NULL, NULL))
|
||||
{
|
||||
ULONG NeededSize = RtlGetFullPathName_U((LPWSTR)lpExistingFileName, 0, NULL, NULL);
|
||||
if(NeededSize > 0)
|
||||
/* Validate parameters */
|
||||
if(!lpFileName || !lpExistingFileName)
|
||||
{
|
||||
LPWSTR lpNtLinkTarget = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize * sizeof(WCHAR));
|
||||
if(lpNtLinkTarget != NULL)
|
||||
{
|
||||
LPWSTR lpFilePart;
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(RtlGetFullPathName_U((LPWSTR)lpExistingFileName, NeededSize, lpNtLinkTarget, &lpFilePart) &&
|
||||
(*lpNtLinkTarget) != L'\0')
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Get target UNC path */
|
||||
if (!RtlDosPathNameToNtPathName_U(lpExistingFileName, &LinkTarget, NULL, NULL))
|
||||
{
|
||||
UNICODE_STRING CheckDrive, LinkDrive;
|
||||
WCHAR wCheckDrive[10];
|
||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
swprintf(wCheckDrive, L"\\??\\%c:", (WCHAR)(*lpNtLinkTarget));
|
||||
RtlInitUnicodeString(&CheckDrive, wCheckDrive);
|
||||
/* Open target */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&LinkTarget,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
(lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
|
||||
|
||||
RtlZeroMemory(&LinkDrive, sizeof(UNICODE_STRING));
|
||||
Status = NtOpenFile(&hTarget,
|
||||
SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
|
||||
&ObjectAttributes,
|
||||
&IoStatusBlock,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
LinkDrive.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (MAX_PATH + 1) * sizeof(WCHAR));
|
||||
if(LinkDrive.Buffer != NULL)
|
||||
{
|
||||
HANDLE hFile, hTarget;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
/* Get UNC path name for link */
|
||||
if (!RtlDosPathNameToNtPathName_U(lpFileName, &LinkName, NULL, NULL))
|
||||
{
|
||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&CheckDrive,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
Status = NtOpenSymbolicLinkObject(&hFile, 1, &ObjectAttributes);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
UNICODE_STRING LanManager;
|
||||
|
||||
RtlInitUnicodeString(&LanManager, L"\\Device\\LanmanRedirector\\");
|
||||
|
||||
NtQuerySymbolicLinkObject(hFile, &LinkDrive, NULL);
|
||||
|
||||
if(!RtlPrefixUnicodeString(&LanManager, &LinkDrive, TRUE))
|
||||
{
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&LinkTarget,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
lpSecurityDescriptor);
|
||||
Status = NtOpenFile(&hTarget,
|
||||
SYNCHRONIZE | DELETE,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
if(RtlDosPathNameToNtPathName_U(lpFileName, &LinkName, NULL, NULL))
|
||||
{
|
||||
NeededSize = sizeof(FILE_LINK_INFORMATION) + LinkName.Length + sizeof(WCHAR);
|
||||
LinkInformation = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize);
|
||||
if(LinkInformation != NULL)
|
||||
{
|
||||
LinkInformation->ReplaceIfExists = FALSE;
|
||||
LinkInformation->RootDirectory = 0;
|
||||
LinkInformation->FileNameLength = LinkName.Length;
|
||||
RtlCopyMemory(LinkInformation->FileName, LinkName.Buffer, LinkName.Length);
|
||||
|
||||
Status = NtSetInformationFile(hTarget, &IoStatus, LinkInformation, NeededSize, FileLinkInformation);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
Ret = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
}
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, LinkInformation);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||
}
|
||||
NtClose(hTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Unable to open link destination \"%wZ\"!\n", &LinkTarget);
|
||||
BaseSetLastNTError(Status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Path \"%wZ\" must not be a mapped drive!\n", &LinkDrive);
|
||||
SetLastError(ERROR_INVALID_NAME);
|
||||
}
|
||||
|
||||
NtClose(hFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Prepare data for link */
|
||||
NeededSize = sizeof(FILE_LINK_INFORMATION) + LinkName.Length;
|
||||
LinkInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, NeededSize);
|
||||
if (!LinkInformation)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
else
|
||||
|
||||
RtlMoveMemory(LinkInformation->FileName, LinkName.Buffer, LinkName.Length);
|
||||
LinkInformation->ReplaceIfExists = FALSE;
|
||||
LinkInformation->RootDirectory = 0;
|
||||
LinkInformation->FileNameLength = LinkName.Length;
|
||||
|
||||
/* Create hard link */
|
||||
Status = NtSetInformationFile(hTarget,
|
||||
&IoStatusBlock,
|
||||
LinkInformation,
|
||||
NeededSize,
|
||||
FileLinkInformation);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_NAME);
|
||||
Ret = TRUE;
|
||||
}
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
}
|
||||
else
|
||||
_SEH2_FINALLY
|
||||
{
|
||||
SetLastError(ERROR_INVALID_NAME);
|
||||
if (LinkTarget.Buffer)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, LinkTarget.Buffer);
|
||||
}
|
||||
|
||||
if (hTarget != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
NtClose(hTarget);
|
||||
}
|
||||
|
||||
if (LinkName.Buffer)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, LinkName.Buffer);
|
||||
}
|
||||
|
||||
if (LinkInformation)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, LinkInformation);
|
||||
}
|
||||
}
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, LinkTarget.Buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
return Ret;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -199,26 +139,32 @@ CreateHardLinkA(LPCSTR lpFileName,
|
|||
LPCSTR lpExistingFileName,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
||||
{
|
||||
PWCHAR FileNameW, ExistingFileNameW;
|
||||
BOOL Ret;
|
||||
BOOL Ret;
|
||||
PUNICODE_STRING lpFileNameW;
|
||||
UNICODE_STRING ExistingFileNameW;
|
||||
|
||||
if(!lpFileName || !lpExistingFileName)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
lpFileNameW = Basep8BitStringToStaticUnicodeString(lpFileName);
|
||||
if (!lpFileNameW)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
|
||||
return FALSE;
|
||||
if (!lpExistingFileName)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, TRUE)))
|
||||
return FALSE;
|
||||
if (!Basep8BitStringToDynamicUnicodeString(&ExistingFileNameW, lpExistingFileName))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Ret = CreateHardLinkW(FileNameW , ExistingFileNameW , lpSecurityAttributes);
|
||||
Ret = CreateHardLinkW(lpFileNameW->Buffer, ExistingFileNameW.Buffer, lpSecurityAttributes);
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingFileNameW);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingFileNameW.Buffer);
|
||||
|
||||
return Ret;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue