1 /*
2  * PROJECT:     fontext_apitest
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Tests for fontext shell extension behavior
5  * COPYRIGHT:   Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #include <ntstatus.h>
9 #define WIN32_NO_STATUS
10 #include <windef.h>
11 #include <ntndk.h>
12 #include <atlbase.h>
13 #include <atlcom.h>
14 #include <shellapi.h>
15 #include <shlobj.h>
16 #include <shobjidl.h>
17 #include <shellutils.h>
18 #include "wine/test.h"
19 
20 const CLSID CLSID_FontExt = { 0xBD84B380, 0x8CA2, 0x1069, { 0xAB, 0x1D, 0x08, 0x00, 0x09, 0x48, 0xF5, 0x34 } };
21 static DWORD g_WinVersion;
22 
23 
24 static HRESULT Initialize(CComPtr<IPersistFolder>& spFolder, LPCWSTR Path)
25 {
26     CComHeapPtr<ITEMIDLIST> pidl;
27     CComPtr<IShellFolder> spDesktop;
28 
29     HRESULT hr = SHGetDesktopFolder(&spDesktop);
30     ok_hex(hr, S_OK);
31     if (FAILED(hr))
32         return hr;
33 
34     DWORD Attributes = 0, chEaten = 0;
35     hr = spDesktop->ParseDisplayName(NULL, NULL, (LPOLESTR)Path, &chEaten, &pidl, &Attributes);
36     ok_hex(hr, S_OK);
37     if (FAILED(hr))
38         return hr;
39 
40     return spFolder->Initialize(pidl);
41 }
42 
43 
44 static void CreateObjectsFromPersistFolder()
45 {
46     WCHAR Path[MAX_PATH] = { 0 };
47 
48     CComPtr<IPersistFolder> spFolder;
49     HRESULT hr = CoCreateInstance(CLSID_FontExt, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPersistFolder, &spFolder));
50     ok_hex(hr, S_OK);
51     if (!SUCCEEDED(hr))
52         return;
53 
54     hr = SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, Path);
55     ok_hex(hr, S_OK);
56     if (FAILED(hr))
57         return;
58 
59     // Initializing this in another folder fails
60     hr = Initialize(spFolder, Path);
61     ok_hex(hr, E_FAIL);
62 
63     hr = SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, Path);
64     ok_hex(hr, S_OK);
65     if (FAILED(hr))
66         return;
67 
68     // Initializing it in the font folder works
69     hr = Initialize(spFolder, Path);
70     ok_hex(hr, S_OK);
71 
72     // For ros we do not implement the ShellView, but go directly to the ShellFolder.
73     // So we detect this special case
74     if (g_WinVersion < _WIN32_WINNT_VISTA)
75     {
76         CComPtr<IShellFolder> spShellFolder;
77         hr = spFolder->QueryInterface(IID_PPV_ARG(IShellFolder, &spShellFolder));
78 
79         if (SUCCEEDED(hr))
80         {
81             trace("Got IShellFolder on < Vista, faking 0x601\n");
82             g_WinVersion = _WIN32_WINNT_WIN7;
83         }
84     }
85 
86     if (g_WinVersion < _WIN32_WINNT_VISTA)
87     {
88         // A view is present
89         CComPtr<IShellView> spView;
90         hr = spFolder->QueryInterface(IID_PPV_ARG(IShellView, &spView));
91         ok_hex(hr, S_OK);
92 
93         // No shell folder
94         CComPtr<IShellFolder> spShellFolder;
95         hr = spFolder->QueryInterface(IID_PPV_ARG(IShellFolder, &spShellFolder));
96         ok_hex(hr, E_NOINTERFACE);
97 
98         // Ask the view:
99         if (spView)
100         {
101             CComPtr<IObjectWithSite> spObjectWithSite;
102             hr = spView->QueryInterface(IID_PPV_ARG(IObjectWithSite, &spObjectWithSite));
103             ok_hex(hr, E_NOINTERFACE);
104 
105             CComPtr<IInternetSecurityManager> spISM;
106             hr = spView->QueryInterface(IID_PPV_ARG(IInternetSecurityManager, &spISM));
107             ok_hex(hr, E_NOINTERFACE);
108         }
109 
110 
111         CComPtr<IDropTarget> spDropTarget;
112         hr = spFolder->QueryInterface(IID_PPV_ARG(IDropTarget, &spDropTarget));
113         ok_hex(hr, S_OK);
114 
115         CComPtr<IExtractIconW> spExtractIcon;
116         hr = spFolder->QueryInterface(IID_PPV_ARG(IExtractIconW, &spExtractIcon));
117         ok_hex(hr, E_NOINTERFACE);
118     }
119     else
120     {
121         // Here we have a shell folder
122         CComPtr<IShellFolder> spShellFolder;
123         hr = spFolder->QueryInterface(IID_PPV_ARG(IShellFolder, &spShellFolder));
124         ok_hex(hr, S_OK);
125 
126         // But no view anymore
127         CComPtr<IShellView> spView;
128         hr = spFolder->QueryInterface(IID_PPV_ARG(IShellView, &spView));
129         ok_hex(hr, E_NOINTERFACE);
130         spView.Release();
131 
132 
133         CComPtr<IDropTarget> spDropTarget;
134         hr = spFolder->QueryInterface(IID_PPV_ARG(IDropTarget, &spDropTarget));
135         ok_hex(hr, E_NOINTERFACE);
136 
137         CComPtr<IExtractIconW> spExtractIcon;
138         hr = spFolder->QueryInterface(IID_PPV_ARG(IExtractIconW, &spExtractIcon));
139         ok_hex(hr, E_NOINTERFACE);
140     }
141 }
142 
143 
144 static void CreateDropTarget()
145 {
146     CComPtr<IDropTarget> spDropTarget;
147     HRESULT hr = CoCreateInstance(CLSID_FontExt, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IDropTarget, &spDropTarget));
148     ok_hex(hr, E_NOINTERFACE);
149 }
150 
151 static void CreateExtractIcon()
152 {
153     if (g_WinVersion < _WIN32_WINNT_VISTA)
154     {
155         CComPtr<IExtractIconA> spExtractIconA;
156         HRESULT hr = CoCreateInstance(CLSID_FontExt, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IExtractIconA, &spExtractIconA));
157         ok_hex(hr, S_OK);
158 
159         CComPtr<IExtractIconW> spExtractIconW;
160         hr = CoCreateInstance(CLSID_FontExt, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IExtractIconW, &spExtractIconW));
161         ok_hex(hr, S_OK);
162     }
163     else
164     {
165         CComPtr<IExtractIconA> spExtractIconA;
166         HRESULT hr = CoCreateInstance(CLSID_FontExt, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IExtractIconA, &spExtractIconA));
167         ok_hex(hr, E_NOINTERFACE);
168 
169         CComPtr<IExtractIconW> spExtractIconW;
170         hr = CoCreateInstance(CLSID_FontExt, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IExtractIconW, &spExtractIconW));
171         ok_hex(hr, E_NOINTERFACE);
172     }
173 }
174 
175 
176 
177 START_TEST(shellext)
178 {
179     RTL_OSVERSIONINFOEXW rtlinfo = {0};
180 
181     rtlinfo.dwOSVersionInfoSize = sizeof(rtlinfo);
182     RtlGetVersion((PRTL_OSVERSIONINFOW)&rtlinfo);
183     g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
184 
185     trace("g_WinVersion=0x%x\n", g_WinVersion);
186 
187     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
188 
189     CreateObjectsFromPersistFolder();
190     CreateDropTarget();
191     CreateExtractIcon();
192 
193     CoUninitialize();
194 }
195