#include "shelltest.h" // + Adapted from https://blogs.msdn.microsoft.com/oldnewthing/20130503-00/?p=4463/ // In short: We want to create an IDLIST from an item that does not exist, // so we have to provide WIN32_FIND_DATAW in a bind context. // If we don't, the FS will be queried, and we do not get a valid IDLIST for a non-existing path. CComModule gModule; class CFileSysBindData : public CComCoClass, public CComObjectRootEx, public IFileSystemBindData { public: virtual HRESULT STDMETHODCALLTYPE SetFindData(const WIN32_FIND_DATAW *pfd) { m_Data = *pfd; return S_OK; } virtual HRESULT STDMETHODCALLTYPE GetFindData(WIN32_FIND_DATAW *pfd) { *pfd = m_Data; return S_OK; } DECLARE_NOT_AGGREGATABLE(CFileSysBindData) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CFileSysBindData) COM_INTERFACE_ENTRY_IID(IID_IFileSystemBindData, IFileSystemBindData) END_COM_MAP() private: WIN32_FIND_DATAW m_Data; }; static HRESULT AddFileSysBindCtx(_In_ IBindCtx *pbc) { CComPtr spfsbc(new CComObject()); WIN32_FIND_DATAW wfd = { 0 }; wfd.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; spfsbc->SetFindData(&wfd); HRESULT hr = pbc->RegisterObjectParam((LPOLESTR)STR_FILE_SYS_BIND_DATA, spfsbc); ok(hr == S_OK, "hr = %lx\n", hr); return hr; } static HRESULT CreateBindCtxWithOpts(_In_ BIND_OPTS *pbo, _Outptr_ IBindCtx **ppbc) { CComPtr spbc; HRESULT hr = CreateBindCtx(0, &spbc); ok(hr == S_OK, "hr = %lx\n", hr); if (SUCCEEDED(hr)) { hr = spbc->SetBindOptions(pbo); ok(hr == S_OK, "hr = %lx\n", hr); } *ppbc = SUCCEEDED(hr) ? spbc.Detach() : NULL; return hr; } static HRESULT CreateFileSysBindCtx(_Outptr_ IBindCtx **ppbc) { CComPtr spbc; BIND_OPTS bo = { sizeof(bo), 0, STGM_CREATE, 0 }; HRESULT hr = CreateBindCtxWithOpts(&bo, &spbc); ok(hr == S_OK, "hr = %lx\n", hr); if (SUCCEEDED(hr)) { hr = AddFileSysBindCtx(spbc); ok(hr == S_OK, "hr = %lx\n", hr); } *ppbc = SUCCEEDED(hr) ? spbc.Detach() : NULL; return hr; } VOID PathToIDList(LPCWSTR pszPath, ITEMIDLIST** ppidl) { CComPtr spbc; HRESULT hr = CreateFileSysBindCtx(&spbc); ok(hr == S_OK, "hr = %lx\n", hr); if (SUCCEEDED(hr)) { hr = SHParseDisplayName(pszPath, spbc, ppidl, 0, NULL); ok(hr == S_OK, "hr = %lx\n", hr); } } // - Adapted from https://blogs.msdn.microsoft.com/oldnewthing/20130503-00/?p=4463/