Reactos
1/*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for SHParseDisplayName
5 * PROGRAMMERS: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8#include "shelltest.h"
9
10/* Version masks */
11#define T_ALL 0x0
12#define T_WIN2K 0x1
13#define T_WINXP 0x2
14#define T_WIN2K3 0x4
15#define T_VISTA 0x8
16#define T_WIN7 0x10
17#define T_WIN8 0x20
18#define T_WIN10 0x40
19
20#define T_PRE_VISTA (T_WIN2K | T_WINXP | T_WIN2K3)
21#define T_PRE_WIN7 (T_PRE_VISTA | T_VISTA)
22#define T_PRE_WIN8 (T_PRE_WIN7 | T_WIN7)
23
24#define T_WIN8_PLUS (T_WIN8 | T_WIN10)
25#define T_WIN7_PLUS (T_WIN7 | T_WIN8_PLUS)
26#define T_VISTA_PLUS (T_VISTA | T_WIN7_PLUS)
27
28struct test_data
29{
30 int testline;
31 PCWSTR wszPathToParse;
32 PCWSTR wszExpectedDisplayName;
33 INT nExpectedCSIDL;
34 HRESULT hResult;
35 UINT ValidForVersion;
36};
37
38struct test_data Tests[] =
39{
40 /* Tests for CDesktopFolder */
41 {__LINE__, NULL, NULL, 0, E_OUTOFMEMORY, T_PRE_VISTA},
42 {__LINE__, NULL, NULL, 0, E_INVALIDARG, T_VISTA_PLUS},
43 {__LINE__, L"", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0, S_OK, 0},
44 {__LINE__, L" ", NULL, 0, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), T_PRE_VISTA},
45 {__LINE__, L" ", NULL, 0, E_INVALIDARG, T_WIN8_PLUS},
46 {__LINE__, L":", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
47 {__LINE__, L": ", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
48 {__LINE__, L" :", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
49 {__LINE__, L"/", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
50 {__LINE__, L"//", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
51 /* This opens C:\ from Win+R and address bar */
52 {__LINE__, L"\\", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
53 /* These two opens "C:\Program Files" from Win+R and address bar */
54 {__LINE__, L"\\Program Files", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
55 {__LINE__, L"\\Program Files\\", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
56 {__LINE__, L"\\\\?", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
57 {__LINE__, L"\\\\?\\", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
58 /* Tests for the shell: protocol */
59 {__LINE__, L"shell:", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), 0},
60 {__LINE__, L"shell::", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), 0},
61 {__LINE__, L"shell:::", NULL, 0, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 0},
62 {__LINE__, L"shell:::{", NULL, 0, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 0},
63 {__LINE__, L"shell:fail", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), 0},
64 {__LINE__, L"shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0, S_OK, 0},
65 {__LINE__, L"shell:desktop", NULL, CSIDL_DESKTOPDIRECTORY, S_OK, T_PRE_VISTA},
66 {__LINE__, L"shell:windows", NULL, CSIDL_WINDOWS, S_OK, T_PRE_VISTA},
67 {__LINE__, L"shell:system", NULL, CSIDL_SYSTEM, S_OK, T_PRE_VISTA},
68 {__LINE__, L"shell:personal", NULL, CSIDL_MYDOCUMENTS, S_OK, T_PRE_VISTA},
69 {__LINE__, L"shell:programs", NULL, CSIDL_PROGRAMS, S_OK, T_PRE_VISTA},
70 {__LINE__, L"shell:programfiles", NULL, CSIDL_PROGRAM_FILES, S_OK, T_PRE_VISTA},
71 {__LINE__, L"shell:windows\\system32", NULL, CSIDL_SYSTEM, S_OK, T_PRE_VISTA},
72 {__LINE__, L"shell:windows\\fonts", NULL, CSIDL_FONTS, S_OK, T_PRE_VISTA},
73 /* The following tests are confusing. They don't work for SHParseDisplayName but work on psfDesktop->ParseDisplayName */
74 {__LINE__, L"shell:desktop", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), T_VISTA_PLUS},
75 {__LINE__, L"shell:windows", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), T_VISTA_PLUS},
76 {__LINE__, L"shell:system", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), T_VISTA_PLUS},
77 {__LINE__, L"shell:personal", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), T_VISTA_PLUS},
78 {__LINE__, L"shell:programs", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), T_VISTA_PLUS},
79 {__LINE__, L"shell:programfiles", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), T_VISTA_PLUS},
80 {__LINE__, L"shell:windows\\system32", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), T_VISTA_PLUS},
81 {__LINE__, L"shell:windows\\fonts", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), T_VISTA_PLUS},
82 /* Tests for CInternet */
83 {__LINE__, L"aa:", NULL, 0, E_INVALIDARG, T_PRE_VISTA},
84 {__LINE__, L"garbage:", NULL, 0, E_INVALIDARG, T_PRE_VISTA},
85 {__LINE__, L"ftp:", NULL, 0, E_INVALIDARG, T_PRE_VISTA},
86 {__LINE__, L"ftp:/", NULL, 0, E_INVALIDARG, T_PRE_VISTA},
87 {__LINE__, L"ftp://", NULL, 0, E_INVALIDARG, T_PRE_VISTA},
88 {__LINE__, L"ftp://a", NULL, 0, E_INVALIDARG, T_PRE_VISTA},
89 {__LINE__, L"ftp://ftp.gnu.org/gnu/octave/", NULL, 0, E_INVALIDARG, T_PRE_VISTA},
90 {__LINE__, L"aa:", L"aa:", 0, S_OK, T_WIN10},
91 {__LINE__, L"garbage:", L"garbage:", 0, S_OK, T_WIN10},
92 {__LINE__, L"ftp:", L"ftp:", 0, S_OK, T_WIN10},
93 {__LINE__, L"ftp:/", L"ftp:/", 0, S_OK, T_WIN10},
94 {__LINE__, L"ftp://", L"ftp:///", 0, S_OK, T_WIN10},
95 {__LINE__, L"ftp://a", L"ftp://a/", 0, S_OK, T_WIN10},
96 {__LINE__, L"ftp://ftp.gnu.org/gnu/octave/", L"ftp://ftp.gnu.org/gnu/octave/", 0, S_OK, T_WIN10},
97 /* Tests for CRegFolder */
98 {__LINE__, L"::", NULL, 0, CO_E_CLASSSTRING, 0},
99 {__LINE__, L"::{", NULL, 0, CO_E_CLASSSTRING, 0},
100 {__LINE__, L"::{ ", NULL, 0, CO_E_CLASSSTRING, 0},
101 {__LINE__, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0, S_OK, 0},
102 {__LINE__, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D} ", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0, S_OK, 0},
103 {__LINE__, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}a", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0, S_OK, 0},
104 {__LINE__, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}garbage", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0, S_OK, 0},
105 {__LINE__, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D ", NULL, 0, CO_E_CLASSSTRING, 0},
106 {__LINE__, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\", NULL, 0, E_INVALIDARG, 0},
107 {__LINE__, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\ ", NULL, 0, E_INVALIDARG, 0},
108 {__LINE__, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}", 0, S_OK, 0},
109 /* Tests for CDrivesFolder */
110 {__LINE__, L"c:", NULL, 0, E_INVALIDARG, T_PRE_VISTA},
111 {__LINE__, L"c:", L"C:\\", 0, S_OK, T_VISTA_PLUS},
112 {__LINE__, L"c:\\", L"C:\\", 0, S_OK, 0},
113 {__LINE__, L"C:\\", L"C:\\", 0, S_OK, 0},
114 {__LINE__, L"y:\\", NULL, 0, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), T_PRE_VISTA},
115 {__LINE__, L"y:\\", NULL, 0, HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE), T_VISTA_PLUS},
116 {__LINE__, L"C:\\ ", NULL, 0, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), T_PRE_VISTA},
117 {__LINE__, L"C:\\ ", NULL, 0, E_INVALIDARG, T_WIN8_PLUS},
118 /* Tests for CFSFolder */
119 {__LINE__, L"$", NULL, 0, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 0},
120 {__LINE__, L"c:\\Program Files", L"C:\\Program Files", 0, S_OK, 0},
121 {__LINE__, L"c:\\Program Files\\", L"C:\\Program Files", 0, S_OK, 0},
122 /* Paths with . are valid for win+r dialog or address bar but not for ParseDisplayName */
123 {__LINE__, L"c:\\Program Files\\.", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
124 {__LINE__, L"c:\\Program Files\\..", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS}, /* This gives C:\ when entered in address bar */
125 {__LINE__, L".", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
126 {__LINE__, L"..", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
127 {__LINE__, L"C:\\.", NULL, 0, E_INVALIDARG, T_PRE_WIN7|T_WIN8_PLUS},
128 {__LINE__, L"fonts", NULL, 0, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 0}, /* These three work for ShellExecute */
129 {__LINE__, L"winsxs", NULL, 0, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 0},
130 {__LINE__, L"system32", NULL, 0, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 0}
131};
132
133UINT get_host_os_flag()
134{
135 switch (GetNTVersion())
136 {
137 case _WIN32_WINNT_WIN2K: return T_WIN2K;
138 case _WIN32_WINNT_WINXP: return T_WINXP;
139 case _WIN32_WINNT_WS03: return T_WIN2K3;
140 case _WIN32_WINNT_VISTA: return T_VISTA;
141 case _WIN32_WINNT_WIN7: return T_WIN7;
142 case _WIN32_WINNT_WIN8: return T_WIN8;
143 case _WIN32_WINNT_WINBLUE: return T_WIN8;
144 case _WIN32_WINNT_WIN10: return T_WIN10;
145 }
146
147 return 0;
148}
149
150START_TEST(SHParseDisplayName)
151{
152 HRESULT hr;
153 WCHAR winDir[MAX_PATH];
154 UINT os_flag = get_host_os_flag();
155 ok (os_flag != 0, "Incompatible os version %d!", os_flag);
156 if (os_flag == 0)
157 return;
158
159 IShellFolder *psfDesktop;
160 hr = SHGetDesktopFolder(&psfDesktop);
161 ok(hr == S_OK, "hr = %lx\n", hr);
162
163 GetWindowsDirectoryW(winDir, _countof(winDir));
164 SetCurrentDirectoryW(winDir);
165
166 for (UINT i = 0; i < _countof(Tests); i ++)
167 {
168 if (Tests[i].ValidForVersion && !(Tests[i].ValidForVersion & os_flag))
169 continue;
170
171 PIDLIST_ABSOLUTE pidl;
172 HRESULT hr = SHParseDisplayName(Tests[i].wszPathToParse, NULL, &pidl, 0, NULL);
173 ok(hr == Tests[i].hResult, "%d: Expected error 0x%lx, got 0x%lx\n", Tests[i].testline, Tests[i].hResult, hr);
174
175 if (Tests[i].wszExpectedDisplayName == NULL && Tests[i].nExpectedCSIDL == 0)
176 {
177 ok(pidl == NULL, "%d: Expected no pidl\n", Tests[i].testline);
178 continue;
179 }
180
181 ok(pidl != NULL, "%d: Expected pidl on success\n", Tests[i].testline);
182 if(!pidl)
183 continue;
184
185 STRRET strret;
186 hr = psfDesktop->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strret);
187 ok(hr == S_OK, "%d: hr = %lx\n", Tests[i].testline, hr);
188
189 ok(strret.uType == STRRET_WSTR, "%d: Expected STRRET_WSTR\n", Tests[i].testline);
190
191 if (Tests[i].wszExpectedDisplayName)
192 {
193 ok(!wcscmp(strret.pOleStr, Tests[i].wszExpectedDisplayName), "%d: expected %S got %S\n", Tests[i].testline, Tests[i].wszExpectedDisplayName, strret.pOleStr);
194 }
195 else
196 {
197 PIDLIST_ABSOLUTE pidlSpecial;
198 hr = SHGetSpecialFolderLocation(NULL, Tests[i].nExpectedCSIDL, &pidlSpecial);
199 ok(hr == S_OK, "%d: hr = %lx\n", Tests[i].testline, hr);
200
201 STRRET strretSpecial;
202 hr = psfDesktop->GetDisplayNameOf(pidlSpecial, SHGDN_FORPARSING, &strretSpecial);
203 ok(hr == S_OK, "%d: hr = %lx\n", Tests[i].testline, hr);
204
205 ok(strret.uType == STRRET_WSTR, "%d: Expected STRRET_WSTR\n", Tests[i].testline);
206
207 ok(!wcscmp(strret.pOleStr, strretSpecial.pOleStr), "%d: expected %S got %S\n", Tests[i].testline, strretSpecial.pOleStr, strret.pOleStr);
208 }
209 }
210
211 CoUninitialize();
212}