3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/hardlink.c
6 * PURPOSE: Hardlink functions
7 * PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
12 /* INCLUDES *****************************************************************/
17 #include "../include/debug.h"
20 /* FUNCTIONS ****************************************************************/
27 CreateHardLinkW(LPCWSTR lpFileName
,
28 LPCWSTR lpExistingFileName
,
29 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
31 UNICODE_STRING LinkTarget
, LinkName
;
32 LPVOID lpSecurityDescriptor
;
33 PFILE_LINK_INFORMATION LinkInformation
;
34 IO_STATUS_BLOCK IoStatus
;
38 if(!lpFileName
|| !lpExistingFileName
)
40 SetLastError(ERROR_INVALID_PARAMETER
);
44 lpSecurityDescriptor
= (lpSecurityAttributes
? lpSecurityAttributes
->lpSecurityDescriptor
: NULL
);
46 if(RtlDetermineDosPathNameType_U((LPWSTR
)lpFileName
) == 1 ||
47 RtlDetermineDosPathNameType_U((LPWSTR
)lpExistingFileName
) == 1)
49 DPRINT1("CreateHardLinkW() cannot handle UNC Paths!\n");
50 SetLastError(ERROR_INVALID_NAME
);
54 if(RtlDosPathNameToNtPathName_U((LPWSTR
)lpExistingFileName
, &LinkTarget
, NULL
, NULL
))
56 ULONG NeededSize
= RtlGetFullPathName_U((LPWSTR
)lpExistingFileName
, 0, NULL
, NULL
);
59 LPWSTR lpNtLinkTarget
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, NeededSize
* sizeof(WCHAR
));
60 if(lpNtLinkTarget
!= NULL
)
64 if(RtlGetFullPathName_U((LPWSTR
)lpExistingFileName
, NeededSize
, lpNtLinkTarget
, &lpFilePart
) &&
65 (*lpNtLinkTarget
) != L
'\0')
67 UNICODE_STRING CheckDrive
, LinkDrive
;
68 WCHAR wCheckDrive
[10];
70 swprintf(wCheckDrive
, L
"\\??\\%c:", (WCHAR
)(*lpNtLinkTarget
));
71 RtlInitUnicodeString(&CheckDrive
, wCheckDrive
);
73 RtlZeroMemory(&LinkDrive
, sizeof(UNICODE_STRING
));
75 LinkDrive
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, (MAX_PATH
+ 1) * sizeof(WCHAR
));
76 if(LinkDrive
.Buffer
!= NULL
)
78 HANDLE hFile
, hTarget
;
79 OBJECT_ATTRIBUTES ObjectAttributes
;
81 InitializeObjectAttributes(&ObjectAttributes
,
87 Status
= NtOpenSymbolicLinkObject(&hFile
, 1, &ObjectAttributes
);
88 if(NT_SUCCESS(Status
))
90 UNICODE_STRING LanManager
;
92 RtlInitUnicodeString(&LanManager
, L
"\\Device\\LanmanRedirector\\");
94 NtQuerySymbolicLinkObject(hFile
, &LinkDrive
, NULL
);
96 if(!RtlPrefixUnicodeString(&LanManager
, &LinkDrive
, TRUE
))
98 InitializeObjectAttributes(&ObjectAttributes
,
100 OBJ_CASE_INSENSITIVE
,
102 lpSecurityDescriptor
);
103 Status
= NtOpenFile(&hTarget
,
104 SYNCHRONIZE
| DELETE
,
107 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
108 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_REPARSE_POINT
);
109 if(NT_SUCCESS(Status
))
111 if(RtlDosPathNameToNtPathName_U((LPWSTR
)lpFileName
, &LinkName
, NULL
, NULL
))
113 NeededSize
= sizeof(FILE_LINK_INFORMATION
) + LinkName
.Length
+ sizeof(WCHAR
);
114 LinkInformation
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, NeededSize
);
115 if(LinkInformation
!= NULL
)
117 LinkInformation
->ReplaceIfExists
= FALSE
;
118 LinkInformation
->RootDirectory
= 0;
119 LinkInformation
->FileNameLength
= LinkName
.Length
;
120 RtlCopyMemory(LinkInformation
->FileName
, LinkName
.Buffer
, LinkName
.Length
);
122 Status
= NtSetInformationFile(hTarget
, &IoStatus
, LinkInformation
, NeededSize
, FileLinkInformation
);
123 if(NT_SUCCESS(Status
))
129 SetLastErrorByStatus(Status
);
132 RtlFreeHeap(RtlGetProcessHeap(), 0, LinkInformation
);
136 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
141 SetLastError(ERROR_PATH_NOT_FOUND
);
147 DPRINT1("Unable to open link destination \"%wZ\"!\n", &LinkTarget
);
148 SetLastErrorByStatus(Status
);
153 DPRINT1("Path \"%wZ\" must not be a mapped drive!\n", &LinkDrive
);
154 SetLastError(ERROR_INVALID_NAME
);
161 SetLastErrorByStatus(Status
);
166 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
171 SetLastError(ERROR_INVALID_NAME
);
173 RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget
);
177 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
182 SetLastError(ERROR_INVALID_NAME
);
184 RtlFreeUnicodeString(&LinkTarget
);
188 SetLastError(ERROR_PATH_NOT_FOUND
);
199 CreateHardLinkA(LPCSTR lpFileName
,
200 LPCSTR lpExistingFileName
,
201 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
203 PWCHAR FileNameW
, ExistingFileNameW
;
206 if(!lpFileName
|| !lpExistingFileName
)
208 SetLastError(ERROR_INVALID_PARAMETER
);
212 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
215 if (!(ExistingFileNameW
= FilenameA2W(lpExistingFileName
, TRUE
)))
218 Ret
= CreateHardLinkW(FileNameW
, ExistingFileNameW
, lpSecurityAttributes
);
220 RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingFileNameW
);