[INTRIN]
[reactos.git] / reactos / dll / win32 / kernel32 / client / file / delete.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/delete.c
5 * PURPOSE: Deleting files
6 * PROGRAMMER: Ariadne (ariadne@xs4all.nl)
7 * UPDATE HISTORY:
8 * Created 01/11/98
9 */
10
11 /* INCLUDES ****************************************************************/
12
13 #include <k32.h>
14 #define NDEBUG
15 #include <reactos/debug.h>
16
17 /* FUNCTIONS ****************************************************************/
18
19 /*
20 * @implemented
21 */
22 BOOL
23 WINAPI
24 DeleteFileA(IN LPCSTR lpFileName)
25 {
26 PUNICODE_STRING FileName;
27
28 /* Convert the string to unicode, and call the wide function */
29 FileName = Basep8BitStringToStaticUnicodeString(lpFileName);
30 if (FileName) return DeleteFileW(FileName->Buffer);
31 return FALSE;
32 }
33
34 /*
35 * @implemented
36 */
37 BOOL
38 WINAPI
39 DeleteFileW(IN LPCWSTR lpFileName)
40 {
41 FILE_DISPOSITION_INFORMATION FileDispInfo;
42 OBJECT_ATTRIBUTES ObjectAttributes;
43 IO_STATUS_BLOCK IoStatusBlock;
44 UNICODE_STRING NtPathU;
45 HANDLE FileHandle;
46 NTSTATUS Status;
47 RTL_RELATIVE_NAME_U RelativeName;
48 PWCHAR PathBuffer;
49 FILE_ATTRIBUTE_TAG_INFORMATION FileTagInformation;
50
51 /* Convert to NT path and get the relative name too */
52 if (!RtlDosPathNameToNtPathName_U(lpFileName,
53 &NtPathU,
54 NULL,
55 &RelativeName))
56 {
57 /* Bail out if the path name makes no sense */
58 SetLastError(ERROR_PATH_NOT_FOUND);
59 return FALSE;
60 }
61
62 /* Save the path buffer in case we free it later */
63 PathBuffer = NtPathU.Buffer;
64
65 /* If we have a relative name... */
66 if (RelativeName.RelativeName.Length)
67 {
68 /* Do a relative open with only the relative path set */
69 NtPathU = RelativeName.RelativeName;
70 }
71 else
72 {
73 /* Do a full path open with no containing directory */
74 RelativeName.ContainingDirectory = NULL;
75 }
76
77 /* Now open the directory name that was passed in */
78 InitializeObjectAttributes(&ObjectAttributes,
79 &NtPathU,
80 OBJ_CASE_INSENSITIVE,
81 RelativeName.ContainingDirectory,
82 NULL);
83 Status = NtOpenFile(&FileHandle,
84 DELETE | FILE_READ_ATTRIBUTES,
85 &ObjectAttributes,
86 &IoStatusBlock,
87 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
88 FILE_NON_DIRECTORY_FILE |
89 FILE_OPEN_FOR_BACKUP_INTENT |
90 FILE_OPEN_REPARSE_POINT);
91 if (NT_SUCCESS(Status))
92 {
93 /* Check if there's a reparse point associated with this file handle */
94 Status = NtQueryInformationFile(FileHandle,
95 &IoStatusBlock,
96 &FileTagInformation,
97 sizeof(FileTagInformation),
98 FileAttributeTagInformation);
99 if ((NT_SUCCESS(Status)) &&
100 (FileTagInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
101 (FileTagInformation.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT))
102 {
103 /* There is, so now try to open it with reparse behavior */
104 NtClose(FileHandle);
105 Status = NtOpenFile(&FileHandle,
106 DELETE,
107 &ObjectAttributes,
108 &IoStatusBlock,
109 FILE_SHARE_DELETE |
110 FILE_SHARE_READ |
111 FILE_SHARE_WRITE,
112 FILE_NON_DIRECTORY_FILE |
113 FILE_OPEN_FOR_BACKUP_INTENT);
114 if (!NT_SUCCESS(Status))
115 {
116 /* We failed -- maybe whoever is handling this tag isn't there */
117 if (Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED)
118 {
119 /* Try to open it for delete, without reparse behavior */
120 Status = NtOpenFile(&FileHandle,
121 DELETE,
122 &ObjectAttributes,
123 &IoStatusBlock,
124 FILE_SHARE_READ |
125 FILE_SHARE_WRITE |
126 FILE_SHARE_DELETE,
127 FILE_NON_DIRECTORY_FILE |
128 FILE_OPEN_FOR_BACKUP_INTENT |
129 FILE_OPEN_REPARSE_POINT);
130 }
131
132 if (!NT_SUCCESS(Status))
133 {
134 RtlReleaseRelativeName(&RelativeName);
135 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
136 BaseSetLastNTError(Status);
137 return FALSE;
138 }
139 }
140 }
141 else if (!(NT_SUCCESS(Status)) &&
142 (Status != STATUS_NOT_IMPLEMENTED) &&
143 (Status != STATUS_INVALID_PARAMETER))
144 {
145 /* We had some critical error querying the attributes, bail out */
146 RtlReleaseRelativeName(&RelativeName);
147 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
148 NtClose(FileHandle);
149 BaseSetLastNTError(Status);
150 return FALSE;
151 }
152 }
153 else
154 {
155 /* It's possible that FILE_OPEN_REPARSE_POINT was not understood */
156 if (Status == STATUS_INVALID_PARAMETER)
157 {
158 /* Try opening the file normally, with reparse behavior */
159 Status = NtOpenFile(&FileHandle,
160 DELETE,
161 &ObjectAttributes,
162 &IoStatusBlock,
163 FILE_SHARE_DELETE |
164 FILE_SHARE_READ |
165 FILE_SHARE_WRITE,
166 FILE_NON_DIRECTORY_FILE |
167 FILE_OPEN_FOR_BACKUP_INTENT);
168 if (!NT_SUCCESS(Status))
169 {
170 /* This failed too, fail */
171 RtlReleaseRelativeName(&RelativeName);
172 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
173 BaseSetLastNTError(Status);
174 return FALSE;
175 }
176 }
177 else
178 {
179 /* Maybe we didn't have READ_ATTRIBUTE rights? */
180 if (Status != STATUS_ACCESS_DENIED)
181 {
182 /* Nope, it was something else, let's fail */
183 RtlReleaseRelativeName(&RelativeName);
184 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
185 BaseSetLastNTError(Status);
186 return FALSE;
187 }
188
189 /* Let's try again, without querying attributes */
190 Status = NtOpenFile(&FileHandle,
191 DELETE,
192 &ObjectAttributes,
193 &IoStatusBlock,
194 FILE_SHARE_DELETE |
195 FILE_SHARE_READ |
196 FILE_SHARE_WRITE,
197 FILE_NON_DIRECTORY_FILE |
198 FILE_OPEN_FOR_BACKUP_INTENT |
199 FILE_OPEN_REPARSE_POINT);
200 if (!NT_SUCCESS(Status))
201 {
202 /* This failed too, so bail out */
203 RtlReleaseRelativeName(&RelativeName);
204 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
205 BaseSetLastNTError(Status);
206 return FALSE;
207 }
208 }
209 }
210
211 /* Ready to delete the file, so cleanup temporary data */
212 RtlReleaseRelativeName(&RelativeName);
213 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
214
215 /* Ask for the file to be deleted */
216 FileDispInfo.DeleteFile = TRUE;
217 Status = NtSetInformationFile(FileHandle,
218 &IoStatusBlock,
219 &FileDispInfo,
220 sizeof(FILE_DISPOSITION_INFORMATION),
221 FileDispositionInformation);
222 NtClose(FileHandle);
223 if (!NT_SUCCESS(Status))
224 {
225 /* Deletion failed, tell the caller */
226 BaseSetLastNTError(Status);
227 return FALSE;
228 }
229
230 /* Tell the caller deletion worked */
231 return TRUE;
232 }
233
234 /* EOF */