Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrecyclebin_v5_enumerator.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: Recycle bin management 00003 * LICENSE: GPL v2 - See COPYING in the top level directory 00004 * FILE: lib/recyclebin/recyclebin_v5_enumerator.c 00005 * PURPOSE: Enumerates contents of a MS Windows 2000/XP/2003 recyclebin 00006 * PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org) 00007 */ 00008 00009 #define COBJMACROS 00010 #include "recyclebin_v5.h" 00011 00012 WINE_DEFAULT_DEBUG_CHANNEL(recyclebin); 00013 00014 struct RecycleBin5File 00015 { 00016 ULONG ref; 00017 IRecycleBin5 *recycleBin; 00018 DELETED_FILE_RECORD deletedFile; 00019 IRecycleBinFile recycleBinFileImpl; 00020 WCHAR FullName[ANY_SIZE]; 00021 }; 00022 00023 static HRESULT STDMETHODCALLTYPE 00024 RecycleBin5File_RecycleBinFile_QueryInterface( 00025 IN IRecycleBinFile *This, 00026 IN REFIID riid, 00027 OUT void **ppvObject) 00028 { 00029 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00030 00031 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject); 00032 00033 if (!ppvObject) 00034 return E_POINTER; 00035 00036 if (IsEqualIID(riid, &IID_IUnknown)) 00037 *ppvObject = &s->recycleBinFileImpl; 00038 else if (IsEqualIID(riid, &IID_IRecycleBinFile)) 00039 *ppvObject = &s->recycleBinFileImpl; 00040 else 00041 { 00042 *ppvObject = NULL; 00043 return E_NOINTERFACE; 00044 } 00045 00046 IUnknown_AddRef(This); 00047 return S_OK; 00048 } 00049 00050 static ULONG STDMETHODCALLTYPE 00051 RecycleBin5File_RecycleBinFile_AddRef( 00052 IN IRecycleBinFile *This) 00053 { 00054 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00055 ULONG refCount = InterlockedIncrement((PLONG)&s->ref); 00056 TRACE("(%p)\n", This); 00057 return refCount; 00058 } 00059 00060 static VOID 00061 RecycleBin5File_Destructor( 00062 struct RecycleBin5File *s) 00063 { 00064 TRACE("(%p)\n", s); 00065 00066 IRecycleBin5_Release(s->recycleBin); 00067 CoTaskMemFree(s); 00068 } 00069 00070 static ULONG STDMETHODCALLTYPE 00071 RecycleBin5File_RecycleBinFile_Release( 00072 IN IRecycleBinFile *This) 00073 { 00074 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00075 ULONG refCount; 00076 00077 TRACE("(%p)\n", This); 00078 00079 refCount = InterlockedDecrement((PLONG)&s->ref); 00080 00081 if (refCount == 0) 00082 RecycleBin5File_Destructor(s); 00083 00084 return refCount; 00085 } 00086 00087 static HRESULT STDMETHODCALLTYPE 00088 RecycleBin5File_RecycleBinFile_GetLastModificationTime( 00089 IN IRecycleBinFile *This, 00090 OUT FILETIME *pLastModificationTime) 00091 { 00092 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00093 HRESULT hr; 00094 DWORD dwAttributes; 00095 HANDLE hFile; 00096 00097 TRACE("(%p, %p)\n", This, pLastModificationTime); 00098 00099 dwAttributes = GetFileAttributesW(s->FullName); 00100 if (dwAttributes == INVALID_FILE_ATTRIBUTES) 00101 return HRESULT_FROM_WIN32(GetLastError()); 00102 if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) 00103 hFile = CreateFileW(s->FullName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 00104 else 00105 hFile = CreateFileW(s->FullName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 00106 if (hFile == INVALID_HANDLE_VALUE) 00107 return HRESULT_FROM_WIN32(GetLastError()); 00108 00109 if (GetFileTime(hFile, NULL, NULL, pLastModificationTime)) 00110 hr = S_OK; 00111 else 00112 hr = HRESULT_FROM_WIN32(GetLastError()); 00113 CloseHandle(hFile); 00114 return hr; 00115 } 00116 00117 static HRESULT STDMETHODCALLTYPE 00118 RecycleBin5File_RecycleBinFile_GetDeletionTime( 00119 IN IRecycleBinFile *This, 00120 OUT FILETIME *pDeletionTime) 00121 { 00122 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00123 TRACE("(%p, %p)\n", This, pDeletionTime); 00124 *pDeletionTime = s->deletedFile.DeletionTime; 00125 return S_OK; 00126 } 00127 00128 static HRESULT STDMETHODCALLTYPE 00129 RecycleBin5File_RecycleBinFile_GetFileSize( 00130 IN IRecycleBinFile *This, 00131 OUT ULARGE_INTEGER *pFileSize) 00132 { 00133 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00134 HRESULT hr; 00135 DWORD dwAttributes; 00136 HANDLE hFile; 00137 00138 TRACE("(%p, %p)\n", This, pFileSize); 00139 00140 dwAttributes = GetFileAttributesW(s->FullName); 00141 if (dwAttributes == INVALID_FILE_ATTRIBUTES) 00142 return HRESULT_FROM_WIN32(GetLastError()); 00143 if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) 00144 { 00145 pFileSize->QuadPart = 0; 00146 return S_OK; 00147 } 00148 00149 hFile = CreateFileW(s->FullName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 00150 if (hFile == INVALID_HANDLE_VALUE) 00151 return HRESULT_FROM_WIN32(GetLastError()); 00152 pFileSize->u.LowPart = GetFileSize(hFile, &pFileSize->u.HighPart); 00153 if (pFileSize->u.LowPart != INVALID_FILE_SIZE) 00154 hr = S_OK; 00155 else 00156 hr = HRESULT_FROM_WIN32(GetLastError()); 00157 CloseHandle(hFile); 00158 return hr; 00159 } 00160 00161 static HRESULT STDMETHODCALLTYPE 00162 RecycleBin5File_RecycleBinFile_GetPhysicalFileSize( 00163 IN IRecycleBinFile *This, 00164 OUT ULARGE_INTEGER *pPhysicalFileSize) 00165 { 00166 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00167 TRACE("(%p, %p)\n", This, pPhysicalFileSize); 00168 pPhysicalFileSize->u.HighPart = 0; 00169 pPhysicalFileSize->u.LowPart = s->deletedFile.dwPhysicalFileSize; 00170 return S_OK; 00171 } 00172 00173 static HRESULT STDMETHODCALLTYPE 00174 RecycleBin5File_RecycleBinFile_GetAttributes( 00175 IN IRecycleBinFile *This, 00176 OUT DWORD *pAttributes) 00177 { 00178 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00179 DWORD dwAttributes; 00180 00181 TRACE("(%p, %p)\n", This, pAttributes); 00182 00183 dwAttributes = GetFileAttributesW(s->FullName); 00184 if (dwAttributes == INVALID_FILE_ATTRIBUTES) 00185 return HRESULT_FROM_WIN32(GetLastError()); 00186 00187 *pAttributes = dwAttributes; 00188 return S_OK; 00189 } 00190 00191 static HRESULT STDMETHODCALLTYPE 00192 RecycleBin5File_RecycleBinFile_GetFileName( 00193 IN IRecycleBinFile *This, 00194 IN SIZE_T BufferSize, 00195 IN OUT LPWSTR Buffer, 00196 OUT SIZE_T *RequiredSize) 00197 { 00198 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00199 DWORD dwRequired; 00200 00201 TRACE("(%p, %u, %p, %p)\n", This, BufferSize, Buffer, RequiredSize); 00202 00203 dwRequired = (DWORD)(wcslen(s->deletedFile.FileNameW) + 1) * sizeof(WCHAR); 00204 if (RequiredSize) 00205 *RequiredSize = dwRequired; 00206 00207 if (BufferSize == 0 && !Buffer) 00208 return S_OK; 00209 00210 if (BufferSize < dwRequired) 00211 return E_OUTOFMEMORY; 00212 CopyMemory(Buffer, s->deletedFile.FileNameW, dwRequired); 00213 return S_OK; 00214 } 00215 00216 static HRESULT STDMETHODCALLTYPE 00217 RecycleBin5File_RecycleBinFile_Delete( 00218 IN IRecycleBinFile *This) 00219 { 00220 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00221 TRACE("(%p)\n", This); 00222 return IRecycleBin5_Delete(s->recycleBin, s->FullName, &s->deletedFile); 00223 } 00224 00225 static HRESULT STDMETHODCALLTYPE 00226 RecycleBin5File_RecycleBinFile_Restore( 00227 IN IRecycleBinFile *This) 00228 { 00229 struct RecycleBin5File *s = CONTAINING_RECORD(This, struct RecycleBin5File, recycleBinFileImpl); 00230 TRACE("(%p)\n", This); 00231 return IRecycleBin5_Restore(s->recycleBin, s->FullName, &s->deletedFile); 00232 } 00233 00234 CONST_VTBL struct IRecycleBinFileVtbl RecycleBin5FileVtbl = 00235 { 00236 RecycleBin5File_RecycleBinFile_QueryInterface, 00237 RecycleBin5File_RecycleBinFile_AddRef, 00238 RecycleBin5File_RecycleBinFile_Release, 00239 RecycleBin5File_RecycleBinFile_GetLastModificationTime, 00240 RecycleBin5File_RecycleBinFile_GetDeletionTime, 00241 RecycleBin5File_RecycleBinFile_GetFileSize, 00242 RecycleBin5File_RecycleBinFile_GetPhysicalFileSize, 00243 RecycleBin5File_RecycleBinFile_GetAttributes, 00244 RecycleBin5File_RecycleBinFile_GetFileName, 00245 RecycleBin5File_RecycleBinFile_Delete, 00246 RecycleBin5File_RecycleBinFile_Restore, 00247 }; 00248 00249 static HRESULT 00250 RecycleBin5File_Constructor( 00251 IN IRecycleBin5 *prb, 00252 IN LPCWSTR Folder, 00253 IN PDELETED_FILE_RECORD pDeletedFile, 00254 OUT IRecycleBinFile **ppFile) 00255 { 00256 struct RecycleBin5File *s = NULL; 00257 LPCWSTR Extension; 00258 SIZE_T Needed; 00259 00260 if (!ppFile) 00261 return E_POINTER; 00262 00263 Extension = wcsrchr(pDeletedFile->FileNameW, '.'); 00264 if (Extension < wcsrchr(pDeletedFile->FileNameW, '\\')) 00265 Extension = NULL; 00266 Needed = wcslen(Folder) + 13; 00267 if (Extension) 00268 Needed += wcslen(Extension); 00269 Needed *= sizeof(WCHAR); 00270 00271 s = CoTaskMemAlloc(sizeof(struct RecycleBin5File) + Needed); 00272 if (!s) 00273 return E_OUTOFMEMORY; 00274 ZeroMemory(s, sizeof(struct RecycleBin5File) + Needed); 00275 s->recycleBinFileImpl.lpVtbl = &RecycleBin5FileVtbl; 00276 s->ref = 1; 00277 s->deletedFile = *pDeletedFile; 00278 s->recycleBin = prb; 00279 IRecycleBin5_AddRef(s->recycleBin); 00280 *ppFile = &s->recycleBinFileImpl; 00281 wsprintfW(s->FullName, L"%s\\D%c%lu%s", Folder, pDeletedFile->dwDriveNumber + 'a', pDeletedFile->dwRecordUniqueId, Extension); 00282 if (GetFileAttributesW(s->FullName) == INVALID_FILE_ATTRIBUTES) 00283 { 00284 RecycleBin5File_Destructor(s); 00285 return E_FAIL; 00286 } 00287 00288 return S_OK; 00289 } 00290 00291 struct RecycleBin5Enum 00292 { 00293 ULONG ref; 00294 IRecycleBin5 *recycleBin; 00295 HANDLE hInfo; 00296 INFO2_HEADER *pInfo; 00297 DWORD dwCurrent; 00298 IRecycleBinEnumList recycleBinEnumImpl; 00299 WCHAR szPrefix[ANY_SIZE]; 00300 }; 00301 00302 static HRESULT STDMETHODCALLTYPE 00303 RecycleBin5Enum_RecycleBinEnumList_QueryInterface( 00304 IN IRecycleBinEnumList *This, 00305 IN REFIID riid, 00306 OUT void **ppvObject) 00307 { 00308 struct RecycleBin5Enum *s = CONTAINING_RECORD(This, struct RecycleBin5Enum, recycleBinEnumImpl); 00309 00310 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject); 00311 00312 if (!ppvObject) 00313 return E_POINTER; 00314 00315 if (IsEqualIID(riid, &IID_IUnknown)) 00316 *ppvObject = &s->recycleBinEnumImpl; 00317 else if (IsEqualIID(riid, &IID_IRecycleBinEnumList)) 00318 *ppvObject = &s->recycleBinEnumImpl; 00319 else 00320 { 00321 *ppvObject = NULL; 00322 return E_NOINTERFACE; 00323 } 00324 00325 IUnknown_AddRef(This); 00326 return S_OK; 00327 } 00328 00329 static ULONG STDMETHODCALLTYPE 00330 RecycleBin5Enum_RecycleBinEnumList_AddRef( 00331 IN IRecycleBinEnumList *This) 00332 { 00333 struct RecycleBin5Enum *s = CONTAINING_RECORD(This, struct RecycleBin5Enum, recycleBinEnumImpl); 00334 ULONG refCount = InterlockedIncrement((PLONG)&s->ref); 00335 TRACE("(%p)\n", This); 00336 return refCount; 00337 } 00338 00339 static VOID 00340 RecycleBin5Enum_Destructor( 00341 struct RecycleBin5Enum *s) 00342 { 00343 TRACE("(%p)\n", s); 00344 00345 IRecycleBin5_OnClosing(s->recycleBin, &s->recycleBinEnumImpl); 00346 UnmapViewOfFile(s->pInfo); 00347 IRecycleBin5_Release(s->recycleBin); 00348 CoTaskMemFree(s); 00349 } 00350 00351 static ULONG STDMETHODCALLTYPE 00352 RecycleBin5Enum_RecycleBinEnumList_Release( 00353 IN IRecycleBinEnumList *This) 00354 { 00355 struct RecycleBin5Enum *s = CONTAINING_RECORD(This, struct RecycleBin5Enum, recycleBinEnumImpl); 00356 ULONG refCount; 00357 00358 TRACE("(%p)\n", This); 00359 00360 refCount = InterlockedDecrement((PLONG)&s->ref); 00361 00362 if (refCount == 0) 00363 RecycleBin5Enum_Destructor(s); 00364 00365 return refCount; 00366 } 00367 00368 static HRESULT STDMETHODCALLTYPE 00369 RecycleBin5Enum_RecycleBinEnumList_Next( 00370 IRecycleBinEnumList *This, 00371 IN DWORD celt, 00372 IN OUT IRecycleBinFile **rgelt, 00373 OUT DWORD *pceltFetched) 00374 { 00375 struct RecycleBin5Enum *s = CONTAINING_RECORD(This, struct RecycleBin5Enum, recycleBinEnumImpl); 00376 ULARGE_INTEGER FileSize; 00377 INFO2_HEADER *pHeader = s->pInfo; 00378 DELETED_FILE_RECORD *pDeletedFile; 00379 DWORD fetched = 0, i; 00380 DWORD dwEntries; 00381 HRESULT hr; 00382 00383 TRACE("(%p, %u, %p, %p)\n", This, celt, rgelt, pceltFetched); 00384 00385 if (!rgelt) 00386 return E_POINTER; 00387 if (!pceltFetched && celt > 1) 00388 return E_INVALIDARG; 00389 00390 FileSize.u.LowPart = GetFileSize(s->hInfo, &FileSize.u.HighPart); 00391 if (FileSize.u.LowPart == 0) 00392 return HRESULT_FROM_WIN32(GetLastError()); 00393 dwEntries = (DWORD)((FileSize.QuadPart - sizeof(INFO2_HEADER)) / sizeof(DELETED_FILE_RECORD)); 00394 00395 i = s->dwCurrent; 00396 pDeletedFile = (DELETED_FILE_RECORD *)(pHeader + 1) + i; 00397 for (; i < dwEntries && fetched < celt; i++) 00398 { 00399 hr = RecycleBin5File_Constructor(s->recycleBin, s->szPrefix, pDeletedFile, &rgelt[fetched]); 00400 if (SUCCEEDED(hr)) 00401 fetched++; 00402 pDeletedFile++; 00403 } 00404 00405 s->dwCurrent = i; 00406 if (pceltFetched) 00407 *pceltFetched = fetched; 00408 if (fetched == celt) 00409 return S_OK; 00410 else 00411 return S_FALSE; 00412 } 00413 00414 static HRESULT STDMETHODCALLTYPE 00415 RecycleBin5Enum_RecycleBinEnumList_Skip( 00416 IN IRecycleBinEnumList *This, 00417 IN DWORD celt) 00418 { 00419 struct RecycleBin5Enum *s = CONTAINING_RECORD(This, struct RecycleBin5Enum, recycleBinEnumImpl); 00420 TRACE("(%p, %u)\n", This, celt); 00421 s->dwCurrent += celt; 00422 return S_OK; 00423 } 00424 00425 static HRESULT STDMETHODCALLTYPE 00426 RecycleBin5Enum_RecycleBinEnumList_Reset( 00427 IN IRecycleBinEnumList *This) 00428 { 00429 struct RecycleBin5Enum *s = CONTAINING_RECORD(This, struct RecycleBin5Enum, recycleBinEnumImpl); 00430 TRACE("(%p)\n", This); 00431 s->dwCurrent = 0; 00432 return S_OK; 00433 } 00434 00435 CONST_VTBL struct IRecycleBinEnumListVtbl RecycleBin5EnumVtbl = 00436 { 00437 RecycleBin5Enum_RecycleBinEnumList_QueryInterface, 00438 RecycleBin5Enum_RecycleBinEnumList_AddRef, 00439 RecycleBin5Enum_RecycleBinEnumList_Release, 00440 RecycleBin5Enum_RecycleBinEnumList_Next, 00441 RecycleBin5Enum_RecycleBinEnumList_Skip, 00442 RecycleBin5Enum_RecycleBinEnumList_Reset, 00443 }; 00444 00445 HRESULT 00446 RecycleBin5Enum_Constructor( 00447 IN IRecycleBin5 *prb, 00448 IN HANDLE hInfo, 00449 IN HANDLE hInfoMapped, 00450 IN LPCWSTR szPrefix, 00451 OUT IUnknown **ppUnknown) 00452 { 00453 struct RecycleBin5Enum *s = NULL; 00454 SIZE_T Needed; 00455 00456 if (!ppUnknown) 00457 return E_POINTER; 00458 00459 Needed = (wcslen(szPrefix) + 1) * sizeof(WCHAR); 00460 00461 s = CoTaskMemAlloc(sizeof(struct RecycleBin5Enum) + Needed); 00462 if (!s) 00463 return E_OUTOFMEMORY; 00464 ZeroMemory(s, sizeof(struct RecycleBin5Enum) + Needed); 00465 s->recycleBinEnumImpl.lpVtbl = &RecycleBin5EnumVtbl; 00466 s->ref = 1; 00467 s->recycleBin = prb; 00468 wcscpy(s->szPrefix, szPrefix); 00469 s->hInfo = hInfo; 00470 s->pInfo = MapViewOfFile(hInfoMapped, FILE_MAP_READ, 0, 0, 0); 00471 if (!s->pInfo) 00472 { 00473 CoTaskMemFree(s); 00474 return HRESULT_FROM_WIN32(GetLastError()); 00475 } 00476 if (s->pInfo->dwVersion != 5 || s->pInfo->dwRecordSize != sizeof(DELETED_FILE_RECORD)) 00477 { 00478 UnmapViewOfFile(s->pInfo); 00479 CoTaskMemFree(s); 00480 return E_FAIL; 00481 } 00482 IRecycleBin5_AddRef(s->recycleBin); 00483 *ppUnknown = (IUnknown *)&s->recycleBinEnumImpl; 00484 00485 return S_OK; 00486 } Generated on Mon May 28 2012 04:36:10 for ReactOS by
1.7.6.1
|