IN LPCWSTR FullName)
{
DWORD RemovableAttributes = FILE_ATTRIBUTE_READONLY;
+ WIN32_FIND_DATAW FindData;
+ HANDLE hSearch = INVALID_HANDLE_VALUE;
+ LPWSTR FullPath = NULL, pFilePart;
DWORD FileAttributes;
+ SIZE_T dwLength;
BOOL ret = FALSE;
FileAttributes = GetFileAttributesW(FullName);
}
if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
- /* Recursive deletion */
- /* FIXME: recursive deletion */
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- goto cleanup;
+ /* Prepare file specification */
+ dwLength = wcslen(FullName);
+ FullPath = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1 + MAX_PATH + 1) * sizeof(WCHAR));
+ if (!FullPath)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ wcscpy(FullPath, FullName);
+ if (FullPath[dwLength - 1] != '\\')
+ {
+ FullPath[dwLength] = '\\';
+ dwLength++;
+ }
+ pFilePart = &FullPath[dwLength];
+ wcscpy(pFilePart, L"*");
+ /* Enumerate contents, and delete it */
+ hSearch = FindFirstFileW(FullPath, &FindData);
+ if (hSearch == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ do
+ {
+ if (!(FindData.cFileName[0] == '.' &&
+ (FindData.cFileName[1] == '\0' || (FindData.cFileName[1] == '.' && FindData.cFileName[2] == '\0'))))
+ {
+ wcscpy(pFilePart, FindData.cFileName);
+ if (!IntDeleteRecursive(FullPath))
+ {
+ FindClose(hSearch);
+ goto cleanup;
+ }
+ }
+ }
+ while (FindNextFileW(hSearch, &FindData));
+ FindClose(hSearch);
+ if (GetLastError() != ERROR_NO_MORE_FILES)
+ goto cleanup;
+
+ /* Remove (now empty) directory */
if (!RemoveDirectoryW(FullName))
goto cleanup;
}
ret = TRUE;
cleanup:
+ HeapFree(GetProcessHeap(), 0, FullPath);
return ret;
}
};
static HRESULT STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_QueryInterface(
+RecycleBin5_RecycleBin5_QueryInterface(
IRecycleBin5 *This,
REFIID riid,
void **ppvObject)
return refCount;
}
+static VOID
+RecycleBin5_Destructor(
+ struct RecycleBin5 *s)
+{
+ TRACE("(%p)\n", s);
+
+ if (s->hInfo && s->hInfo != INVALID_HANDLE_VALUE)
+ CloseHandle(s->hInfo);
+ if (s->hInfoMapped)
+ CloseHandle(s->hInfoMapped);
+ CoTaskMemFree(s);
+}
+
static ULONG STDMETHODCALLTYPE
RecycleBin5_RecycleBin5_Release(
IRecycleBin5 *This)
refCount = InterlockedDecrement((PLONG)&s->ref);
if (refCount == 0)
- {
- CloseHandle(s->hInfo);
- CloseHandle(s->hInfoMapped);
- CoTaskMemFree(s);
- }
+ RecycleBin5_Destructor(s);
return refCount;
}
HANDLE hFile = INVALID_HANDLE_VALUE;
PINFO2_HEADER pHeader = NULL;
PDELETED_FILE_RECORD pDeletedFile;
- ULARGE_INTEGER fileSize;
- DWORD dwAttributes;
+ ULARGE_INTEGER FileSize;
+ DWORD dwAttributes, dwEntries;
SYSTEMTIME SystemTime;
DWORD ClusterSize, BytesPerSector, SectorsPerCluster;
HRESULT hr;
TRACE("(%p, %s)\n", This, debugstr_w(szFileName));
if (s->EnumeratorCount != 0)
- return E_FAIL;
+ return HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION);
/* Get full file name */
while (TRUE)
hr = HRESULT_FROM_WIN32(GetLastError());
goto cleanup;
}
- pDeletedFile = ((PDELETED_FILE_RECORD)(pHeader + 1)) + pHeader->dwNumberOfEntries;
+
+ /* Get number of entries */
+ FileSize.u.LowPart = GetFileSize(s->hInfo, &FileSize.u.HighPart);
+ if (FileSize.u.LowPart < sizeof(INFO2_HEADER))
+ {
+ UnmapViewOfFile(pHeader);
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ dwEntries = (DWORD)((FileSize.QuadPart - sizeof(INFO2_HEADER)) / sizeof(DELETED_FILE_RECORD)) - 1;
+ pDeletedFile = ((PDELETED_FILE_RECORD)(pHeader + 1)) + dwEntries;
/* Get file size */
#if 0
- if (!GetFileSizeEx(hFile, (PLARGE_INTEGER)&fileSize))
+ if (!GetFileSizeEx(hFile, (PLARGE_INTEGER)&FileSize))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto cleanup;
}
#else
- fileSize.u.LowPart = GetFileSize(hFile, &fileSize.u.HighPart);
- if (fileSize.u.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
+ FileSize.u.LowPart = GetFileSize(hFile, &FileSize.u.HighPart);
+ if (FileSize.u.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto cleanup;
}
#endif
/* Check if file size is > 4Gb */
- if (fileSize.u.HighPart != 0)
+ if (FileSize.u.HighPart != 0)
{
- /* FIXME: how to delete files >= 4Gb? */
- hr = E_NOTIMPL;
+ /* Yes, this recyclebin can't support this file */
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
goto cleanup;
}
- pHeader->dwTotalLogicalSize += fileSize.u.LowPart;
+ pHeader->dwTotalLogicalSize += FileSize.u.LowPart;
/* Generate new name */
- pHeader->dwHighestRecordUniqueId++;
Extension = wcsrchr(szFullName, '.');
ZeroMemory(pDeletedFile, sizeof(DELETED_FILE_RECORD));
- pDeletedFile->dwRecordUniqueId = pHeader->dwHighestRecordUniqueId;
+ if (dwEntries == 0)
+ pDeletedFile->dwRecordUniqueId = 0;
+ else
+ {
+ PDELETED_FILE_RECORD pLastDeleted = ((PDELETED_FILE_RECORD)(pHeader + 1)) + dwEntries - 1;
+ pDeletedFile->dwRecordUniqueId = pLastDeleted->dwRecordUniqueId + 1;
+ }
pDeletedFile->dwDriveNumber = tolower(szFullName[0]) - 'a';
_snwprintf(DeletedFileName, MAX_PATH, L"%s\\D%c%lu%s", s->Folder, pDeletedFile->dwDriveNumber + 'a', pDeletedFile->dwRecordUniqueId, Extension);
hr = HRESULT_FROM_WIN32(GetLastError());
goto cleanup;
}
- pDeletedFile->dwPhysicalFileSize = ROUND_UP(fileSize.u.LowPart, ClusterSize);
+ pDeletedFile->dwPhysicalFileSize = ROUND_UP(FileSize.u.LowPart, ClusterSize);
/* Set name */
wcscpy(pDeletedFile->FileNameW, szFullName);
SetLastError(ERROR_INVALID_NAME);
goto cleanup;
}
- pHeader->dwNumberOfEntries++;
/* Move file */
if (MoveFileW(szFullName, DeletedFileName))
TRACE("(%p, %p)\n", This, ppEnumList);
- hr = RecycleBin5_Enumerator_Constructor(This, s->hInfo, s->hInfoMapped, s->Folder, &pUnk);
+ hr = RecycleBin5Enum_Constructor(This, s->hInfo, s->hInfoMapped, s->Folder, &pUnk);
if (!SUCCEEDED(hr))
return hr;
TRACE("(%p, %s, %p)\n", This, debugstr_w(pDeletedFileName), pDeletedFile);
if (s->EnumeratorCount != 0)
- return E_FAIL;
-
+ return HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION);
+
pHeader = MapViewOfFile(s->hInfoMapped, FILE_MAP_WRITE, 0, 0, 0);
if (!pHeader)
return HRESULT_FROM_WIN32(GetLastError());
PINFO2_HEADER pHeader;
DELETED_FILE_RECORD *pRecord, *pLast;
DWORD dwEntries, i;
+ SHFILEOPSTRUCTW op;
TRACE("(%p, %s, %p)\n", This, debugstr_w(pDeletedFileName), pDeletedFile);
if (s->EnumeratorCount != 0)
- return E_FAIL;
+ return HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION);
pHeader = MapViewOfFile(s->hInfoMapped, FILE_MAP_WRITE, 0, 0, 0);
if (!pHeader)
if (pRecord->dwRecordUniqueId == pDeletedFile->dwRecordUniqueId)
{
/* Restore file */
- if (!MoveFileW(pDeletedFileName, pDeletedFile->FileNameW))
+ ZeroMemory(&op, sizeof(op));
+ op.wFunc = FO_COPY;
+ op.pFrom = pDeletedFileName;
+ op.pTo = pDeletedFile->FileNameW;
+
+ if (!SHFileOperationW(&op))
{
UnmapViewOfFile(pHeader);
return HRESULT_FROM_WIN32(GetLastError());
LPWSTR FileName; /* Pointer into BufferName buffer */
LPCSTR DesktopIniContents = "[.ShellClassInfo]\r\nCLSID={645FF040-5081-101B-9F08-00AA002F954E}\r\n";
INFO2_HEADER Info2Contents[] = { { 5, 0, 0, 0x320, 0 } };
- SIZE_T BytesToWrite, BytesWritten, Needed;
+ DWORD BytesToWrite, BytesWritten, Needed;
HANDLE hFile = INVALID_HANDLE_VALUE;
HRESULT hr;
HANDLE tokenHandle = INVALID_HANDLE_VALUE;
PTOKEN_USER TokenUserInfo = NULL;
LPWSTR StringSid = NULL, p;
- SIZE_T Needed, DirectoryLength;
+ DWORD Needed, DirectoryLength;
INT len;
HRESULT hr;
if (!SUCCEEDED(hr))
{
if (s)
- {
- if (s->hInfo && s->hInfo != INVALID_HANDLE_VALUE)
- CloseHandle(s->hInfo);
- if (s->hInfoMapped)
- CloseHandle(s->hInfoMapped);
- CoTaskMemFree(s);
- }
+ RecycleBin5_Destructor(s);
}
return hr;
}