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
);
61 RecycleBin5File_Destructor(
62 struct RecycleBin5File
*s
)
66 IRecycleBin5_Release(s
->recycleBin
);
70 static ULONG STDMETHODCALLTYPE
71 RecycleBin5File_RecycleBinFile_Release(
72 IN IRecycleBinFile
*This
)
74 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
77 TRACE("(%p)\n", This
);
79 refCount
= InterlockedDecrement((PLONG
)&s
->ref
);
82 RecycleBin5File_Destructor(s
);
87 static HRESULT STDMETHODCALLTYPE
88 RecycleBin5File_RecycleBinFile_GetLastModificationTime(
89 IN IRecycleBinFile
*This
,
90 OUT FILETIME
*pLastModificationTime
)
92 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
97 TRACE("(%p, %p)\n", This
, pLastModificationTime
);
99 dwAttributes
= GetFileAttributesW(s
->FullName
);
100 if (dwAttributes
== INVALID_FILE_ATTRIBUTES
)
101 return HRESULT_FROM_WIN32(GetLastError());
102 if (dwAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
103 hFile
= CreateFileW(s
->FullName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
105 hFile
= CreateFileW(s
->FullName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
106 if (hFile
== INVALID_HANDLE_VALUE
)
107 return HRESULT_FROM_WIN32(GetLastError());
109 if (GetFileTime(hFile
, NULL
, NULL
, pLastModificationTime
))
112 hr
= HRESULT_FROM_WIN32(GetLastError());
117 static HRESULT STDMETHODCALLTYPE
118 RecycleBin5File_RecycleBinFile_GetDeletionTime(
119 IN IRecycleBinFile
*This
,
120 OUT FILETIME
*pDeletionTime
)
122 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
123 TRACE("(%p, %p)\n", This
, pDeletionTime
);
124 *pDeletionTime
= s
->deletedFile
.DeletionTime
;
128 static HRESULT STDMETHODCALLTYPE
129 RecycleBin5File_RecycleBinFile_GetFileSize(
130 IN IRecycleBinFile
*This
,
131 OUT ULARGE_INTEGER
*pFileSize
)
133 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
138 TRACE("(%p, %p)\n", This
, pFileSize
);
140 dwAttributes
= GetFileAttributesW(s
->FullName
);
141 if (dwAttributes
== INVALID_FILE_ATTRIBUTES
)
142 return HRESULT_FROM_WIN32(GetLastError());
143 if (dwAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
145 pFileSize
->QuadPart
= 0;
149 hFile
= CreateFileW(s
->FullName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
150 if (hFile
== INVALID_HANDLE_VALUE
)
151 return HRESULT_FROM_WIN32(GetLastError());
152 pFileSize
->u
.LowPart
= GetFileSize(hFile
, &pFileSize
->u
.HighPart
);
153 if (pFileSize
->u
.LowPart
!= INVALID_FILE_SIZE
)
156 hr
= HRESULT_FROM_WIN32(GetLastError());
161 static HRESULT STDMETHODCALLTYPE
162 RecycleBin5File_RecycleBinFile_GetPhysicalFileSize(
163 IN IRecycleBinFile
*This
,
164 OUT ULARGE_INTEGER
*pPhysicalFileSize
)
166 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
167 TRACE("(%p, %p)\n", This
, pPhysicalFileSize
);
168 pPhysicalFileSize
->u
.HighPart
= 0;
169 pPhysicalFileSize
->u
.LowPart
= s
->deletedFile
.dwPhysicalFileSize
;
173 static HRESULT STDMETHODCALLTYPE
174 RecycleBin5File_RecycleBinFile_GetAttributes(
175 IN IRecycleBinFile
*This
,
176 OUT DWORD
*pAttributes
)
178 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
181 TRACE("(%p, %p)\n", This
, pAttributes
);
183 dwAttributes
= GetFileAttributesW(s
->FullName
);
184 if (dwAttributes
== INVALID_FILE_ATTRIBUTES
)
185 return HRESULT_FROM_WIN32(GetLastError());
187 *pAttributes
= dwAttributes
;
191 static HRESULT STDMETHODCALLTYPE
192 RecycleBin5File_RecycleBinFile_GetFileName(
193 IN IRecycleBinFile
*This
,
194 IN SIZE_T BufferSize
,
195 IN OUT LPWSTR Buffer
,
196 OUT SIZE_T
*RequiredSize
)
198 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
201 TRACE("(%p, %u, %p, %p)\n", This
, BufferSize
, Buffer
, RequiredSize
);
203 dwRequired
= (DWORD
)(wcslen(s
->deletedFile
.FileNameW
) + 1) * sizeof(WCHAR
);
205 *RequiredSize
= dwRequired
;
207 if (BufferSize
== 0 && !Buffer
)
210 if (BufferSize
< dwRequired
)
211 return E_OUTOFMEMORY
;
212 CopyMemory(Buffer
, s
->deletedFile
.FileNameW
, dwRequired
);
216 static HRESULT STDMETHODCALLTYPE
217 RecycleBin5File_RecycleBinFile_Delete(
218 IN IRecycleBinFile
*This
)
220 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
221 TRACE("(%p)\n", This
);
222 return IRecycleBin5_Delete(s
->recycleBin
, s
->FullName
, &s
->deletedFile
);
225 static HRESULT STDMETHODCALLTYPE
226 RecycleBin5File_RecycleBinFile_Restore(
227 IN IRecycleBinFile
*This
)
229 struct RecycleBin5File
*s
= CONTAINING_RECORD(This
, struct RecycleBin5File
, recycleBinFileImpl
);
230 TRACE("(%p)\n", This
);
231 return IRecycleBin5_Restore(s
->recycleBin
, s
->FullName
, &s
->deletedFile
);
234 CONST_VTBL
struct IRecycleBinFileVtbl RecycleBin5FileVtbl
=
236 RecycleBin5File_RecycleBinFile_QueryInterface
,
237 RecycleBin5File_RecycleBinFile_AddRef
,
238 RecycleBin5File_RecycleBinFile_Release
,
239 RecycleBin5File_RecycleBinFile_GetLastModificationTime
,
240 RecycleBin5File_RecycleBinFile_GetDeletionTime
,
241 RecycleBin5File_RecycleBinFile_GetFileSize
,
242 RecycleBin5File_RecycleBinFile_GetPhysicalFileSize
,
243 RecycleBin5File_RecycleBinFile_GetAttributes
,
244 RecycleBin5File_RecycleBinFile_GetFileName
,
245 RecycleBin5File_RecycleBinFile_Delete
,
246 RecycleBin5File_RecycleBinFile_Restore
,
250 RecycleBin5File_Constructor(
251 IN IRecycleBin5
*prb
,
253 IN PDELETED_FILE_RECORD pDeletedFile
,
254 OUT IRecycleBinFile
**ppFile
)
256 struct RecycleBin5File
*s
= NULL
;
263 Extension
= wcsrchr(pDeletedFile
->FileNameW
, '.');
264 if (Extension
< wcsrchr(pDeletedFile
->FileNameW
, '\\'))
266 Needed
= wcslen(Folder
) + 13;
268 Needed
+= wcslen(Extension
);
269 Needed
*= sizeof(WCHAR
);
271 s
= CoTaskMemAlloc(sizeof(struct RecycleBin5File
) + Needed
);
273 return E_OUTOFMEMORY
;
274 ZeroMemory(s
, sizeof(struct RecycleBin5File
) + Needed
);
275 s
->recycleBinFileImpl
.lpVtbl
= &RecycleBin5FileVtbl
;
277 s
->deletedFile
= *pDeletedFile
;
279 IRecycleBin5_AddRef(s
->recycleBin
);
280 *ppFile
= &s
->recycleBinFileImpl
;
281 wsprintfW(s
->FullName
, L
"%s\\D%c%lu%s", Folder
, pDeletedFile
->dwDriveNumber
+ 'a', pDeletedFile
->dwRecordUniqueId
, Extension
);
282 if (GetFileAttributesW(s
->FullName
) == INVALID_FILE_ATTRIBUTES
)
284 RecycleBin5File_Destructor(s
);
291 struct RecycleBin5Enum
294 IRecycleBin5
*recycleBin
;
298 IRecycleBinEnumList recycleBinEnumImpl
;
299 WCHAR szPrefix
[ANY_SIZE
];
302 static HRESULT STDMETHODCALLTYPE
303 RecycleBin5Enum_RecycleBinEnumList_QueryInterface(
304 IN IRecycleBinEnumList
*This
,
306 OUT
void **ppvObject
)
308 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
310 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
315 if (IsEqualIID(riid
, &IID_IUnknown
))
316 *ppvObject
= &s
->recycleBinEnumImpl
;
317 else if (IsEqualIID(riid
, &IID_IRecycleBinEnumList
))
318 *ppvObject
= &s
->recycleBinEnumImpl
;
322 return E_NOINTERFACE
;
325 IUnknown_AddRef(This
);
329 static ULONG STDMETHODCALLTYPE
330 RecycleBin5Enum_RecycleBinEnumList_AddRef(
331 IN IRecycleBinEnumList
*This
)
333 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
334 ULONG refCount
= InterlockedIncrement((PLONG
)&s
->ref
);
335 TRACE("(%p)\n", This
);
340 RecycleBin5Enum_Destructor(
341 struct RecycleBin5Enum
*s
)
345 IRecycleBin5_OnClosing(s
->recycleBin
, &s
->recycleBinEnumImpl
);
346 UnmapViewOfFile(s
->pInfo
);
347 IRecycleBin5_Release(s
->recycleBin
);
351 static ULONG STDMETHODCALLTYPE
352 RecycleBin5Enum_RecycleBinEnumList_Release(
353 IN IRecycleBinEnumList
*This
)
355 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
358 TRACE("(%p)\n", This
);
360 refCount
= InterlockedDecrement((PLONG
)&s
->ref
);
363 RecycleBin5Enum_Destructor(s
);
368 static HRESULT STDMETHODCALLTYPE
369 RecycleBin5Enum_RecycleBinEnumList_Next(
370 IRecycleBinEnumList
*This
,
372 IN OUT IRecycleBinFile
**rgelt
,
373 OUT DWORD
*pceltFetched
)
375 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
376 ULARGE_INTEGER FileSize
;
377 INFO2_HEADER
*pHeader
= s
->pInfo
;
378 DELETED_FILE_RECORD
*pDeletedFile
;
379 DWORD fetched
= 0, i
;
383 TRACE("(%p, %u, %p, %p)\n", This
, celt
, rgelt
, pceltFetched
);
387 if (!pceltFetched
&& celt
> 1)
390 FileSize
.u
.LowPart
= GetFileSize(s
->hInfo
, &FileSize
.u
.HighPart
);
391 if (FileSize
.u
.LowPart
== 0)
392 return HRESULT_FROM_WIN32(GetLastError());
393 dwEntries
= (DWORD
)((FileSize
.QuadPart
- sizeof(INFO2_HEADER
)) / sizeof(DELETED_FILE_RECORD
));
396 pDeletedFile
= (DELETED_FILE_RECORD
*)(pHeader
+ 1) + i
;
397 for (; i
< dwEntries
&& fetched
< celt
; i
++)
399 hr
= RecycleBin5File_Constructor(s
->recycleBin
, s
->szPrefix
, pDeletedFile
, &rgelt
[fetched
]);
407 *pceltFetched
= fetched
;
414 static HRESULT STDMETHODCALLTYPE
415 RecycleBin5Enum_RecycleBinEnumList_Skip(
416 IN IRecycleBinEnumList
*This
,
419 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
420 TRACE("(%p, %u)\n", This
, celt
);
421 s
->dwCurrent
+= celt
;
425 static HRESULT STDMETHODCALLTYPE
426 RecycleBin5Enum_RecycleBinEnumList_Reset(
427 IN IRecycleBinEnumList
*This
)
429 struct RecycleBin5Enum
*s
= CONTAINING_RECORD(This
, struct RecycleBin5Enum
, recycleBinEnumImpl
);
430 TRACE("(%p)\n", This
);
435 CONST_VTBL
struct IRecycleBinEnumListVtbl RecycleBin5EnumVtbl
=
437 RecycleBin5Enum_RecycleBinEnumList_QueryInterface
,
438 RecycleBin5Enum_RecycleBinEnumList_AddRef
,
439 RecycleBin5Enum_RecycleBinEnumList_Release
,
440 RecycleBin5Enum_RecycleBinEnumList_Next
,
441 RecycleBin5Enum_RecycleBinEnumList_Skip
,
442 RecycleBin5Enum_RecycleBinEnumList_Reset
,
446 RecycleBin5Enum_Constructor(
447 IN IRecycleBin5
*prb
,
449 IN HANDLE hInfoMapped
,
451 OUT IUnknown
**ppUnknown
)
453 struct RecycleBin5Enum
*s
= NULL
;
459 Needed
= (wcslen(szPrefix
) + 1) * sizeof(WCHAR
);
461 s
= CoTaskMemAlloc(sizeof(struct RecycleBin5Enum
) + Needed
);
463 return E_OUTOFMEMORY
;
464 ZeroMemory(s
, sizeof(struct RecycleBin5Enum
) + Needed
);
465 s
->recycleBinEnumImpl
.lpVtbl
= &RecycleBin5EnumVtbl
;
468 wcscpy(s
->szPrefix
, szPrefix
);
470 s
->pInfo
= MapViewOfFile(hInfoMapped
, FILE_MAP_READ
, 0, 0, 0);
474 return HRESULT_FROM_WIN32(GetLastError());
476 if (s
->pInfo
->dwVersion
!= 5 || s
->pInfo
->dwRecordSize
!= sizeof(DELETED_FILE_RECORD
))
478 UnmapViewOfFile(s
->pInfo
);
482 IRecycleBin5_AddRef(s
->recycleBin
);
483 *ppUnknown
= (IUnknown
*)&s
->recycleBinEnumImpl
;