2 * PROJECT: Recycle bin management
3 * LICENSE: GPL v2 - See COPYING in the top level directory
4 * FILE: lib/recyclebin/recyclebin_v5_enumerator.c
5 * PURPOSE: Enumerates contents of a MS Windows 2000/XP/2003 recyclebin
6 * PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
10 #include "recyclebin_v5.h"
12 WINE_DEFAULT_DEBUG_CHANNEL(recyclebin
);
14 struct RecycleBin5File
17 IRecycleBin5
*recycleBin
;
18 DELETED_FILE_RECORD deletedFile
;
19 IRecycleBinFile recycleBinFileImpl
;
20 WCHAR FullName
[ANY_SIZE
];
23 static HRESULT STDMETHODCALLTYPE
24 RecycleBin5File_RecycleBinFile_QueryInterface(
25 IN IRecycleBinFile
*This
,
29 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
31 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
36 if (IsEqualIID(riid
, &IID_IUnknown
))
37 *ppvObject
= &s
->recycleBinFileImpl
;
38 else if (IsEqualIID(riid
, &IID_IRecycleBinFile
))
39 *ppvObject
= &s
->recycleBinFileImpl
;
46 IUnknown_AddRef(This
);
50 static ULONG STDMETHODCALLTYPE
51 RecycleBin5File_RecycleBinFile_AddRef(
52 IN IRecycleBinFile
*This
)
54 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
55 ULONG refCount
= InterlockedIncrement((PLONG
)&s
->ref
);
56 TRACE("(%p)\n", This
);
60 static ULONG STDMETHODCALLTYPE
61 RecycleBin5File_RecycleBinFile_Release(
62 IN IRecycleBinFile
*This
)
64 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
67 TRACE("(%p)\n", This
);
69 refCount
= InterlockedDecrement((PLONG
)&s
->ref
);
73 IRecycleBin5_Release(s
->recycleBin
);
80 static HRESULT STDMETHODCALLTYPE
81 RecycleBin5File_RecycleBinFile_GetLastModificationTime(
82 IN IRecycleBinFile
*This
,
83 OUT FILETIME
*pLastModificationTime
)
85 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
90 TRACE("(%p, %p)\n", This
, pLastModificationTime
);
92 dwAttributes
= GetFileAttributesW(s
->FullName
);
93 if (dwAttributes
== INVALID_FILE_ATTRIBUTES
)
94 return HRESULT_FROM_WIN32(GetLastError());
95 if (dwAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
96 hFile
= CreateFileW(s
->FullName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
98 hFile
= CreateFileW(s
->FullName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
99 if (hFile
== INVALID_HANDLE_VALUE
)
100 return HRESULT_FROM_WIN32(GetLastError());
102 if (GetFileTime(hFile
, NULL
, NULL
, pLastModificationTime
))
105 hr
= HRESULT_FROM_WIN32(GetLastError());
110 static HRESULT STDMETHODCALLTYPE
111 RecycleBin5File_RecycleBinFile_GetDeletionTime(
112 IN IRecycleBinFile
*This
,
113 OUT FILETIME
*pDeletionTime
)
115 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
116 TRACE("(%p, %p)\n", This
, pDeletionTime
);
117 *pDeletionTime
= s
->deletedFile
.DeletionTime
;
121 static HRESULT STDMETHODCALLTYPE
122 RecycleBin5File_RecycleBinFile_GetFileSize(
123 IN IRecycleBinFile
*This
,
124 OUT ULARGE_INTEGER
*pFileSize
)
126 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
131 TRACE("(%p, %p)\n", This
, pFileSize
);
133 dwAttributes
= GetFileAttributesW(s
->FullName
);
134 if (dwAttributes
== INVALID_FILE_ATTRIBUTES
)
135 return HRESULT_FROM_WIN32(GetLastError());
136 if (dwAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
138 pFileSize
->QuadPart
= 0;
142 hFile
= CreateFileW(s
->FullName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
143 if (hFile
== INVALID_HANDLE_VALUE
)
144 return HRESULT_FROM_WIN32(GetLastError());
145 pFileSize
->u
.LowPart
= GetFileSize(hFile
, &pFileSize
->u
.HighPart
);
146 if (pFileSize
->u
.LowPart
!= INVALID_FILE_SIZE
)
149 hr
= HRESULT_FROM_WIN32(GetLastError());
154 static HRESULT STDMETHODCALLTYPE
155 RecycleBin5File_RecycleBinFile_GetPhysicalFileSize(
156 IN IRecycleBinFile
*This
,
157 OUT ULARGE_INTEGER
*pPhysicalFileSize
)
159 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
160 TRACE("(%p, %p)\n", This
, pPhysicalFileSize
);
161 pPhysicalFileSize
->u
.HighPart
= 0;
162 pPhysicalFileSize
->u
.LowPart
= s
->deletedFile
.dwPhysicalFileSize
;
166 static HRESULT STDMETHODCALLTYPE
167 RecycleBin5File_RecycleBinFile_GetAttributes(
168 IN IRecycleBinFile
*This
,
169 OUT DWORD
*pAttributes
)
171 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
174 TRACE("(%p, %p)\n", This
, pAttributes
);
176 dwAttributes
= GetFileAttributesW(s
->FullName
);
177 if (dwAttributes
== INVALID_FILE_ATTRIBUTES
)
178 return HRESULT_FROM_WIN32(GetLastError());
180 *pAttributes
= dwAttributes
;
184 static HRESULT STDMETHODCALLTYPE
185 RecycleBin5File_RecycleBinFile_GetFileName(
186 IN IRecycleBinFile
*This
,
188 IN OUT LPWSTR Buffer
,
189 OUT DWORD
*RequiredSize
)
191 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
194 TRACE("(%p, %u, %p, %p)\n", This
, BufferSize
, Buffer
, RequiredSize
);
196 dwRequired
= (DWORD
)(wcslen(s
->deletedFile
.FileNameW
) + 1) * sizeof(WCHAR
);
198 *RequiredSize
= dwRequired
;
200 if (BufferSize
== 0 && !Buffer
)
203 if (BufferSize
< dwRequired
)
204 return E_OUTOFMEMORY
;
205 CopyMemory(Buffer
, s
->deletedFile
.FileNameW
, dwRequired
);
209 static HRESULT STDMETHODCALLTYPE
210 RecycleBin5File_RecycleBinFile_Delete(
211 IN IRecycleBinFile
*This
)
213 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
214 TRACE("(%p)\n", This
);
215 return IRecycleBin5_Delete(s
->recycleBin
, s
->FullName
, &s
->deletedFile
);
218 static HRESULT STDMETHODCALLTYPE
219 RecycleBin5File_RecycleBinFile_Restore(
220 IN IRecycleBinFile
*This
)
222 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
223 TRACE("(%p)\n", This
);
224 return IRecycleBin5_Restore(s
->recycleBin
, s
->FullName
, &s
->deletedFile
);
227 CONST_VTBL
struct IRecycleBinFileVtbl RecycleBin5FileVtbl
=
229 RecycleBin5File_RecycleBinFile_QueryInterface
,
230 RecycleBin5File_RecycleBinFile_AddRef
,
231 RecycleBin5File_RecycleBinFile_Release
,
232 RecycleBin5File_RecycleBinFile_GetLastModificationTime
,
233 RecycleBin5File_RecycleBinFile_GetDeletionTime
,
234 RecycleBin5File_RecycleBinFile_GetFileSize
,
235 RecycleBin5File_RecycleBinFile_GetPhysicalFileSize
,
236 RecycleBin5File_RecycleBinFile_GetAttributes
,
237 RecycleBin5File_RecycleBinFile_GetFileName
,
238 RecycleBin5File_RecycleBinFile_Delete
,
239 RecycleBin5File_RecycleBinFile_Restore
,
243 RecycleBin5_File_Constructor(
244 IN IRecycleBin5
*prb
,
246 IN PDELETED_FILE_RECORD pDeletedFile
,
247 OUT IRecycleBinFile
**ppFile
)
249 struct RecycleBin5File
*s
= NULL
;
256 Extension
= wcsrchr(pDeletedFile
->FileNameW
, '.');
257 if (Extension
< wcsrchr(pDeletedFile
->FileNameW
, '\\'))
259 Needed
= wcslen(Folder
) + 13;
261 Needed
+= wcslen(Extension
);
262 Needed
*= sizeof(WCHAR
);
264 s
= CoTaskMemAlloc(sizeof(struct RecycleBin5File
) + Needed
);
266 return E_OUTOFMEMORY
;
267 ZeroMemory(s
, sizeof(struct RecycleBin5File
) + Needed
);
268 s
->recycleBinFileImpl
.lpVtbl
= &RecycleBin5FileVtbl
;
270 s
->deletedFile
= *pDeletedFile
;
272 IRecycleBin5_AddRef(s
->recycleBin
);
273 *ppFile
= &s
->recycleBinFileImpl
;
274 wsprintfW(s
->FullName
, L
"%s\\D%c%lu%s", Folder
, pDeletedFile
->dwDriveNumber
+ 'a', pDeletedFile
->dwRecordUniqueId
, Extension
);
279 struct RecycleBin5Enum
282 IRecycleBin5
*recycleBin
;
286 IRecycleBinEnumList recycleBinEnumImpl
;
287 WCHAR szPrefix
[ANY_SIZE
];
290 static HRESULT STDMETHODCALLTYPE
291 RecycleBin5Enum_RecycleBinEnumList_QueryInterface(
292 IN IRecycleBinEnumList
*This
,
294 OUT
void **ppvObject
)
296 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
298 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
303 if (IsEqualIID(riid
, &IID_IUnknown
))
304 *ppvObject
= &s
->recycleBinEnumImpl
;
305 else if (IsEqualIID(riid
, &IID_IRecycleBinEnumList
))
306 *ppvObject
= &s
->recycleBinEnumImpl
;
310 return E_NOINTERFACE
;
313 IUnknown_AddRef(This
);
317 static ULONG STDMETHODCALLTYPE
318 RecycleBin5Enum_RecycleBinEnumList_AddRef(
319 IN IRecycleBinEnumList
*This
)
321 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
322 ULONG refCount
= InterlockedIncrement((PLONG
)&s
->ref
);
323 TRACE("(%p)\n", This
);
327 static ULONG STDMETHODCALLTYPE
328 RecycleBin5Enum_RecycleBinEnumList_Release(
329 IN IRecycleBinEnumList
*This
)
331 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
334 TRACE("(%p)\n", This
);
336 refCount
= InterlockedDecrement((PLONG
)&s
->ref
);
340 IRecycleBin5_OnClosing(s
->recycleBin
, This
);
341 UnmapViewOfFile(s
->pInfo
);
342 IRecycleBin5_Release(s
->recycleBin
);
349 static HRESULT STDMETHODCALLTYPE
350 RecycleBin5Enum_RecycleBinEnumList_Next(
351 IRecycleBinEnumList
*This
,
353 IN OUT IRecycleBinFile
**rgelt
,
354 OUT DWORD
*pceltFetched
)
356 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
357 ULARGE_INTEGER FileSize
;
358 INFO2_HEADER
*pHeader
= s
->pInfo
;
359 DELETED_FILE_RECORD
*pDeletedFile
;
360 DWORD fetched
= 0, i
;
364 TRACE("(%p, %u, %p, %p)\n", This
, celt
, rgelt
, pceltFetched
);
368 if (!pceltFetched
&& celt
> 1)
371 FileSize
.u
.LowPart
= GetFileSize(s
->hInfo
, &FileSize
.u
.HighPart
);
372 if (FileSize
.u
.LowPart
== 0)
373 return HRESULT_FROM_WIN32(GetLastError());
374 dwEntries
= (DWORD
)((FileSize
.QuadPart
- sizeof(INFO2_HEADER
)) / sizeof(DELETED_FILE_RECORD
));
377 pDeletedFile
= (DELETED_FILE_RECORD
*)(pHeader
+ 1) + i
;
378 for (; i
< dwEntries
&& fetched
< celt
; i
++)
380 hr
= RecycleBin5_File_Constructor(s
->recycleBin
, s
->szPrefix
, pDeletedFile
, &rgelt
[fetched
]);
383 for (i
= 0; i
< fetched
; i
++)
384 IRecycleBinFile_Release(rgelt
[i
]);
393 *pceltFetched
= fetched
;
400 static HRESULT STDMETHODCALLTYPE
401 RecycleBin5Enum_RecycleBinEnumList_Skip(
402 IN IRecycleBinEnumList
*This
,
405 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
406 TRACE("(%p, %u)\n", This
, celt
);
407 s
->dwCurrent
+= celt
;
411 static HRESULT STDMETHODCALLTYPE
412 RecycleBin5Enum_RecycleBinEnumList_Reset(
413 IN IRecycleBinEnumList
*This
)
415 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
416 TRACE("(%p)\n", This
);
421 CONST_VTBL
struct IRecycleBinEnumListVtbl RecycleBin5EnumVtbl
=
423 RecycleBin5Enum_RecycleBinEnumList_QueryInterface
,
424 RecycleBin5Enum_RecycleBinEnumList_AddRef
,
425 RecycleBin5Enum_RecycleBinEnumList_Release
,
426 RecycleBin5Enum_RecycleBinEnumList_Next
,
427 RecycleBin5Enum_RecycleBinEnumList_Skip
,
428 RecycleBin5Enum_RecycleBinEnumList_Reset
,
432 RecycleBin5_Enumerator_Constructor(
433 IN IRecycleBin5
*prb
,
435 IN HANDLE hInfoMapped
,
437 OUT IUnknown
**ppUnknown
)
439 struct RecycleBin5Enum
*s
= NULL
;
445 Needed
= (wcslen(szPrefix
) + 1) * sizeof(WCHAR
);
447 s
= CoTaskMemAlloc(sizeof(struct RecycleBin5Enum
) + Needed
);
449 return E_OUTOFMEMORY
;
450 ZeroMemory(s
, sizeof(struct RecycleBin5Enum
) + Needed
);
451 s
->recycleBinEnumImpl
.lpVtbl
= &RecycleBin5EnumVtbl
;
454 wcscpy(s
->szPrefix
, szPrefix
);
456 s
->pInfo
= MapViewOfFile(hInfoMapped
, FILE_MAP_READ
, 0, 0, 0);
460 return HRESULT_FROM_WIN32(GetLastError());
462 if (s
->pInfo
->dwVersion
!= 5 || s
->pInfo
->dwRecordSize
!= sizeof(DELETED_FILE_RECORD
))
464 UnmapViewOfFile(s
->pInfo
);
468 IRecycleBin5_AddRef(s
->recycleBin
);
469 *ppUnknown
= (IUnknown
*)&s
->recycleBinEnumImpl
;