ReactOS 0.4.16-dev-983-g23ad936
ItemIDList.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS API tests
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Test for SHSimpleIDListFromPath
5 * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6 * Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
7 */
8
9#include "shelltest.h"
10#include <shellutils.h>
11
12enum {
13 DIRBIT = 1, FILEBIT = 2,
16};
17
19{
20 // Return the type without the 0x80 flag
21 return pidl && pidl->mkid.cb >= 3 ? (pidl->mkid.abID[0] & 0x7F) : 0;
22}
23
24struct FS95 // FileSystem item header
25{
33
35 {
36 return (p && p->mkid.cb > 2) ? (p->mkid.abID[0] & 0x70) == 0x30 : FALSE;
37 }
39 {
41 return p && p->mkid.cb > FIELD_OFFSET(FS95, name) && IsFS(p) ? (FS95*)p : NULL;
42 }
43};
44
46{
47 C_ASSERT(FIELD_OFFSET(FS95, att) == 12);
48 FS95 *p = FS95::Validate(pidl);
49 return p ? p->att : (UINT(1) << 31);
50}
51
53{
54 STRRET sr;
55 HRESULT hr = pSF->GetDisplayNameOf(pidl, Flags, &sr);
56 if (SUCCEEDED(hr))
57 hr = StrRetToBufW(&sr, pidl, Buf, Cap);
58 return hr;
59}
60
61#define TEST_CLSID(pidl, type, offset, clsid) \
62 do { \
63 ok_long(GetPIDLType(pidl), (type)); \
64 ok_int(*(CLSID*)((&pidl->mkid.abID[(offset) - sizeof(WORD)])) == clsid, TRUE); \
65 } while (0)
66
68{
69 HRESULT hr;
72
73 // We compare pidl1 and pidl2
74 CComHeapPtr<ITEMIDLIST> pidl1(SHSimpleIDListFromPath(szPath));
75 CComHeapPtr<ITEMIDLIST> pidl2(ILCreateFromPathW(szPath));
76
77 // Yes, they are equal logically
78 LPITEMIDLIST pidl1Last = ILFindLastID(pidl1), pidl2Last = ILFindLastID(pidl2);
79 ok_int(ILIsEqual(pidl1, pidl2), TRUE);
80 ok_int(ILIsEqual(pidl1Last, pidl2Last), TRUE);
81
82 // Bind to parent
83 CComPtr<IShellFolder> psf1, psf2;
85 ok_long(hr, S_OK);
87 ok_long(hr, S_OK);
88
89 // Get attributes
90 DWORD attrs1 = SFGAO_FOLDER, attrs2 = SFGAO_FOLDER;
91 hr = (psf1 ? psf1->GetAttributesOf(1, &pidl1Last, &attrs1) : E_UNEXPECTED);
92 ok_long(hr, S_OK);
93 hr = (psf2 ? psf2->GetAttributesOf(1, &pidl2Last, &attrs2) : E_UNEXPECTED);
94 ok_long(hr, S_OK);
95
96 // There is the difference in attributes because SHSimpleIDListFromPath
97 // cannot create PIDLs to folders, only files and drives:
98 ok_long((attrs1 & SFGAO_FOLDER), 0);
99 ok_long((attrs2 & SFGAO_FOLDER), SFGAO_FOLDER);
100
101
102 // Make sure the internal details match Windows NT5+
105 CComHeapPtr<ITEMIDLIST> pidlSys32(SHSimpleIDListFromPath(szPath));
106 if (szPath[1] != ':' || PathFindFileNameW(szPath) <= szPath)
107 {
108 skip("Not a local directory %ls\n", szPath);
109 }
110 else if (!(LPITEMIDLIST)pidlSys32)
111 {
112 skip("?\n");
113 }
114 else
115 {
116 item = ILFindLastID(pidlSys32);
117 ok_long(item->mkid.abID[0] & 0x73, 0x30 | FILEBIT); // This is actually a file PIDL
118 ok_long(FileStruct_Att(item), 0); // Simple PIDL without attributes
119 ok_int(*(UINT*)(&item->mkid.abID[2]), 0); // No size
120
121 ILRemoveLastID(pidlSys32); // Now we should have "c:\Windows"
122 item = ILFindLastID(pidlSys32);
123 ok_long(item->mkid.abID[0] & 0x73, 0x30 | DIRBIT);
124 ok_int(*(UINT*)(&item->mkid.abID[2]), 0); // No size
125 }
126
127 WCHAR drive[4] = { szPath[0], szPath[1], L'\\', L'\0' };
128 CComHeapPtr<ITEMIDLIST> pidlDrive(SHSimpleIDListFromPath(drive));
129 if (drive[1] != ':')
130 {
131 skip("Not a local drive %ls\n", drive);
132 }
133 else if (!(LPITEMIDLIST)pidlDrive)
134 {
135 skip("?\n");
136 }
137 else
138 {
139 item = ILFindLastID(pidlDrive);
140 ok_long(item->mkid.abID[0] & 0x70, 0x20); // Something in My Computer
141 ok_char(item->mkid.abID[1] | 32, drive[0] | 32);
142 }
143
144 CComHeapPtr<ITEMIDLIST> pidlVirt(SHSimpleIDListFromPath(L"x:\\IDontExist"));
145 if (!(LPITEMIDLIST)pidlVirt)
146 {
147 skip("?\n");
148 }
149 else
150 {
151 item = ILFindLastID(pidlVirt);
152 ok_long(item->mkid.abID[0] & 0x73, 0x30 | FILEBIT); // Yes, a file
153 ok_long(FileStruct_Att(item), 0); // Simple PIDL, no attributes
154 ok_int(*(UINT*)(&item->mkid.abID[2]), 0); // No size
155
156 ILRemoveLastID(pidlVirt); // "x:\"
157 item = ILFindLastID(pidlVirt);
158 ok_long(item->mkid.abID[0] & 0x70, 0x20); // Something in My Computer
159 ok_char(item->mkid.abID[1] | 32, 'x' | 32); // x:
160 }
161
162 LPITEMIDLIST pidl;
163 ok_int((pidl = SHSimpleIDListFromPath(L"c:")) != NULL, TRUE);
164 ILFree(pidl);
165 ok_int((pidl = SHSimpleIDListFromPath(L"c:\\")) != NULL, TRUE);
166 ILFree(pidl);
167}
168
170{
173
174 ok_ptr(ILCreateFromPathW(L"c:\\IDontExist"), NULL);
175
177 CComHeapPtr<ITEMIDLIST> pidlDir(ILCreateFromPathW(szPath));
178 if (szPath[1] != ':' || PathFindFileNameW(szPath) <= szPath)
179 {
180 skip("Not a local directory %ls\n", szPath);
181 }
182 else if (!(LPITEMIDLIST)pidlDir)
183 {
184 skip("?\n");
185 }
186 else
187 {
188 item = ILFindLastID(pidlDir);
189 ok_long(item->mkid.abID[0] & 0x73, 0x30 | DIRBIT);
190 ok_int(*(UINT*)(&item->mkid.abID[2]), 0); // No size
191 }
192 PathAppendW(szPath, L"kernel32.dll");
193 CComHeapPtr<ITEMIDLIST> pidlFile(ILCreateFromPathW(szPath));
194 if (!(LPITEMIDLIST)pidlFile)
195 {
196 skip("?\n");
197 }
198 else
199 {
200 item = ILFindLastID(pidlFile);
201 ok_long(item->mkid.abID[0] & 0x73, 0x30 | FILEBIT);
202 ok_int(*(UINT*)(&item->mkid.abID[2]) > 1024 * 42, TRUE); // At least this large
203 }
204}
205
207{
208 CCoInit ComInit;
209 LPITEMIDLIST pidl;
210
212 if (pidl)
213 TEST_CLSID(ILFindLastID(pidl), 0x1f, 4, CLSID_MyComputer);
214 else
215 skip("?\n");
216 ILFree(pidl);
217
219 if (pidl)
220 TEST_CLSID(ILFindLastID(pidl), 0x71, 14, CLSID_Printers);
221 else
222 skip("?\n");
223 ILFree(pidl);
224
225
226 CComPtr<IShellFolder> pInternet;
227 HRESULT hr = SHCoCreateInstance(NULL, &CLSID_Internet, NULL, IID_PPV_ARG(IShellFolder, &pInternet));
228 if (SUCCEEDED(hr))
229 {
230 PCWSTR pszUrl = L"http://example.com/page?query&foo=bar";
231 PIDLIST_RELATIVE pidlUrl;
232 hr = pInternet->ParseDisplayName(NULL, NULL, const_cast<PWSTR>(pszUrl), NULL, &pidlUrl, NULL);
233 ok_long(hr, S_OK);
234 if (hr == S_OK)
235 {
236 ok_int(pidlUrl->mkid.abID[0], PT_INTERNET_URL);
238 hr = GetDisplayNameOf(pInternet, pidlUrl, SHGDN_FORPARSING, buf, _countof(buf));
239 ok_long(hr, S_OK);
240 if (SUCCEEDED(hr))
241 {
242 ok(!lstrcmpiW(buf, pszUrl), "FORPARSING must match URL\n");
243 }
244 ILFree(pidlUrl);
245 }
246 }
247}
248
250{
251 LPITEMIDLIST p1, p2, pidl;
252
253 p1 = p2 = NULL;
254 ok_int(ILIsEqual(p1, p2), TRUE);
255
256 ITEMIDLIST emptyitem = {}, emptyitem2 = {};
257 ok_int(ILIsEqual(&emptyitem, &emptyitem2), TRUE);
258
259 ok_int(ILIsEqual(NULL, &emptyitem), FALSE); // These two are not equal for some reason
260
263 if (p1 && p2)
264 {
265 ok_int(ILIsEqual(p1, p2), TRUE);
266 p1->mkid.abID[0] = PT_COMPUTER_REGITEM; // RegItem in wrong parent
267 ok_int(ILIsEqual(p1, p2), FALSE);
268 }
269 else
270 {
271 skip("Unable to initialize test\n");
272 }
273 ILFree(p1);
274 ILFree(p2);
275
276 // ILIsParent must compare like ILIsEqual
277 p1 = SHSimpleIDListFromPath(L"c:\\");
278 p2 = SHSimpleIDListFromPath(L"c:\\dir\\file");
279 if (p1 && p2)
280 {
281 ok_int(ILIsParent(NULL, p1, FALSE), FALSE); // NULL is always false
282 ok_int(ILIsParent(p1, NULL, FALSE), FALSE); // NULL is always false
283 ok_int(ILIsParent(NULL, NULL, FALSE), FALSE); // NULL is always false
284 ok_int(ILIsParent(p1, p1, FALSE), TRUE); // I'm my own parent
285 ok_int(ILIsParent(p1, p1, TRUE), FALSE); // Self is not immediate
286 ok_int(ILIsParent(p1, p2, FALSE), TRUE); // Grandchild
287 ok_int(ILIsParent(p1, p2, TRUE), FALSE); // Grandchild is not immediate
288 ok_ptr(ILFindChild(p1, p2), ILGetNext(ILGetNext(p2))); // Child is "dir\\file", skip MyComputer and C:
289 ok_int(ILIsEmpty(pidl = ILFindChild(p1, p1)) && pidl, TRUE); // Self
290 ILRemoveLastID(p2);
291 ok_int(ILIsParent(p1, p2, TRUE), TRUE); // Immediate child
292
293 p1->mkid.abID[0] = PT_COMPUTER_REGITEM; // RegItem in wrong parent
294 ok_int(ILIsParent(p1, p2, FALSE), FALSE);
295 }
296 else
297 {
298 skip("Unable to initialize test\n");
299 }
300 ILFree(p1);
301 ILFree(p2);
302}
static HRESULT GetDisplayNameOf(IShellFolder *pSF, LPCITEMIDLIST pidl, UINT Flags, PWSTR Buf, UINT Cap)
Definition: ItemIDList.cpp:52
static int FileStruct_Att(LPCITEMIDLIST pidl)
Definition: ItemIDList.cpp:45
static BYTE GetPIDLType(LPCITEMIDLIST pidl)
Definition: ItemIDList.cpp:18
#define TEST_CLSID(pidl, type, offset, clsid)
Definition: ItemIDList.cpp:61
@ PT_INTERNET_URL
Definition: ItemIDList.cpp:15
@ FILEBIT
Definition: ItemIDList.cpp:13
@ PT_COMPUTER_REGITEM
Definition: ItemIDList.cpp:14
@ DIRBIT
Definition: ItemIDList.cpp:13
#define ok_long(expression, result)
Definition: atltest.h:133
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define ok_char(expression, result)
Definition: atltest.h:122
#define START_TEST(x)
Definition: atltest.h:75
#define ok_int(expression, result)
Definition: atltest.h:134
#define ok_ptr(expression, result)
Definition: atltest.h:108
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define MAX_PATH
Definition: compat.h:34
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4262
HRESULT WINAPI SHCoCreateInstance(LPCWSTR aclsid, const CLSID *clsid, LPUNKNOWN pUnkOuter, REFIID refiid, LPVOID *ppv)
Definition: shellole.c:105
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:394
HRESULT WINAPI StrRetToBufW(LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, UINT len)
Definition: string.c:1530
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
HRESULT GetDisplayNameOf([in] PCUITEMID_CHILD pidl, [in] SHGDNF uFlags, [out] STRRET *lpName)
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define C_ASSERT(e)
Definition: intsafe.h:73
LPCWSTR szPath
Definition: env.c:37
static ATOM item
Definition: dde.c:856
unsigned int UINT
Definition: ndis.h:50
#define L(x)
Definition: ntvdm.h:50
#define PathAppendW
Definition: pathcch.h:309
LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner, int nFolder, BOOL fCreate)
Definition: pidl.c:445
void WINAPI ILFree(LPITEMIDLIST pidl)
Definition: pidl.c:1044
LPITEMIDLIST WINAPI ILFindLastID(LPCITEMIDLIST pidl)
Definition: pidl.c:198
BOOL WINAPI ILIsParent(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate)
Definition: pidl.c:697
BOOL WINAPI ILRemoveLastID(LPITEMIDLIST pidl)
Definition: pidl.c:221
HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
Definition: pidl.c:1462
LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl)
Definition: pidl.c:970
PUIDLIST_RELATIVE WINAPI ILFindChild(PIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
Definition: pidl.c:750
LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path)
Definition: pidl.c:1101
BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
Definition: pidl.c:582
HRESULT hr
Definition: shlfolder.c:183
#define ILCreateFromPath
Definition: shlobj.h:2514
#define CSIDL_PRINTERS
Definition: shlobj.h:2185
static BOOL ILIsEmpty(_In_opt_ PCUIDLIST_RELATIVE pidl)
Definition: shlobj.h:2527
PIDLIST_ABSOLUTE WINAPI SHSimpleIDListFromPath(PCWSTR)
#define CSIDL_DRIVES
Definition: shlobj.h:2197
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h:70
COM Initialisation.
Definition: shellclasses.h:179
WORD time
Definition: ItemIDList.cpp:30
WORD att
Definition: ItemIDList.cpp:31
BYTE unknown
Definition: ItemIDList.cpp:28
WORD cb
Definition: ItemIDList.cpp:26
BYTE type
Definition: ItemIDList.cpp:27
static FS95 * Validate(LPCITEMIDLIST p)
Definition: ItemIDList.cpp:38
WORD date
Definition: ItemIDList.cpp:30
UINT size
Definition: ItemIDList.cpp:29
static BOOL IsFS(LPCITEMIDLIST p)
Definition: ItemIDList.cpp:34
BYTE abID[1]
Definition: shtypes.idl:28
SHITEMID mkid
Definition: shtypes.idl:34
Definition: name.c:39
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define ANYSIZE_ARRAY
Definition: typedefs.h:46
#define E_UNEXPECTED
Definition: winerror.h:2456
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define IID_PPV_ARG(Itype, ppType)
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193