Access violation when using IShellFolder2

FreeSlave freeslave93 at gmail.com
Thu Sep 10 13:30:15 UTC 2020


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);
     }
}


More information about the Digitalmars-d-learn mailing list