diff --git a/reactos/include/ddk/fstypes.h b/reactos/include/ddk/fstypes.h index d04f7bc0101..c8d7519e4d7 100644 --- a/reactos/include/ddk/fstypes.h +++ b/reactos/include/ddk/fstypes.h @@ -1,6 +1,6 @@ #ifndef __INCLUDE_DDK_FSTYPES_H #define __INCLUDE_DDK_FSTYPES_H -/* $Id: fstypes.h,v 1.13 2003/08/14 18:30:27 silverblade Exp $ */ +/* $Id: fstypes.h,v 1.14 2004/03/14 09:21:41 weiden Exp $ */ #ifndef __USE_W32API @@ -14,6 +14,12 @@ typedef struct _FILE_LOCK_INFO { LARGE_INTEGER EndingByte; } FILE_LOCK_INFO, *PFILE_LOCK_INFO; +typedef struct _FILE_LINK_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; typedef NTSTATUS (*PCOMPLETE_LOCK_IRP_ROUTINE) ( IN PVOID Context, diff --git a/reactos/include/ddk/iodef.h b/reactos/include/ddk/iodef.h index f6248fa14dc..608005a0c8d 100644 --- a/reactos/include/ddk/iodef.h +++ b/reactos/include/ddk/iodef.h @@ -428,6 +428,8 @@ enum #define FILE_VALID_MAILSLOT_OPTION_FLAGS 0x00000032 #define FILE_VALID_SET_FLAGS 0x00001036 +#define FILE_OPEN_REPARSE_POINT 0x00200000 + /* * special ByteOffset values */ diff --git a/reactos/lib/kernel32/file/hardlink.c b/reactos/lib/kernel32/file/hardlink.c new file mode 100644 index 00000000000..ab28ec4d9e6 --- /dev/null +++ b/reactos/lib/kernel32/file/hardlink.c @@ -0,0 +1,251 @@ +/* $Id: hardlink.c,v 1.1 2004/03/14 09:21:42 weiden Exp $ + * + * 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 +#include + +#define NDEBUG +#include "../include/debug.h" + + +/* FUNCTIONS ****************************************************************/ + + +/* + * @implemented + */ +BOOL STDCALL +CreateHardLinkW( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes +) +{ + UNICODE_STRING LinkTarget, LinkName, CheckDrive, LinkDrive, LanManager; + LPWSTR lpNtLinkTarget, lpFilePart; + ULONG NeededSize; + LPVOID lpSecurityDescriptor; + WCHAR wCheckDrive[10]; + OBJECT_ATTRIBUTES ObjectAttribues; + PFILE_LINK_INFORMATION LinkInformation; + IO_STATUS_BLOCK IoStatus; + HANDLE hFile, hTarget; + NTSTATUS Status; + + 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) + { + DPRINT1("CreateHardLinkW() cannot handle UNC Paths!\n"); + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + + if(!RtlDosPathNameToNtPathName_U((LPWSTR)lpExistingFileName, &LinkTarget, NULL, NULL)) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + if(!(NeededSize = RtlGetFullPathName_U((LPWSTR)lpExistingFileName, 0, NULL, NULL))) + { + RtlFreeUnicodeString(&LinkTarget); + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + + NeededSize += 2; + if(!(lpNtLinkTarget = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize * sizeof(WCHAR)))) + { + RtlFreeUnicodeString(&LinkTarget); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + if(!RtlGetFullPathName_U((LPWSTR)lpExistingFileName, NeededSize, lpNtLinkTarget, &lpFilePart)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget); + RtlFreeUnicodeString(&LinkTarget); + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + + swprintf(wCheckDrive, L"\\??\\%c:", (WCHAR)(*lpNtLinkTarget)); + RtlInitUnicodeString(&CheckDrive, wCheckDrive); + + RtlZeroMemory(&LinkDrive, sizeof(UNICODE_STRING)); + if(!(LinkDrive.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, + (MAX_PATH + 1) * sizeof(WCHAR)))) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget); + RtlFreeUnicodeString(&LinkTarget); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + InitializeObjectAttributes(&ObjectAttribues, + &CheckDrive, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = ZwOpenSymbolicLinkObject(&hFile, 1, &ObjectAttribues); + if(!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, LinkDrive.Buffer); + RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget); + RtlFreeUnicodeString(&LinkTarget); + SetLastErrorByStatus(Status); + return FALSE; + } + + RtlInitUnicodeString(&LanManager, L"\\Device\\LanmanRedirector\\"); + + ZwQuerySymbolicLinkObject(hFile, &LinkDrive, NULL); + + if(RtlPrefixUnicodeString(&LanManager, &LinkDrive, TRUE)) + { + ZwClose(hFile); + RtlFreeHeap(RtlGetProcessHeap(), 0, LinkDrive.Buffer); + RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget); + RtlFreeUnicodeString(&LinkTarget); + DPRINT1("Path \"%wZ\" must not be a mapped drive!\n", &LinkDrive); + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + + InitializeObjectAttributes(&ObjectAttribues, + &LinkTarget, + OBJ_CASE_INSENSITIVE, + NULL, + lpSecurityDescriptor); + + Status = ZwOpenFile(&hTarget, SYNCHRONIZE | DELETE, &ObjectAttribues, &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)) + { + ZwClose(hFile); + RtlFreeHeap(RtlGetProcessHeap(), 0, LinkDrive.Buffer); + RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget); + RtlFreeUnicodeString(&LinkTarget); + DPRINT1("Unable to open link destination \"%wZ\"!\n", &LinkTarget); + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + + if(!RtlDosPathNameToNtPathName_U((LPWSTR)lpFileName, &LinkName, NULL, NULL)) + { + ZwClose(hTarget); + ZwClose(hFile); + RtlFreeHeap(RtlGetProcessHeap(), 0, LinkDrive.Buffer); + RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget); + RtlFreeUnicodeString(&LinkTarget); + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + + NeededSize = sizeof(FILE_LINK_INFORMATION) + LinkName.Length + sizeof(WCHAR); + if(!(LinkInformation = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize))) + { + ZwClose(hTarget); + ZwClose(hFile); + RtlFreeHeap(RtlGetProcessHeap(), 0, LinkDrive.Buffer); + RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget); + RtlFreeUnicodeString(&LinkTarget); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + LinkInformation->ReplaceIfExists = FALSE; + LinkInformation->RootDirectory = 0; + LinkInformation->FileNameLength = LinkName.Length; + RtlCopyMemory(LinkInformation->FileName, LinkName.Buffer, LinkName.Length); + + Status = ZwSetInformationFile(hTarget, &IoStatus, LinkInformation, NeededSize, FileLinkInformation); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + } + + ZwClose(hTarget); + ZwClose(hFile); + RtlFreeHeap(RtlGetProcessHeap(), 0, LinkInformation); + RtlFreeHeap(RtlGetProcessHeap(), 0, LinkDrive.Buffer); + RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget); + RtlFreeUnicodeString(&LinkTarget); + return NT_SUCCESS(Status); +} + + +/* + * @implemented + */ +BOOL STDCALL +CreateHardLinkA( + LPCSTR lpFileName, + LPCSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes +) +{ + ANSI_STRING FileNameA, ExistingFileNameA; + UNICODE_STRING FileName, ExistingFileName; + NTSTATUS Status; + BOOL Ret; + + if(!lpFileName || !lpExistingFileName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + RtlInitAnsiString(&FileNameA, (LPSTR)lpFileName); + RtlInitAnsiString(&ExistingFileNameA, (LPSTR)lpExistingFileName); + + if(bIsFileApiAnsi) + Status = RtlAnsiStringToUnicodeString(&FileName, &FileNameA, TRUE); + else + Status = RtlOemStringToUnicodeString(&FileName, &FileNameA, TRUE); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + if(bIsFileApiAnsi) + Status = RtlAnsiStringToUnicodeString(&ExistingFileName, &ExistingFileNameA, TRUE); + else + Status = RtlOemStringToUnicodeString(&ExistingFileName, &ExistingFileNameA, TRUE); + if(!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&FileName); + SetLastErrorByStatus(Status); + return FALSE; + } + + Ret = CreateHardLinkW(FileName.Buffer, ExistingFileName.Buffer, lpSecurityAttributes); + + RtlFreeUnicodeString(&FileName); + RtlFreeUnicodeString(&ExistingFileName); + + return Ret; +} + +/* EOF */ diff --git a/reactos/lib/kernel32/k32.h b/reactos/lib/kernel32/k32.h index 9859cc5eabb..816c8c70f85 100755 --- a/reactos/lib/kernel32/k32.h +++ b/reactos/lib/kernel32/k32.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/reactos/lib/kernel32/makefile b/reactos/lib/kernel32/makefile index ebd99de263c..30af6359d4d 100644 --- a/reactos/lib/kernel32/makefile +++ b/reactos/lib/kernel32/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.77 2004/02/22 17:30:32 chorns Exp $ +# $Id: makefile,v 1.78 2004/03/14 09:21:41 weiden Exp $ PATH_TO_TOP = ../.. @@ -41,7 +41,7 @@ FILE_OBJECTS = file/file.o file/curdir.o file/lfile.o file/dir.o \ file/create.o file/find.o file/copy.o file/pipe.o \ file/move.o file/lock.o file/rw.o file/delete.o \ file/npipe.o file/tape.o file/mailslot.o file/backup.o \ - file/cnotify.o + file/cnotify.o file/hardlink.o MEM_OBJECTS = mem/global.o mem/heap.o mem/isbad.o mem/local.o \ mem/procmem.o mem/section.o mem/virtual.o diff --git a/reactos/lib/kernel32/misc/stubs.c b/reactos/lib/kernel32/misc/stubs.c index 8d2eb88474f..50b7fb7ef26 100644 --- a/reactos/lib/kernel32/misc/stubs.c +++ b/reactos/lib/kernel32/misc/stubs.c @@ -1,4 +1,4 @@ -/* $Id: stubs.c,v 1.62 2004/02/15 07:03:56 arty Exp $ +/* $Id: stubs.c,v 1.63 2004/03/14 09:21:41 weiden Exp $ * * KERNEL32.DLL stubs (unimplemented functions) * Remove from this file, if you implement them. @@ -1653,21 +1653,6 @@ CheckNameLegalDOS8Dot3W( return 0; } -/* - * @unimplemented - */ -BOOL -STDCALL -CreateHardLinkW( - LPCWSTR lpFileName, - LPCWSTR lpExistingFileName, - LPSECURITY_ATTRIBUTES lpSecurityAttributes - ) -{ - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - /* * @unimplemented */ @@ -2042,21 +2027,6 @@ CheckNameLegalDOS8Dot3A( return 0; } -/* - * @unimplemented - */ -BOOL -STDCALL -CreateHardLinkA( - LPCSTR lpFileName, - LPCSTR lpExistingFileName, - LPSECURITY_ATTRIBUTES lpSecurityAttributes - ) -{ - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - /* * @unimplemented */