I'm looking for a way to put a folder (with subfolders) into a Recycle Bin with these conditions:
It must be done silently -- without any Windows UI.
The folder must never be permanently deleted. If it can't be put into Recycle Bin, I'd expect the API to fail.
Get a callback routine for the process like CopyFileEx does.
So far I was able to come up with this:
SHFILEOPSTRUCT sfo = {0};
sfo.wFunc = FO_DELETE;
sfo.pFrom = L"K:\\test del from USB\0"; //Folder on a USB stick
sfo.fFlags = FOF_ALLOWUNDO |
FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR |
FOF_WANTNUKEWARNING;
int res = SHFileOperation(&sfo);
BOOL bFullSuccess = res == 0 && !sfo.fAnyOperationsAborted;
Which horribly fails on a folder located on a USB flash drive, i.e. it is permanently deleted in despite of the FOF_ALLOWUNDO
flag.
So whether I'm not doing something right, or SHFileOperation API is very wrong!
Any idea how to do what I outlined above?
EDIT: I implemented the IRecycleBinManager::WillRecycle
method as was suggested by @Denis Anisimov, but there's evidently more to it. Here's my C++ version. First interface definition for the method I need:
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("5869092D-8AF9-4A6C-AE84-1F03BE2246CC")
IRecycleBinManager : public IUnknown
{
public:
//function WillRecycle(const pszPath: LPCWSTR): HRESULT; stdcall;
virtual HRESULT STDMETHODCALLTYPE WillRecycle(
/* [string][in] */ __RPC__in LPCWSTR pszFile) = 0;
};
#endif
and then the call itself:
HRESULT hr;
CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED);
// {4A04656D-52AA-49DE-8A09-CB178760E748}
const CLSID CLSID_RecycleBinManager = {0x4A04656D, 0x52AA, 0x49DE, {0x8A, 0x09, 0xCB, 0x17, 0x87, 0x60, 0xE7, 0x48}};
// {5869092D-8AF9-4A6C-AE84-1F03BE2246CC}
const IID IID_IRecycleBinManager = {0x5869092D, 0x8AF9, 0x4A6C, {0xAE, 0x84, 0x1F, 0x03, 0xBE, 0x22, 0x46, 0xCC}};
IRecycleBinManager* pIRBM = NULL;
hr = CoCreateInstance(CLSID_RecycleBinManager, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IID_IRecycleBinManager, (void**) &pIRBM);
// hr = SHCoCreateInstance(NULL, &CLSID_RecycleBinManager, NULL, IID_IRecycleBinManager, (void **)&pIRBM);
if (SUCCEEDED(hr))
{
hr = pIRBM->WillRecycle(L"C:\\test del"); //Crashes
pIRBM->Release();
}
Unfortunately I'm getting this error on the line where I'm supposed to call WillRecycle
method:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
SHFileOperation
will not do to implement your goal. You may have to roll your own solution. Helpful information is available under Handling Shell Data Transfer Scenarios - Dropping Files on the Recycle Bin. – StockinetSHFileOperation
API is placed into the Recycle Bin vs. permanently deleted? – Oppilate