1 /*
2 * PROJECT: Recycle bin management
3 * LICENSE: GPL v2 - See COPYING in the top level directory
4 * FILE: lib/recyclebin/recyclebin.c
5 * PURPOSE: Public interface
6 * PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
7 */
8
9 #include "recyclebin_private.h"
10
11 BOOL WINAPI
CloseRecycleBinHandle(IN HDELFILE hDeletedFile)12 CloseRecycleBinHandle(
13 IN HDELFILE hDeletedFile)
14 {
15 IRecycleBinFile *rbf = IRecycleBinFileFromHDELFILE(hDeletedFile);
16 HRESULT hr;
17
18 TRACE("(%p)\n", hDeletedFile);
19
20 hr = IRecycleBinFile_Release(rbf);
21 if (SUCCEEDED(hr))
22 return TRUE;
23 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
24 SetLastError(HRESULT_CODE(hr));
25 else
26 SetLastError(ERROR_GEN_FAILURE);
27 return FALSE;
28 }
29
30 BOOL WINAPI
DeleteFileToRecycleBinA(IN LPCSTR FileName)31 DeleteFileToRecycleBinA(
32 IN LPCSTR FileName)
33 {
34 int len;
35 LPWSTR FileNameW = NULL;
36 BOOL ret = FALSE;
37
38 TRACE("(%s)\n", debugstr_a(FileName));
39
40 /* Check parameters */
41 if (FileName == NULL)
42 {
43 SetLastError(ERROR_INVALID_PARAMETER);
44 goto cleanup;
45 }
46
47 len = MultiByteToWideChar(CP_ACP, 0, FileName, -1, NULL, 0);
48 if (len == 0)
49 goto cleanup;
50 FileNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
51 if (!FileNameW)
52 {
53 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
54 goto cleanup;
55 }
56 if (MultiByteToWideChar(CP_ACP, 0, FileName, -1, FileNameW, len) == 0)
57 goto cleanup;
58
59 ret = DeleteFileToRecycleBinW(FileNameW);
60
61 cleanup:
62 HeapFree(GetProcessHeap(), 0, FileNameW);
63 return ret;
64 }
65
66 BOOL WINAPI
DeleteFileToRecycleBinW(IN LPCWSTR FileName)67 DeleteFileToRecycleBinW(
68 IN LPCWSTR FileName)
69 {
70 IRecycleBin *prb;
71 HRESULT hr;
72
73 TRACE("(%s)\n", debugstr_w(FileName));
74
75 hr = GetDefaultRecycleBin(NULL, &prb);
76 if (!SUCCEEDED(hr))
77 goto cleanup;
78
79 hr = IRecycleBin_DeleteFile(prb, FileName);
80 IRecycleBin_Release(prb);
81
82 cleanup:
83 if (SUCCEEDED(hr))
84 return TRUE;
85 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
86 SetLastError(HRESULT_CODE(hr));
87 else
88 SetLastError(ERROR_GEN_FAILURE);
89 return FALSE;
90 }
91
92 BOOL WINAPI
DeleteFileInRecycleBin(IN HDELFILE hDeletedFile)93 DeleteFileInRecycleBin(
94 IN HDELFILE hDeletedFile)
95 {
96 IRecycleBinFile *rbf = (IRecycleBinFile *)hDeletedFile;
97 HRESULT hr;
98
99 TRACE("(%p)\n", hDeletedFile);
100
101 hr = IRecycleBinFile_Delete(rbf);
102
103 if (SUCCEEDED(hr))
104 return TRUE;
105 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
106 SetLastError(HRESULT_CODE(hr));
107 else
108 SetLastError(ERROR_GEN_FAILURE);
109 return FALSE;
110 }
111
112 BOOL WINAPI
EmptyRecycleBinA(IN LPCSTR pszRoot OPTIONAL)113 EmptyRecycleBinA(
114 IN LPCSTR pszRoot OPTIONAL)
115 {
116 int len;
117 LPWSTR szRootW = NULL;
118 BOOL ret = FALSE;
119
120 TRACE("(%s)\n", debugstr_a(pszRoot));
121
122 if (pszRoot)
123 {
124 len = MultiByteToWideChar(CP_ACP, 0, pszRoot, -1, NULL, 0);
125 if (len == 0)
126 goto cleanup;
127 szRootW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
128 if (!szRootW)
129 {
130 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
131 goto cleanup;
132 }
133 if (MultiByteToWideChar(CP_ACP, 0, pszRoot, -1, szRootW, len) == 0)
134 goto cleanup;
135 }
136
137 ret = EmptyRecycleBinW(szRootW);
138
139 cleanup:
140 HeapFree(GetProcessHeap(), 0, szRootW);
141 return ret;
142 }
143
144 BOOL WINAPI
EmptyRecycleBinW(IN LPCWSTR pszRoot OPTIONAL)145 EmptyRecycleBinW(
146 IN LPCWSTR pszRoot OPTIONAL)
147 {
148 IRecycleBin *prb;
149 HRESULT hr;
150
151 TRACE("(%s)\n", debugstr_w(pszRoot));
152
153 hr = GetDefaultRecycleBin(pszRoot, &prb);
154 if (!SUCCEEDED(hr))
155 goto cleanup;
156
157 hr = IRecycleBin_EmptyRecycleBin(prb);
158 IRecycleBin_Release(prb);
159
160 cleanup:
161 if (SUCCEEDED(hr))
162 return TRUE;
163 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
164 SetLastError(HRESULT_CODE(hr));
165 else
166 SetLastError(ERROR_GEN_FAILURE);
167 return FALSE;
168 }
169
170 BOOL WINAPI
EnumerateRecycleBinA(IN LPCSTR pszRoot OPTIONAL,IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,IN PVOID Context OPTIONAL)171 EnumerateRecycleBinA(
172 IN LPCSTR pszRoot OPTIONAL,
173 IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,
174 IN PVOID Context OPTIONAL)
175 {
176 int len;
177 LPWSTR szRootW = NULL;
178 BOOL ret = FALSE;
179
180 TRACE("(%s, %p, %p)\n", debugstr_a(pszRoot), pFnCallback, Context);
181
182 if (pszRoot)
183 {
184 len = MultiByteToWideChar(CP_ACP, 0, pszRoot, -1, NULL, 0);
185 if (len == 0)
186 goto cleanup;
187 szRootW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
188 if (!szRootW)
189 {
190 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
191 goto cleanup;
192 }
193 if (MultiByteToWideChar(CP_ACP, 0, pszRoot, -1, szRootW, len) == 0)
194 goto cleanup;
195 }
196
197 ret = EnumerateRecycleBinW(szRootW, pFnCallback, Context);
198
199 cleanup:
200 HeapFree(GetProcessHeap(), 0, szRootW);
201 return ret;
202 }
203
204 BOOL WINAPI
EnumerateRecycleBinW(IN LPCWSTR pszRoot OPTIONAL,IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,IN PVOID Context OPTIONAL)205 EnumerateRecycleBinW(
206 IN LPCWSTR pszRoot OPTIONAL,
207 IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,
208 IN PVOID Context OPTIONAL)
209 {
210 IRecycleBin *prb = NULL;
211 IRecycleBinEnumList *prbel = NULL;
212 IRecycleBinFile *prbf;
213 HRESULT hr;
214
215 TRACE("(%s, %p, %p)\n", debugstr_w(pszRoot), pFnCallback, Context);
216
217 hr = GetDefaultRecycleBin(NULL, &prb);
218 if (!SUCCEEDED(hr))
219 goto cleanup;
220
221 hr = IRecycleBin_EnumObjects(prb, &prbel);
222 if (!SUCCEEDED(hr))
223 goto cleanup;
224 while (TRUE)
225 {
226 hr = IRecycleBinEnumList_Next(prbel, 1, &prbf, NULL);
227 if (hr == S_FALSE)
228 {
229 hr = S_OK;
230 goto cleanup;
231 }
232 else if (!SUCCEEDED(hr))
233 goto cleanup;
234 if (!pFnCallback(Context, (HDELFILE)prbf))
235 {
236 UINT error = GetLastError();
237 hr = HRESULT_FROM_WIN32(error);
238 goto cleanup;
239 }
240 }
241
242 cleanup:
243 if (prb)
244 IRecycleBin_Release(prb);
245 if (prbel)
246 IRecycleBinEnumList_Release(prbel);
247 if (SUCCEEDED(hr))
248 return TRUE;
249 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
250 SetLastError(HRESULT_CODE(hr));
251 else
252 SetLastError(ERROR_GEN_FAILURE);
253 return FALSE;
254 }
255
256 typedef struct _BBENUMFILECONTEXT
257 {
258 const RECYCLEBINFILEIDENTITY *pFI;
259 HDELFILE hDelFile;
260 } BBENUMFILECONTEXT;
261
262 static BOOL CALLBACK
GetRecycleBinFileHandleCallback(IN PVOID Context,IN HDELFILE hDeletedFile)263 GetRecycleBinFileHandleCallback(IN PVOID Context, IN HDELFILE hDeletedFile)
264 {
265 BBENUMFILECONTEXT *pCtx = (BBENUMFILECONTEXT*)Context;
266 IRecycleBinFile *pRBF = IRecycleBinFileFromHDELFILE(hDeletedFile);
267 if (IRecycleBinFile_IsEqualIdentity(pRBF, pCtx->pFI) == S_OK)
268 {
269 pCtx->hDelFile = hDeletedFile;
270 return FALSE;
271 }
272 CloseRecycleBinHandle(hDeletedFile);
273 return TRUE;
274 }
275
276 EXTERN_C HDELFILE
GetRecycleBinFileHandle(IN LPCWSTR pszRoot OPTIONAL,IN const RECYCLEBINFILEIDENTITY * pFI)277 GetRecycleBinFileHandle(
278 IN LPCWSTR pszRoot OPTIONAL,
279 IN const RECYCLEBINFILEIDENTITY *pFI)
280 {
281 BBENUMFILECONTEXT context = { pFI, NULL };
282 EnumerateRecycleBinW(pszRoot, GetRecycleBinFileHandleCallback, &context);
283 return context.hDelFile;
284 }
285
286 BOOL WINAPI
RestoreFileFromRecycleBin(IN HDELFILE hDeletedFile)287 RestoreFileFromRecycleBin(
288 IN HDELFILE hDeletedFile)
289 {
290 IRecycleBinFile *rbf = (IRecycleBinFile *)hDeletedFile;
291 HRESULT hr;
292
293 TRACE("(%p)\n", hDeletedFile);
294
295 hr = IRecycleBinFile_Restore(rbf);
296 if (SUCCEEDED(hr))
297 return TRUE;
298 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
299 SetLastError(HRESULT_CODE(hr));
300 else
301 SetLastError(ERROR_GEN_FAILURE);
302 return FALSE;
303 }
304
305 EXTERN_C HRESULT
GetDefaultRecycleBin(IN LPCWSTR pszVolume OPTIONAL,OUT IRecycleBin ** pprb)306 GetDefaultRecycleBin(
307 IN LPCWSTR pszVolume OPTIONAL,
308 OUT IRecycleBin **pprb)
309 {
310 IUnknown *pUnk;
311 HRESULT hr;
312
313 TRACE("(%s, %p)\n", debugstr_w(pszVolume), pprb);
314
315 if (!pprb)
316 return E_POINTER;
317
318 if (!pszVolume)
319 hr = RecycleBinGeneric_Constructor(&pUnk);
320 else
321 {
322 /* FIXME: do a better validation! */
323 if (wcslen(pszVolume) != 3 || pszVolume[1] != ':' || pszVolume[2] != '\\')
324 return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
325
326 /* For now, only support this type of recycle bins... */
327 hr = RecycleBin5_Constructor(pszVolume, &pUnk);
328 }
329 if (!SUCCEEDED(hr))
330 return hr;
331 hr = IUnknown_QueryInterface(pUnk, &IID_IRecycleBin, (void **)pprb);
332 IUnknown_Release(pUnk);
333 return hr;
334 }
335
336 EXTERN_C HRESULT
GetRecycleBinPathFromDriveNumber(UINT Drive,LPWSTR Path)337 GetRecycleBinPathFromDriveNumber(UINT Drive, LPWSTR Path)
338 {
339 const WCHAR volume[] = { LOWORD('A' + Drive), ':', '\\', '\0' };
340 IRecycleBin *pRB;
341 HRESULT hr = GetDefaultRecycleBin(volume, &pRB);
342 if (SUCCEEDED(hr))
343 {
344 hr = IRecycleBin_GetDirectory(pRB, Path);
345 IRecycleBin_Release(pRB);
346 }
347 return hr;
348 }
349