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