mirror of
https://github.com/reactos/reactos.git
synced 2024-11-04 13:52:30 +00:00
178300c8a6
* Fix PCH use in shell32. svn path=/branches/shell32_new-bringup/; revision=53319
224 lines
6.9 KiB
C
224 lines
6.9 KiB
C
/* $Id$
|
|
*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS system libraries
|
|
* FILE: lib/kernel32/file/hardlink.c
|
|
* PURPOSE: Hardlink functions
|
|
* PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
|
|
* UPDATE HISTORY:
|
|
* Created 13/03/2004
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <k32.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
DEBUG_CHANNEL(kernel32file);
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL WINAPI
|
|
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;
|
|
|
|
if(!lpFileName || !lpExistingFileName)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
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)
|
|
{
|
|
LPWSTR lpNtLinkTarget = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize * sizeof(WCHAR));
|
|
if(lpNtLinkTarget != NULL)
|
|
{
|
|
LPWSTR lpFilePart;
|
|
|
|
if(RtlGetFullPathName_U((LPWSTR)lpExistingFileName, NeededSize, lpNtLinkTarget, &lpFilePart) &&
|
|
(*lpNtLinkTarget) != L'\0')
|
|
{
|
|
UNICODE_STRING CheckDrive, LinkDrive;
|
|
WCHAR wCheckDrive[10];
|
|
|
|
swprintf(wCheckDrive, L"\\??\\%c:", (WCHAR)(*lpNtLinkTarget));
|
|
RtlInitUnicodeString(&CheckDrive, wCheckDrive);
|
|
|
|
RtlZeroMemory(&LinkDrive, sizeof(UNICODE_STRING));
|
|
|
|
LinkDrive.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (MAX_PATH + 1) * sizeof(WCHAR));
|
|
if(LinkDrive.Buffer != NULL)
|
|
{
|
|
HANDLE hFile, hTarget;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
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
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
}
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget);
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
}
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LinkTarget.Buffer);
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL WINAPI
|
|
CreateHardLinkA(LPCSTR lpFileName,
|
|
LPCSTR lpExistingFileName,
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
|
{
|
|
PWCHAR FileNameW, ExistingFileNameW;
|
|
BOOL Ret;
|
|
|
|
if(!lpFileName || !lpExistingFileName)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
|
|
return FALSE;
|
|
|
|
if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, TRUE)))
|
|
return FALSE;
|
|
|
|
Ret = CreateHardLinkW(FileNameW , ExistingFileNameW , lpSecurityAttributes);
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingFileNameW);
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/* EOF */
|