From acee43d271976e1b5c701d9f30a2f1d1ab2b37d9 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sat, 24 Sep 2011 07:51:21 +0000 Subject: [PATCH] [KERNEL32] Simplify overcomplicated function CreateHardlinkW(), and SEHify it. svn path=/trunk/; revision=53823 --- .../dll/win32/kernel32/client/file/hardlink.c | 270 +++++++----------- 1 file changed, 108 insertions(+), 162 deletions(-) diff --git a/reactos/dll/win32/kernel32/client/file/hardlink.c b/reactos/dll/win32/kernel32/client/file/hardlink.c index 91e2a6ac674..ca7b4fe675b 100644 --- a/reactos/dll/win32/kernel32/client/file/hardlink.c +++ b/reactos/dll/win32/kernel32/client/file/hardlink.c @@ -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 */