mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 08:54:40 +00:00
[KERNEL32]: CreateHardLinkW was not setting last error on failure.
[KERNEL32]: Cleanup/format/comment/annotate CreateHardLink*. svn path=/trunk/; revision=55790
This commit is contained in:
parent
49103eac64
commit
8c1ab63ced
|
@ -13,18 +13,17 @@
|
||||||
#include <k32.h>
|
#include <k32.h>
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
DEBUG_CHANNEL(kernel32file);
|
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI
|
BOOL
|
||||||
CreateHardLinkW(LPCWSTR lpFileName,
|
WINAPI
|
||||||
LPCWSTR lpExistingFileName,
|
CreateHardLinkW(IN LPCWSTR lpFileName,
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
IN LPCWSTR lpExistingFileName,
|
||||||
|
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
BOOL Ret = FALSE;
|
BOOL Ret = FALSE;
|
||||||
|
@ -33,12 +32,13 @@ CreateHardLinkW(LPCWSTR lpFileName,
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
HANDLE hTarget = INVALID_HANDLE_VALUE;
|
HANDLE hTarget = INVALID_HANDLE_VALUE;
|
||||||
PFILE_LINK_INFORMATION LinkInformation = NULL;
|
PFILE_LINK_INFORMATION LinkInformation = NULL;
|
||||||
UNICODE_STRING LinkTarget = {0, 0, NULL}, LinkName = {0, 0, NULL};
|
UNICODE_STRING LinkTarget, LinkName;
|
||||||
|
|
||||||
TRACE("CreateHardLinkW: %S, %S, %p\n", lpFileName, lpExistingFileName, lpSecurityAttributes);
|
/* Initialize */
|
||||||
|
LinkTarget.Buffer = LinkName.Buffer = NULL;
|
||||||
|
|
||||||
/* Validate parameters */
|
/* Validate parameters */
|
||||||
if(!lpFileName || !lpExistingFileName)
|
if (!(lpFileName) || !(lpExistingFileName))
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -47,8 +47,12 @@ CreateHardLinkW(LPCWSTR lpFileName,
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
/* Get target UNC path */
|
/* Get target UNC path */
|
||||||
if (!RtlDosPathNameToNtPathName_U(lpExistingFileName, &LinkTarget, NULL, NULL))
|
if (!RtlDosPathNameToNtPathName_U(lpExistingFileName,
|
||||||
|
&LinkTarget,
|
||||||
|
NULL,
|
||||||
|
NULL))
|
||||||
{
|
{
|
||||||
|
/* Set the error and fail */
|
||||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
@ -58,8 +62,9 @@ CreateHardLinkW(LPCWSTR lpFileName,
|
||||||
&LinkTarget,
|
&LinkTarget,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE,
|
||||||
NULL,
|
NULL,
|
||||||
(lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
|
lpSecurityAttributes ?
|
||||||
|
lpSecurityAttributes->lpSecurityDescriptor :
|
||||||
|
NULL);
|
||||||
Status = NtOpenFile(&hTarget,
|
Status = NtOpenFile(&hTarget,
|
||||||
SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
|
SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
|
@ -68,6 +73,7 @@ CreateHardLinkW(LPCWSTR lpFileName,
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT);
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
/* Convert the error and fail */
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
@ -75,95 +81,93 @@ CreateHardLinkW(LPCWSTR lpFileName,
|
||||||
/* Get UNC path name for link */
|
/* Get UNC path name for link */
|
||||||
if (!RtlDosPathNameToNtPathName_U(lpFileName, &LinkName, NULL, NULL))
|
if (!RtlDosPathNameToNtPathName_U(lpFileName, &LinkName, NULL, NULL))
|
||||||
{
|
{
|
||||||
|
/* Set the error and fail */
|
||||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare data for link */
|
/* Allocate data for link */
|
||||||
NeededSize = sizeof(FILE_LINK_INFORMATION) + LinkName.Length;
|
NeededSize = sizeof(FILE_LINK_INFORMATION) + LinkName.Length;
|
||||||
LinkInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, NeededSize);
|
LinkInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, NeededSize);
|
||||||
if (!LinkInformation)
|
if (!LinkInformation)
|
||||||
{
|
{
|
||||||
|
/* We're out of memory */
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Setup data for link and create it */
|
||||||
RtlMoveMemory(LinkInformation->FileName, LinkName.Buffer, LinkName.Length);
|
RtlMoveMemory(LinkInformation->FileName, LinkName.Buffer, LinkName.Length);
|
||||||
LinkInformation->ReplaceIfExists = FALSE;
|
LinkInformation->ReplaceIfExists = FALSE;
|
||||||
LinkInformation->RootDirectory = 0;
|
LinkInformation->RootDirectory = 0;
|
||||||
LinkInformation->FileNameLength = LinkName.Length;
|
LinkInformation->FileNameLength = LinkName.Length;
|
||||||
|
|
||||||
/* Create hard link */
|
|
||||||
Status = NtSetInformationFile(hTarget,
|
Status = NtSetInformationFile(hTarget,
|
||||||
&IoStatusBlock,
|
&IoStatusBlock,
|
||||||
LinkInformation,
|
LinkInformation,
|
||||||
NeededSize,
|
NeededSize,
|
||||||
FileLinkInformation);
|
FileLinkInformation);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
/* Set success code */
|
||||||
Ret = TRUE;
|
Ret = TRUE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Convert error code and return default (FALSE) */
|
||||||
|
BaseSetLastNTError(Status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_SEH2_FINALLY
|
_SEH2_FINALLY
|
||||||
{
|
{
|
||||||
if (LinkTarget.Buffer)
|
/* Cleanup all allocations */
|
||||||
{
|
if (LinkTarget.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, 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);
|
||||||
if (hTarget != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
NtClose(hTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LinkName.Buffer)
|
|
||||||
{
|
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, LinkName.Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LinkInformation)
|
|
||||||
{
|
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, LinkInformation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI
|
BOOL
|
||||||
CreateHardLinkA(LPCSTR lpFileName,
|
WINAPI
|
||||||
LPCSTR lpExistingFileName,
|
CreateHardLinkA(IN LPCSTR lpFileName,
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
IN LPCSTR lpExistingFileName,
|
||||||
|
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
||||||
{
|
{
|
||||||
BOOL Ret;
|
BOOL Ret;
|
||||||
PUNICODE_STRING lpFileNameW;
|
PUNICODE_STRING lpFileNameW;
|
||||||
UNICODE_STRING ExistingFileNameW;
|
UNICODE_STRING ExistingFileNameW;
|
||||||
|
|
||||||
|
/* Convert the filename to unicode, using MAX_PATH limitations */
|
||||||
lpFileNameW = Basep8BitStringToStaticUnicodeString(lpFileName);
|
lpFileNameW = Basep8BitStringToStaticUnicodeString(lpFileName);
|
||||||
if (!lpFileNameW)
|
if (!lpFileNameW) return FALSE;
|
||||||
|
|
||||||
|
/* Check if there's an existing name as well */
|
||||||
|
if (lpExistingFileName)
|
||||||
{
|
{
|
||||||
return FALSE;
|
/* We're already using the static string above, so do this dynamically */
|
||||||
|
if (!Basep8BitStringToDynamicUnicodeString(&ExistingFileNameW,
|
||||||
|
lpExistingFileName))
|
||||||
|
{
|
||||||
|
/* Out of memory -- fail */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No existing file name */
|
||||||
|
ExistingFileNameW.Buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lpExistingFileName)
|
/* Call the Wide function, and then free our dynamic string */
|
||||||
{
|
Ret = CreateHardLinkW(lpFileNameW->Buffer,
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
ExistingFileNameW.Buffer,
|
||||||
return FALSE;
|
lpSecurityAttributes);
|
||||||
}
|
RtlFreeUnicodeString(&ExistingFileNameW);
|
||||||
|
|
||||||
if (!Basep8BitStringToDynamicUnicodeString(&ExistingFileNameW, lpExistingFileName))
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ret = CreateHardLinkW(lpFileNameW->Buffer, ExistingFileNameW.Buffer, lpSecurityAttributes);
|
|
||||||
|
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingFileNameW.Buffer);
|
|
||||||
|
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue