1 #include "shelltest.h"
2 #include <atlbase.h>
3 #include <atlcom.h>
4 
5 
6 // + Adapted from https://blogs.msdn.microsoft.com/oldnewthing/20130503-00/?p=4463/
7 // In short: We want to create an IDLIST from an item that does not exist,
8 // so we have to provide WIN32_FIND_DATAW in a bind context.
9 // If we don't, the FS will be queried, and we do not get a valid IDLIST for a non-existing path.
10 
11 CComModule gModule;
12 
13 class CFileSysBindData :
14     public CComCoClass<CFileSysBindData>,
15     public CComObjectRootEx<CComMultiThreadModelNoCS>,
16     public IFileSystemBindData
17 {
18 public:
19     virtual HRESULT STDMETHODCALLTYPE SetFindData(const WIN32_FIND_DATAW *pfd)
20     {
21         m_Data = *pfd;
22         return S_OK;
23     }
24 
25     virtual HRESULT STDMETHODCALLTYPE GetFindData(WIN32_FIND_DATAW *pfd)
26     {
27         *pfd = m_Data;
28         return S_OK;
29     }
30 
31     DECLARE_NOT_AGGREGATABLE(CFileSysBindData)
32     DECLARE_PROTECT_FINAL_CONSTRUCT()
33     BEGIN_COM_MAP(CFileSysBindData)
34         COM_INTERFACE_ENTRY_IID(IID_IFileSystemBindData, IFileSystemBindData)
35     END_COM_MAP()
36 private:
37     WIN32_FIND_DATAW m_Data;
38 };
39 
40 static
41 HRESULT
42 AddFileSysBindCtx(_In_ IBindCtx *pbc)
43 {
44     CComPtr<IFileSystemBindData> spfsbc(new CComObject<CFileSysBindData>());
45     WIN32_FIND_DATAW wfd = { 0 };
46     wfd.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
47     spfsbc->SetFindData(&wfd);
48     HRESULT hr = pbc->RegisterObjectParam((LPOLESTR)STR_FILE_SYS_BIND_DATA, spfsbc);
49     ok(hr == S_OK, "hr = %lx\n", hr);
50     return hr;
51 }
52 
53 static
54 HRESULT
55 CreateBindCtxWithOpts(_In_ BIND_OPTS *pbo, _Outptr_ IBindCtx **ppbc)
56 {
57     CComPtr<IBindCtx> spbc;
58     HRESULT hr = CreateBindCtx(0, &spbc);
59     ok(hr == S_OK, "hr = %lx\n", hr);
60     if (SUCCEEDED(hr))
61     {
62         hr = spbc->SetBindOptions(pbo);
63         ok(hr == S_OK, "hr = %lx\n", hr);
64     }
65     *ppbc = SUCCEEDED(hr) ? spbc.Detach() : NULL;
66     return hr;
67 }
68 
69 static HRESULT
70 CreateFileSysBindCtx(_Outptr_ IBindCtx **ppbc)
71 {
72     CComPtr<IBindCtx> spbc;
73     BIND_OPTS bo = { sizeof(bo), 0, STGM_CREATE, 0 };
74     HRESULT hr = CreateBindCtxWithOpts(&bo, &spbc);
75     ok(hr == S_OK, "hr = %lx\n", hr);
76     if (SUCCEEDED(hr))
77     {
78         hr = AddFileSysBindCtx(spbc);
79         ok(hr == S_OK, "hr = %lx\n", hr);
80     }
81     *ppbc = SUCCEEDED(hr) ? spbc.Detach() : NULL;
82     return hr;
83 }
84 
85 VOID
86 PathToIDList(LPCWSTR pszPath, ITEMIDLIST** ppidl)
87 {
88     CComPtr<IBindCtx> spbc;
89     HRESULT hr = CreateFileSysBindCtx(&spbc);
90     ok(hr == S_OK, "hr = %lx\n", hr);
91     if (SUCCEEDED(hr))
92     {
93         hr = SHParseDisplayName(pszPath, spbc, ppidl, 0, NULL);
94         ok(hr == S_OK, "hr = %lx\n", hr);
95     }
96 }
97 
98 // - Adapted from https://blogs.msdn.microsoft.com/oldnewthing/20130503-00/?p=4463/
99