2 * PROJECT: Recycle bin management
3 * LICENSE: GPL v2 - See COPYING in the top level directory
4 * FILE: lib/recyclebin/openclose.c
5 * PURPOSE: Public interface
6 * PROGRAMMERS: Copyright 2006 Hervé Poussineau (hpoussin@reactos.org)
9 #include "recyclebin_private.h"
11 typedef struct _ENUMERATE_RECYCLE_BIN_CONTEXT
14 PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback
;
16 } ENUMERATE_RECYCLE_BIN_CONTEXT
, *PENUMERATE_RECYCLE_BIN_CONTEXT
;
19 CloseRecycleBinHandle(
20 IN HANDLE hDeletedFile
)
24 if (!IntCheckDeletedFileHandle(hDeletedFile
))
25 SetLastError(ERROR_INVALID_HANDLE
);
28 PDELETED_FILE_HANDLE file
= (PDELETED_FILE_HANDLE
)hDeletedFile
;
29 ret
= DereferenceHandle(&file
->refCount
);
36 DeleteFileToRecycleBinA(
40 LPWSTR FileNameW
= NULL
;
43 /* Check parameters */
46 SetLastError(ERROR_INVALID_PARAMETER
);
50 len
= MultiByteToWideChar(CP_ACP
, 0, FileName
, -1, NULL
, 0);
53 FileNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
56 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
59 if (MultiByteToWideChar(CP_ACP
, 0, FileName
, -1, FileNameW
, len
) == 0)
62 ret
= DeleteFileToRecycleBinW(FileNameW
);
65 HeapFree(GetProcessHeap(), 0, FileNameW
);
70 DeleteFileToRecycleBinW(
73 LPWSTR FullFileName
= NULL
;
74 DWORD dwBufferLength
= 0;
77 PRECYCLE_BIN bin
= NULL
;
80 /* Check parameters */
83 SetLastError(ERROR_INVALID_PARAMETER
);
87 /* Get full file name */
90 len
= GetFullPathNameW(FileName
, dwBufferLength
, FullFileName
, &lpFilePart
);
93 else if (len
< dwBufferLength
)
95 HeapFree(GetProcessHeap(), 0, FullFileName
);
97 FullFileName
= HeapAlloc(GetProcessHeap(), 0, dwBufferLength
* sizeof(WCHAR
));
100 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
105 if (!lpFilePart
|| dwBufferLength
< 2 || FullFileName
[1] != ':')
107 /* Only a directory name, or not a local file */
108 SetLastError(ERROR_INVALID_NAME
);
111 /* Open recycle bin */
112 bin
= IntReferenceRecycleBin(FullFileName
[0]);
116 if (bin
->Callbacks
.DeleteFile
)
117 ret
= bin
->Callbacks
.DeleteFile(bin
, FullFileName
, lpFilePart
);
119 SetLastError(ERROR_NOT_SUPPORTED
);
122 HeapFree(GetProcessHeap(), 0, FullFileName
);
124 DereferenceHandle(&bin
->refCount
);
132 return EmptyRecycleBinW((WCHAR
)driveLetter
);
137 IN WCHAR driveLetter
)
139 PRECYCLE_BIN bin
= NULL
;
142 /* Open recycle bin */
143 bin
= IntReferenceRecycleBin(driveLetter
);
147 if (bin
->Callbacks
.EmptyRecycleBin
)
148 ret
= bin
->Callbacks
.EmptyRecycleBin(&bin
);
150 SetLastError(ERROR_NOT_SUPPORTED
);
154 DereferenceHandle(&bin
->refCount
);
159 EnumerateRecycleBinA(
161 IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback
,
162 IN PVOID Context OPTIONAL
)
164 return EnumerateRecycleBinW((WCHAR
)driveLetter
, pFnCallback
, Context
);
168 IntCloseDeletedFileHandle(
169 IN PREFCOUNT_DATA pData
)
171 PDELETED_FILE_HANDLE file
;
173 file
= CONTAINING_RECORD(pData
, DELETED_FILE_HANDLE
, refCount
);
174 if (!DereferenceHandle(&file
->bin
->refCount
))
178 HeapFree(GetProcessHeap(), 0, file
);
183 IntEnumerateRecycleBinCallback(
185 IN HANDLE hDeletedFile
)
187 PENUMERATE_RECYCLE_BIN_CONTEXT CallbackContext
= (PENUMERATE_RECYCLE_BIN_CONTEXT
)Context
;
188 PDELETED_FILE_HANDLE DeletedFileHandle
= NULL
;
191 DeletedFileHandle
= HeapAlloc(GetProcessHeap(), 0, sizeof(DELETED_FILE_HANDLE
));
192 if (!DeletedFileHandle
)
194 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
198 ReferenceHandle(&CallbackContext
->bin
->refCount
);
199 InitializeHandle(&DeletedFileHandle
->refCount
, IntCloseDeletedFileHandle
);
200 DeletedFileHandle
->magic
= DELETEDFILE_MAGIC
;
201 DeletedFileHandle
->bin
= CallbackContext
->bin
;
202 DeletedFileHandle
->hDeletedFile
= hDeletedFile
;
204 ret
= CallbackContext
->pFnCallback(CallbackContext
->Context
, DeletedFileHandle
);
209 if (DeletedFileHandle
)
210 DereferenceHandle(&DeletedFileHandle
->refCount
);
216 EnumerateRecycleBinW(
217 IN WCHAR driveLetter
,
218 IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback
,
219 IN PVOID Context OPTIONAL
)
221 PRECYCLE_BIN bin
= NULL
;
224 /* Check parameters */
225 if (pFnCallback
== NULL
)
227 SetLastError(ERROR_INVALID_PARAMETER
);
231 /* Open recycle bin */
232 bin
= IntReferenceRecycleBin(driveLetter
);
236 if (bin
->Callbacks
.EnumerateFiles
)
238 ENUMERATE_RECYCLE_BIN_CONTEXT CallbackContext
;
240 CallbackContext
.bin
= bin
;
241 CallbackContext
.pFnCallback
= pFnCallback
;
242 CallbackContext
.Context
= Context
;
244 ret
= bin
->Callbacks
.EnumerateFiles(bin
, IntEnumerateRecycleBinCallback
, &CallbackContext
);
247 SetLastError(ERROR_NOT_SUPPORTED
);
251 DereferenceHandle(&bin
->refCount
);
256 GetDeletedFileDetailsA(
257 IN HANDLE hDeletedFile
,
259 IN OUT PDELETED_FILE_DETAILS_A FileDetails OPTIONAL
,
260 OUT LPDWORD RequiredSize OPTIONAL
)
262 PDELETED_FILE_DETAILS_W FileDetailsW
= NULL
;
263 DWORD BufferSizeW
= 0;
266 if (BufferSize
>= FIELD_OFFSET(DELETED_FILE_DETAILS_A
, FileName
))
268 BufferSizeW
= FIELD_OFFSET(DELETED_FILE_DETAILS_W
, FileName
)
269 + (BufferSize
- FIELD_OFFSET(DELETED_FILE_DETAILS_A
, FileName
)) * sizeof(WCHAR
);
271 if (FileDetails
&& BufferSizeW
)
273 FileDetailsW
= HeapAlloc(GetProcessHeap(), 0, BufferSizeW
);
276 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
281 ret
= GetDeletedFileDetailsW(hDeletedFile
, BufferSizeW
, FileDetailsW
, RequiredSize
);
287 memcpy(FileDetails
, FileDetailsW
, FIELD_OFFSET(DELETED_FILE_DETAILS_A
, FileName
));
288 if (0 == WideCharToMultiByte(CP_ACP
, 0, FileDetailsW
->FileName
, -1, FileDetails
->FileName
, BufferSize
- FIELD_OFFSET(DELETED_FILE_DETAILS_A
, FileName
), NULL
, NULL
))
294 HeapFree(GetProcessHeap(), 0, FileDetailsW
);
299 GetDeletedFileDetailsW(
300 IN HANDLE hDeletedFile
,
302 IN OUT PDELETED_FILE_DETAILS_W FileDetails OPTIONAL
,
303 OUT LPDWORD RequiredSize OPTIONAL
)
307 if (!IntCheckDeletedFileHandle(hDeletedFile
))
308 SetLastError(ERROR_INVALID_HANDLE
);
311 PDELETED_FILE_HANDLE DeletedFile
= (PDELETED_FILE_HANDLE
)hDeletedFile
;
312 if (DeletedFile
->bin
->Callbacks
.GetDetails
)
313 ret
= DeletedFile
->bin
->Callbacks
.GetDetails(DeletedFile
->bin
, DeletedFile
->hDeletedFile
, BufferSize
, FileDetails
, RequiredSize
);
315 SetLastError(ERROR_NOT_SUPPORTED
);
323 IN HANDLE hDeletedFile
)
327 if (!IntCheckDeletedFileHandle(hDeletedFile
))
328 SetLastError(ERROR_INVALID_HANDLE
);
331 PDELETED_FILE_HANDLE DeletedFile
= (PDELETED_FILE_HANDLE
)hDeletedFile
;
332 if (DeletedFile
->bin
->Callbacks
.RestoreFile
)
333 ret
= DeletedFile
->bin
->Callbacks
.RestoreFile(DeletedFile
->bin
, DeletedFile
->hDeletedFile
);
335 SetLastError(ERROR_NOT_SUPPORTED
);