[KERNEL32]

Simplify overcomplicated function CreateHardlinkW(), and SEHify it.

svn path=/trunk/; revision=53823
This commit is contained in:
Pierre Schweitzer 2011-09-24 07:51:21 +00:00
parent 2c440bd22d
commit acee43d271

View file

@ -2,11 +2,10 @@
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
* FILE: lib/kernel32/file/hardlink.c * FILE: dll/win32/kernel32/client/file/hardlink.c
* PURPOSE: Hardlink functions * PURPOSE: Hardlink functions
* PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net) * PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
* UPDATE HISTORY: * Pierre Schweitzer (pierre.schweitzer@reactos.org)
* Created 13/03/2004
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -27,170 +26,111 @@ CreateHardLinkW(LPCWSTR lpFileName,
LPCWSTR lpExistingFileName, LPCWSTR lpExistingFileName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes) LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{ {
UNICODE_STRING LinkTarget, LinkName; NTSTATUS Status;
LPVOID lpSecurityDescriptor; BOOL Ret = FALSE;
PFILE_LINK_INFORMATION LinkInformation; ULONG NeededSize;
IO_STATUS_BLOCK IoStatus; IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes;
BOOL Ret = FALSE; HANDLE hTarget = INVALID_HANDLE_VALUE;
PFILE_LINK_INFORMATION LinkInformation = NULL;
UNICODE_STRING LinkTarget = {0, 0, NULL}, LinkName = {0, 0, NULL};
if(!lpFileName || !lpExistingFileName) TRACE("CreateHardLinkW: %S, %S, %p\n", lpFileName, lpExistingFileName, lpSecurityAttributes);
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
lpSecurityDescriptor = (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL); /* Validate parameters */
if(!lpFileName || !lpExistingFileName)
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)
{ {
LPWSTR lpNtLinkTarget = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize * sizeof(WCHAR)); SetLastError(ERROR_INVALID_PARAMETER);
if(lpNtLinkTarget != NULL) return FALSE;
{ }
LPWSTR lpFilePart;
if(RtlGetFullPathName_U((LPWSTR)lpExistingFileName, NeededSize, lpNtLinkTarget, &lpFilePart) && _SEH2_TRY
(*lpNtLinkTarget) != L'\0') {
/* Get target UNC path */
if (!RtlDosPathNameToNtPathName_U(lpExistingFileName, &LinkTarget, NULL, NULL))
{ {
UNICODE_STRING CheckDrive, LinkDrive; SetLastError(ERROR_PATH_NOT_FOUND);
WCHAR wCheckDrive[10]; _SEH2_LEAVE;
}
swprintf(wCheckDrive, L"\\??\\%c:", (WCHAR)(*lpNtLinkTarget)); /* Open target */
RtlInitUnicodeString(&CheckDrive, wCheckDrive); 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)); /* Get UNC path name for link */
if(LinkDrive.Buffer != NULL) if (!RtlDosPathNameToNtPathName_U(lpFileName, &LinkName, NULL, NULL))
{ {
HANDLE hFile, hTarget; SetLastError(ERROR_PATH_NOT_FOUND);
OBJECT_ATTRIBUTES ObjectAttributes; _SEH2_LEAVE;
}
InitializeObjectAttributes(&ObjectAttributes, /* Prepare data for link */
&CheckDrive, NeededSize = sizeof(FILE_LINK_INFORMATION) + LinkName.Length;
OBJ_CASE_INSENSITIVE, LinkInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, NeededSize);
NULL, if (!LinkInformation)
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
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY); 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); _SEH2_END;
}
else
{
SetLastError(ERROR_PATH_NOT_FOUND);
}
return Ret; return Ret;
} }
/* /*
* @implemented * @implemented
*/ */
@ -199,26 +139,32 @@ CreateHardLinkA(LPCSTR lpFileName,
LPCSTR lpExistingFileName, LPCSTR lpExistingFileName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes) LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{ {
PWCHAR FileNameW, ExistingFileNameW; BOOL Ret;
BOOL Ret; PUNICODE_STRING lpFileNameW;
UNICODE_STRING ExistingFileNameW;
if(!lpFileName || !lpExistingFileName) lpFileNameW = Basep8BitStringToStaticUnicodeString(lpFileName);
{ if (!lpFileNameW)
SetLastError(ERROR_INVALID_PARAMETER); {
return FALSE; return FALSE;
} }
if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) if (!lpExistingFileName)
return FALSE; {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, TRUE))) if (!Basep8BitStringToDynamicUnicodeString(&ExistingFileNameW, lpExistingFileName))
return FALSE; {
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 */ /* EOF */