On Thursday, 10 September 2020 at 06:43:35 UTC, John Chapman
wrote:
On Wednesday, 9 September 2020 at 22:44:50 UTC, FreeSlave wrote:
Btw do you know how to parse a date returned by GetDetailsOf?
Couldn't find any examples in C++. I actually can see digits
representing date and time as a part of the string, but I
would prefer to use some winapi function to translate it into
some time type instead of manually parsing the result.
You could look at passing the str.pOleStr field in the
SHELLDETAILS you got from GetDetailsOf to VarDateFromStr. It
will give you a DATE value that VariantTimeToSystemTime will
convert to a SYSTEMTIME from which you can get the years,
months, days etc.
For example:
SHELLDETAILS details;
GetDetailsOf(pidl, 3, &details);
DATE date;
VarDateFromStr(details.str.pOleStr, LOCALE_USER_DEFAULT, 0,
&date);
SYSTEMTIME st;
VariantTimeToSystemTime(date, &st);
auto year = st.wYear;
auto month = st.wMonth;
You can convert that into a more D-friendly SysTime object
using SYSTEMTIMEToSysTime from the std.datetime package.
Thanks. I tried this, but VarDateFromStr does not succeed for me.
Here's the updated example. Note that I use a column 2 to
retrieve the date because that's the deletion date column for
recycle bin folder.
import core.sys.windows.windows;
import core.sys.windows.shlobj;
import core.sys.windows.wtypes;
import core.sys.windows.oaidl;
import std.exception;
import std.datetime;
pragma(lib, "Ole32");
pragma(lib, "OleAut32");
interface IShellFolder2 : IShellFolder {
HRESULT GetDefaultSearchGUID(GUID*);
HRESULT EnumSearches(IEnumExtraSearch*);
HRESULT GetDefaultColumn(DWORD, ULONG*, ULONG*);
HRESULT GetDefaultColumnState(UINT, SHCOLSTATEF*);
HRESULT GetDetailsEx(LPCITEMIDLIST, const(SHCOLUMNID)*,
VARIANT*);
HRESULT GetDetailsOf(LPCITEMIDLIST, UINT, SHELLDETAILS*);
HRESULT MapColumnToSCID(UINT, SHCOLUMNID*);
}
import std.stdio;
static @trusted string StrRetToString(ref scope STRRET strRet)
{
import std.string : fromStringz;
switch (strRet.uType)
{
case STRRET_CSTR:
return fromStringz(strRet.cStr.ptr).idup;
case STRRET_OFFSET:
writeln("STRRET_OFFSET!");
return string.init;
case STRRET_WSTR:
char[MAX_PATH] szTemp;
auto len = WideCharToMultiByte (CP_UTF8, 0,
strRet.pOleStr, -1, szTemp.ptr, szTemp.sizeof, null, null);
scope(exit) CoTaskMemFree(strRet.pOleStr);
if (len)
return szTemp[0..len-1].idup;
else
return string.init;
default:
return string.init;
}
}
static @trusted SysTime StrRetToSysTime(ref scope STRRET strRet)
{
enforce(strRet.uType == STRRET_WSTR, "Expected STRRET_WSTR");
DATE date;
enforce(SUCCEEDED(VarDateFromStr(strRet.pOleStr,
LOCALE_USER_DEFAULT, 0, &date)), "Failed to convert string to
date value");
SYSTEMTIME sysTime;
VariantTimeToSystemTime(date, &sysTime);
return SYSTEMTIMEToSysTime(&sysTime);
}
void main()
{
OleInitialize(null);
scope(exit) OleUninitialize();
IShellFolder desktop;
LPITEMIDLIST pidlRecycleBin;
enforce(SUCCEEDED(SHGetDesktopFolder(&desktop)), "Failed to
get desktop shell folder");
assert(desktop);
scope(exit) desktop.Release();
enforce(SUCCEEDED(SHGetSpecialFolderLocation(null,
CSIDL_BITBUCKET, &pidlRecycleBin)), "Failed to get recycle bin
location");
assert(pidlRecycleBin);
scope(exit) ILFree(pidlRecycleBin);
IShellFolder2 recycleBin;
enforce(SUCCEEDED(desktop.BindToObject(pidlRecycleBin, null,
&IID_IShellFolder2, cast(LPVOID *)&recycleBin)), "Failed to get
recycle bin shell folder");
assert(recycleBin);
scope(exit) recycleBin.Release();
IEnumIDList enumFiles;
with(SHCONTF) enforce(SUCCEEDED(recycleBin.EnumObjects(null,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN,
&enumFiles)), "Failed to enumerate objects in recycle bin");
scope(exit) enumFiles.Release();
LPITEMIDLIST pidl;
while (enumFiles.Next(1, &pidl, null) != S_FALSE) {
string name;
string originalLocation;
SysTime deletionTime;
SHELLDETAILS details;
if(SUCCEEDED(recycleBin.GetDetailsOf(pidl,0,&details)))
{
name = StrRetToString(details.str);
}
if(SUCCEEDED(recycleBin.GetDetailsOf(pidl,1,&details)))
{
originalLocation = StrRetToString(details.str);
}
if(SUCCEEDED(recycleBin.GetDetailsOf(pidl,2,&details)))
{
deletionTime = StrRetToSysTime(details.str);
}
writefln("Name: %s, original location: %s, datetime: %s",
name, originalLocation, deletionTime);
CoTaskMemFree(pidl);
}
}