I have a program that gets information about files in the windows recycle bin. The only non-crutch solution to the bucket access problem I see is using the shell environment.
I have a code for removing single file (or folder) from recycle bin with winapi (shell envirionment) like the next:
#include <iostream>
#include <shobjidl_core.h>
#include <Shlobj.h>
#include <shlwapi.h>
#include <ntquery.h>
const SHCOLUMNID SCID_RemovedFrom = { PSGUID_DISPLACED, PID_DISPLACED_FROM };
const SHCOLUMNID SCID_RemovedName = { PSGUID_STORAGE, PID_STG_NAME };
const SHCOLUMNID SCID_DateDeleted = { PSGUID_DISPLACED, PID_DISPLACED_DATE };
const SHCOLUMNID SCID_DateCreated = { PSGUID_STORAGE, PID_STG_CREATETIME };
const SHCOLUMNID SCID_DateModifed = { PSGUID_STORAGE, PID_STG_WRITETIME };
const SHCOLUMNID SCID_DateOpened = { PSGUID_STORAGE, PID_STG_ACCESSTIME };
int main() {
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
LPSHELLFOLDER pDesktop = NULL;
SHGetDesktopFolder(&pDesktop);
LPITEMIDLIST pidlRecycleBin = NULL;
SHGetSpecialFolderLocation(NULL, CSIDL_BITBUCKET, &pidlRecycleBin);
IShellFolder2 *pRecycleBin;
pDesktop->BindToObject(pidlRecycleBin, NULL, IID_IShellFolder2, (LPVOID*)&pRecycleBin);
pDesktop->Release();
CoTaskMemFree(pidlRecycleBin);
IEnumIDList* penumFiles;
pRecycleBin->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &penumFiles);
STRRET sret;
IFileOperation *pfo;
CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pfo));
pfo->SetOperationFlags(FOF_NO_UI);
LPITEMIDLIST pidl = NULL;
BSTR bstr = NULL;
VARIANT vt;
SYSTEMTIME syst;
while (penumFiles->Next(1, &pidl, NULL) != S_FALSE) {
pRecycleBin->GetDisplayNameOf(pidl, SHGDN_NORMAL, &sret); // not a FULL name!!!
StrRetToBSTR(&sret, pidl, &bstr);
std::wcout << bstr << L' ';
SysFreeString(bstr);
pRecycleBin->GetDetailsEx(pidl, &SCID_DateDeleted, &vt);
VariantTimeToSystemTime(vt.date, &syst);
std::wcout << "\t" << syst.wHour << ":" << syst.wMinute << " " << syst.wDay << "." << syst.wMonth << "." << syst.wYear << std::endl;
/*MARK ITEMS TO DELETE*/
SHCreateItemWithParent(NULL, pRecycleBin, pidl, IID_IShellItem, (void**)&shi);
pfo->DeleteItem(shi, NULL);
shi->Release();
CoTaskMemFree(pidl);
}
penumFiles->Release();
pRecycleBin->Release();
/*DELETE MARKED ITEMS*/
pfo->PerformOperations();
pfo->Release();
//Update recycle bin icon [undocumented function]
(void (*)())GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHUpdateRecycleBinIcon")();
CoUninitialize();
return 0;
}
In the code above, at the top, there are constant definitions (SCID_RemovedFrom
, SCID_RemovedName
) for getting the path where the deleted file was located and the name via the function GetDetailsEx
. However, the resulting name does not always contain the extension, but only when the file is registered in the system in such a way that the extension is displayed in File Explorer. In other cases, the name is obtained without an extension.
I couldn't find a constant where GetDetailsEx
will return the full name (with the extension) regardless of the user's settings. So far, I've only found a crutch: use pRecycleBin->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &sret);
to get extensions, BUT there a problem: I can't determine how to interpret the name some.docx
and extension $RXZH1I6.docx
: is some.docx
a full name (if extensions are shown) or some.docx.docx
is a full name (if extensions are hidden). It turns out that this crutch is even dangerous.
How can I get the name of any file ("NONFOLDER") guaranteed to have an extension?