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 DEBUG_CHANNEL(kernel32file
);
19 /* FUNCTIONS ****************************************************************/
26 CreateHardLinkW(LPCWSTR lpFileName
,
27 LPCWSTR lpExistingFileName
,
28 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
30 UNICODE_STRING LinkTarget
, LinkName
;
31 LPVOID lpSecurityDescriptor
;
32 PFILE_LINK_INFORMATION LinkInformation
;
33 IO_STATUS_BLOCK IoStatus
;
37 if(!lpFileName
|| !lpExistingFileName
)
39 SetLastError(ERROR_INVALID_PARAMETER
);
43 lpSecurityDescriptor
= (lpSecurityAttributes
? lpSecurityAttributes
->lpSecurityDescriptor
: NULL
);
45 if(RtlDetermineDosPathNameType_U((LPWSTR
)lpFileName
) == 1 ||
46 RtlDetermineDosPathNameType_U((LPWSTR
)lpExistingFileName
) == 1)
48 WARN("CreateHardLinkW() cannot handle UNC Paths!\n");
49 SetLastError(ERROR_INVALID_NAME
);
53 if(RtlDosPathNameToNtPathName_U(lpExistingFileName
, &LinkTarget
, NULL
, NULL
))
55 ULONG NeededSize
= RtlGetFullPathName_U((LPWSTR
)lpExistingFileName
, 0, NULL
, NULL
);
58 LPWSTR lpNtLinkTarget
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, NeededSize
* sizeof(WCHAR
));
59 if(lpNtLinkTarget
!= NULL
)
63 if(RtlGetFullPathName_U((LPWSTR
)lpExistingFileName
, NeededSize
, lpNtLinkTarget
, &lpFilePart
) &&
64 (*lpNtLinkTarget
) != L
'\0')
66 UNICODE_STRING CheckDrive
, LinkDrive
;
67 WCHAR wCheckDrive
[10];
69 swprintf(wCheckDrive
, L
"\\??\\%c:", (WCHAR
)(*lpNtLinkTarget
));
70 RtlInitUnicodeString(&CheckDrive
, wCheckDrive
);
72 RtlZeroMemory(&LinkDrive
, sizeof(UNICODE_STRING
));
74 LinkDrive
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, (MAX_PATH
+ 1) * sizeof(WCHAR
));
75 if(LinkDrive
.Buffer
!= NULL
)
77 HANDLE hFile
, hTarget
;
78 OBJECT_ATTRIBUTES ObjectAttributes
;
80 InitializeObjectAttributes(&ObjectAttributes
,
86 Status
= NtOpenSymbolicLinkObject(&hFile
, 1, &ObjectAttributes
);
87 if(NT_SUCCESS(Status
))
89 UNICODE_STRING LanManager
;
91 RtlInitUnicodeString(&LanManager
, L
"\\Device\\LanmanRedirector\\");
93 NtQuerySymbolicLinkObject(hFile
, &LinkDrive
, NULL
);
95 if(!RtlPrefixUnicodeString(&LanManager
, &LinkDrive
, TRUE
))
97 InitializeObjectAttributes(&ObjectAttributes
,
101 lpSecurityDescriptor
);
102 Status
= NtOpenFile(&hTarget
,
103 SYNCHRONIZE
| DELETE
,
106 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
107 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_REPARSE_POINT
);
108 if(NT_SUCCESS(Status
))
110 if(RtlDosPathNameToNtPathName_U(lpFileName
, &LinkName
, NULL
, NULL
))
112 NeededSize
= sizeof(FILE_LINK_INFORMATION
) + LinkName
.Length
+ sizeof(WCHAR
);
113 LinkInformation
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, NeededSize
);
114 if(LinkInformation
!= NULL
)
116 LinkInformation
->ReplaceIfExists
= FALSE
;
117 LinkInformation
->RootDirectory
= 0;
118 LinkInformation
->FileNameLength
= LinkName
.Length
;
119 RtlCopyMemory(LinkInformation
->FileName
, LinkName
.Buffer
, LinkName
.Length
);
121 Status
= NtSetInformationFile(hTarget
, &IoStatus
, LinkInformation
, NeededSize
, FileLinkInformation
);
122 if(NT_SUCCESS(Status
))
128 SetLastErrorByStatus(Status
);
131 RtlFreeHeap(RtlGetProcessHeap(), 0, LinkInformation
);
135 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
140 SetLastError(ERROR_PATH_NOT_FOUND
);
146 WARN("Unable to open link destination \"%wZ\"!\n", &LinkTarget
);
147 SetLastErrorByStatus(Status
);
152 WARN("Path \"%wZ\" must not be a mapped drive!\n", &LinkDrive
);
153 SetLastError(ERROR_INVALID_NAME
);
160 SetLastErrorByStatus(Status
);
165 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
170 SetLastError(ERROR_INVALID_NAME
);
172 RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget
);
176 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
181 SetLastError(ERROR_INVALID_NAME
);
183 RtlFreeHeap(RtlGetProcessHeap(), 0, LinkTarget
.Buffer
);
187 SetLastError(ERROR_PATH_NOT_FOUND
);
198 CreateHardLinkA(LPCSTR lpFileName
,
199 LPCSTR lpExistingFileName
,
200 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
202 PWCHAR FileNameW
, ExistingFileNameW
;
205 if(!lpFileName
|| !lpExistingFileName
)
207 SetLastError(ERROR_INVALID_PARAMETER
);
211 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
214 if (!(ExistingFileNameW
= FilenameA2W(lpExistingFileName
, TRUE
)))
217 Ret
= CreateHardLinkW(FileNameW
, ExistingFileNameW
, lpSecurityAttributes
);
219 RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingFileNameW
);