Skip to content

Commit

Permalink
[SHELL32] SHUpdateRecycleBinIcon() part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
wjk committed Sep 1, 2023
1 parent 93520dc commit 1efb4ef
Showing 1 changed file with 64 additions and 0 deletions.
64 changes: 64 additions & 0 deletions dll/win32/shell32/folders/CRecycleBin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,70 @@ static void TRASH_PlayEmptyRecycleBinSound()
*/
EXTERN_C HRESULT WINAPI SHUpdateRecycleBinIcon(void)
{
/*
* SHUpdateRecycleBinIcon's logic of updating the trash bin icon is like so, in the following order:
*
* 1. Determine if the trash bin is empty or not. It first iterates all the drive partitions and
* check each of them that one has the location path of the bucket that is associated as the
* default bin of the system. Afterwards it loops the bucket of potential remaining files using
* the traditional fashion of FindFirstFileW ... FindNextFileW API calls. If the file in question
* is a directory (pointed by the FILE_ATTRIBUTE_DIRECTORY attribute) then it iterates over that
* directory as well. If at least one or more files have been found (empty directories are taken
* into account as well) then the bin is NOT empty.
* 2. Query/Set the Registry SHELL32 data. Presumably it queries some information in regard of the
* trash bin icons and sets the default value as either "Empty" or "Full" depending on the state
* of the bin, I haven't looked much deeper into that.
* 3. Expand the environment strings with SHExpandEnvironmentStringsW.
* 4. Update the icon image with SHUpdateImageW.
* 5. Invoke a notification with SHChangeNotify.
*/

BOOL recycleBinEmpty = true, recycleBinEmptySet = false;

/* First, check to see if the Recycle Bin on any drive has anything in it.*/

// I do not want to use CString here because this API returns a LPWZZSTR.
CHeapPtr<WCHAR> logicalDrivesBuffer;
DWORD logicalDrivesBufferLength;
logicalDrivesBufferLength = GetLogicalDriveStringsW(0, NULL);
logicalDrivesBuffer.Allocate(logicalDrivesBufferLength / sizeof(WCHAR));
GetLogicalDriveStringsW(logicalDrivesBufferLength, (LPWSTR)&logicalDrivesBuffer);

/* For every drive in the system: */
LPWSTR logicalDrivesPtr = (LPWSTR)logicalDrivesBuffer.m_pData;
while (*logicalDrivesPtr != L'\0')
{
LPWSTR logicalDrive = logicalDrivesPtr;
logicalDrivesPtr += strlenW(logicalDrive) + 1; // count the trailing NUL

/* Get its recycle bin... */
CComPtr<IRecycleBin> recycleBin;
HRESULT hr = GetDefaultRecycleBin(logicalDrive, &recycleBin);
if (FAILED(hr)) continue;

/* ...and check if there is anything in it. */
CComPtr<IRecycleBinEnumList> recycleBinEnum;
hr = recycleBin->EnumObjects(&recycleBinEnum);

// If the rgelt parameter is NULL, then IRecycleBinEnum::Next() will return an error.
CComPtr<IRecycleBinFile> dontCare;
hr = recycleBinEnum->Next(1, &dontCare, NULL);
if (FAILED(hr)) continue;

if (hr == S_FALSE)
{
// The recycle bin is empty. Continue.
}
else
{
// There is at least one item in the recycle bin for this drive.
// Since we know that the recycle bin is not empty, we can stop now.
recycleBinEmpty = false;
recycleBinEmptySet = true;
break;
}
}

FIXME("stub\n");

return S_OK;
Expand Down

0 comments on commit 1efb4ef

Please sign in to comment.