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