ReactOS 0.4.17-dev-116-ga4b6fe9
IStreamPidl.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS api tests
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Tests for g_fnIStream_ReadPidl and g_fnIStream_WritePidl
5 * COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#include <apitest.h>
9#include <shlwapi.h>
10#include <shlobj.h>
11#include <shlwapi_undoc.h>
12
16
20
21static LPITEMIDLIST MakeSimplePidl(const BYTE *data, UINT dataLen)
22{
23 UINT cbItem = (UINT)(sizeof(USHORT) + dataLen);
24 UINT cbTotal = cbItem + sizeof(USHORT);
26 if (!pidl)
27 return NULL;
28 ZeroMemory(pidl, cbTotal);
29 pidl->mkid.cb = (USHORT)cbItem;
30 if (dataLen)
31 memcpy(pidl->mkid.abID, data, dataLen);
32 return pidl;
33}
34
35static void RewindStream(IStream *pstm)
36{
38 li.QuadPart = 0;
39 pstm->Seek(li, STREAM_SEEK_SET, NULL);
40}
41
43{
44 const BYTE data[] = {0x11, 0x22, 0x33};
45 LPITEMIDLIST pidlSrc = MakeSimplePidl(data, sizeof(data));
46 LPITEMIDLIST pidlDst = NULL;
47 HRESULT hr;
48 IStream *pstm;
49
50 ok(pidlSrc != NULL, "pidlSrc was NULL.\n");
51 if (!pidlSrc)
52 {
53 skip("pidlSrc was NULL.\n");
54 return;
55 }
56
57 pstm = SHCreateMemStream(NULL, 0);
58 ok(pstm != NULL, "pstm was NULL.\n");
59 if (!pstm)
60 {
61 skip("pstm was NULL.\n");
62 return;
63 }
64
65 hr = g_fnIStream_WritePidl(pstm, pidlSrc);
66 ok_hr(hr, S_OK);
67
68 RewindStream(pstm);
69 hr = g_fnIStream_ReadPidl(pstm, &pidlDst);
70 ok_hr(hr, S_OK);
71 ok(pidlDst != NULL, "pidlDst was NULL\n");
72
73 if (pidlDst)
74 {
75 UINT cbSrc = g_fnILGetSize(pidlSrc);
76 UINT cbDst = g_fnILGetSize(pidlDst);
77 ok_int(cbSrc, cbDst);
78 ok_int(memcmp(pidlSrc, pidlDst, cbSrc), 0);
79 CoTaskMemFree(pidlDst);
80 }
81
82 pstm->Release();
83 CoTaskMemFree(pidlSrc);
84}
85
86static void Test_RoundTrip_EmptyPidl(void)
87{
89 LPITEMIDLIST pidlDst = NULL;
90 HRESULT hr;
91 IStream *pstm;
92
93 ok(pidlSrc != NULL, "CoTaskMemAlloc failed\n");
94 if (!pidlSrc)
95 {
96 skip("pidlSrc was NULL\n");
97 return;
98 }
99
100 ZeroMemory(pidlSrc, sizeof(USHORT));
101
102 pstm = SHCreateMemStream(NULL, 0);
103 ok(pstm != NULL, "pstm was NULL\n");
104 if (!pstm)
105 {
106 skip("pstm was NULL\n");
107 return;
108 }
109
110 hr = g_fnIStream_WritePidl(pstm, pidlSrc);
111 ok_hr(hr, S_OK);
112
113 RewindStream(pstm);
114 hr = g_fnIStream_ReadPidl(pstm, &pidlDst);
115 ok_hr(hr, S_OK);
116 ok(pidlDst != NULL, "pidlDst was NULL\n");
117
118 if (pidlDst)
119 {
120 UINT cbSrc = g_fnILGetSize(pidlSrc);
121 UINT cbDst = g_fnILGetSize(pidlDst);
122 ok_int(cbSrc, cbDst);
123 ok_int(memcmp(pidlSrc, pidlDst, cbSrc), 0);
124 CoTaskMemFree(pidlDst);
125 }
126
127 pstm->Release();
128 CoTaskMemFree(pidlSrc);
129}
130
132{
133 UINT cbTotal = 4 + 5 + 2;
134 LPITEMIDLIST pidlSrc = (LPITEMIDLIST)CoTaskMemAlloc(cbTotal);
135 LPITEMIDLIST pidlDst = NULL;
136 PBYTE p;
137 HRESULT hr;
138 IStream *pstm;
139
140 ok(pidlSrc != NULL, "CoTaskMemAlloc failed\n");
141 if (!pidlSrc)
142 {
143 skip("pidlSrc was NULL\n");
144 return;
145 }
146
147 ZeroMemory(pidlSrc, cbTotal);
148 p = (PBYTE)pidlSrc;
149
150 *(USHORT *)p = 4; p += 2;
151 *p++ = 0xAA; *p++ = 0xBB;
152
153 *(USHORT *)p = 5; p += 2;
154 *p++ = 0x01; *p++ = 0x02; *p++ = 0x03;
155
156 pstm = SHCreateMemStream(NULL, 0);
157 ok(pstm != NULL, "pstm was NULL\n");
158 if (!pstm)
159 {
160 skip("pstm was NULL\n");
161 return;
162 }
163
164 hr = g_fnIStream_WritePidl(pstm, pidlSrc);
165 ok_hr(hr, S_OK);
166
167 RewindStream(pstm);
168 hr = g_fnIStream_ReadPidl(pstm, &pidlDst);
169 ok_hr(hr, S_OK);
170 ok(pidlDst != NULL, "pidlDst was NULL\n");
171
172 if (pidlDst)
173 {
174 ok_int(g_fnILGetSize(pidlSrc), g_fnILGetSize(pidlDst));
175 ok_int(memcmp(pidlSrc, pidlDst, g_fnILGetSize(pidlSrc)), 0);
176 CoTaskMemFree(pidlDst);
177 }
178
179 pstm->Release();
180 CoTaskMemFree(pidlSrc);
181}
182
183static void Test_Read_EmptyStream(void)
184{
185 IStream *pstm = SHCreateMemStream(NULL, 0);
186 LPITEMIDLIST pidl = NULL;
187 HRESULT hr;
188
189 ok(pstm != NULL, "pstm was NULL\n");
190 if (!pstm)
191 {
192 skip("pstm was NULL\n");
193 return;
194 }
195
196 hr = g_fnIStream_ReadPidl(pstm, &pidl);
197 ok(FAILED(hr), "hr was wrongly succeeded\n");
198 ok(pidl == NULL, "pidl was not NULL\n");
199
200 pstm->Release();
201}
202
204{
205 IStream *pstm = SHCreateMemStream(NULL, 0);
206 LPITEMIDLIST pidl = NULL;
207 UINT cbSize = 1;
208 ULONG cbWritten;
209 HRESULT hr;
210
211 ok(pstm != NULL, "pstm was NULL.\n");
212 if (!pstm)
213 {
214 skip("pstm was NULL.\n");
215 return;
216 }
217
218 pstm->Write(&cbSize, sizeof(cbSize), &cbWritten);
219
220 RewindStream(pstm);
221 hr = g_fnIStream_ReadPidl(pstm, &pidl);
222 ok(FAILED(hr), "hr was 0x%X\n", hr);
223 ok(pidl == NULL, "pidl was not NULL\n");
224
225 pstm->Release();
226}
227
228static void Test_Read_TruncatedData(void)
229{
230 IStream *pstm = SHCreateMemStream(NULL, 0);
231 LPITEMIDLIST pidl = NULL;
232 UINT cbSize = 100;
233 ULONG cbWritten;
234 HRESULT hr;
235
236 ok(pstm != NULL, "pstm was NULL.\n");
237 if (!pstm)
238 {
239 skip("pstm was NULL.\n");
240 return;
241 }
242
243 pstm->Write(&cbSize, sizeof(cbSize), &cbWritten);
244
245 RewindStream(pstm);
246 hr = g_fnIStream_ReadPidl(pstm, &pidl);
247 ok(FAILED(hr), "hr was 0x%X\n", hr);
248 ok(pidl == NULL, "pidl was not NULL\n");
249
250 pstm->Release();
251}
252
254{
255 IStream *pstm = SHCreateMemStream(NULL, 0);
256 LPITEMIDLIST pidl = NULL;
257 UINT cbSize = 4;
258 BYTE rawData[4] = {0x04, 0x00, 0x11, 0x22};
259 ULONG cbWritten;
260 HRESULT hr;
261
262 ok(pstm != NULL, "pstm was NULL.\n");
263 if (!pstm)
264 {
265 skip("pstm was NULL.\n");
266 return;
267 }
268
269 pstm->Write(&cbSize, sizeof(cbSize), &cbWritten);
270 pstm->Write(rawData, cbSize, &cbWritten);
271
272 RewindStream(pstm);
273 hr = g_fnIStream_ReadPidl(pstm, &pidl);
274 ok(FAILED(hr), "hr was 0x%X\n", hr);
275 ok(pidl == NULL, "pidl was not NULL\n");
276
277 pstm->Release();
278}
279
281{
282 const BYTE data[] = {0xDE, 0xAD};
283 LPITEMIDLIST pidlSrc = MakeSimplePidl(data, sizeof(data));
284 IStream *pstm = SHCreateMemStream(NULL, 0);
287 HRESULT hr;
288 UINT expectedPos;
289
290 ok(pidlSrc != NULL, "pidlSrc was NULL\n");
291 if (!pidlSrc)
292 {
293 skip("pidlSrc was NULL\n");
294 return;
295 }
296
297 ok(pstm != NULL, "pstm was NULL.\n");
298 if (!pstm)
299 {
300 skip("pstm was NULL.\n");
301 return;
302 }
303
304 zero.QuadPart = 0;
305
306 hr = g_fnIStream_WritePidl(pstm, pidlSrc);
307 ok_hr(hr, S_OK);
308
309 pstm->Seek(zero, STREAM_SEEK_CUR, &pos);
310
311 expectedPos = sizeof(UINT) + g_fnILGetSize(pidlSrc);
312 ok_eq_longlong(pos.QuadPart, expectedPos);
313
314 pstm->Release();
315 CoTaskMemFree(pidlSrc);
316}
317
319{
320 IStream *pstm = SHCreateMemStream(NULL, 0);
321 LPITEMIDLIST pidl = (LPITEMIDLIST)UlongToPtr(0xDEADBEEF);
322 HRESULT hr;
323
324 ok(pstm != NULL, "pstm was NULL.\n");
325 if (!pstm)
326 {
327 skip("pstm was NULL.\n");
328 return;
329 }
330
331 hr = g_fnIStream_ReadPidl(pstm, &pidl);
332 ok(FAILED(hr), "hr was 0x%X\n", hr);
333 ok(pidl == NULL, "pidl was not NULL\n");
334
335 pstm->Release();
336}
337
338START_TEST(IStreamPidl)
339{
340 HINSTANCE hSHLWAPI = LoadLibraryW(L"shlwapi");
341 if (!hSHLWAPI)
342 {
343 skip("shlwapi not found\n");
344 return;
345 }
346
350 {
351 skip("IStream_ReadPidl or IStream_WritePidl not found\n");
352 FreeLibrary(hSHLWAPI);
353 return;
354 }
355
356 HINSTANCE hSHELL32 = LoadLibraryW(L"shell32");
357 if (!hSHELL32)
358 {
359 skip("shell32 not found\n");
360 FreeLibrary(hSHLWAPI);
361 return;
362 }
363
364 g_fnILGetSize = (FN_ILGetSize)GetProcAddress(hSHELL32, "ILGetSize");
365 if (!g_fnILGetSize)
366 {
367 skip("ILGetSize not found\n");
368 FreeLibrary(hSHELL32);
369 FreeLibrary(hSHLWAPI);
370 return;
371 }
372
373 HRESULT hrCoInit = CoInitialize(NULL);
374
384
385 if (SUCCEEDED(hrCoInit))
387
388 FreeLibrary(hSHELL32);
389 FreeLibrary(hSHLWAPI);
390}
#define ok_hr(status, expected)
Definition: ACListISF.cpp:31
static void RewindStream(IStream *pstm)
Definition: IStreamPidl.cpp:35
UINT(WINAPI * FN_ILGetSize)(LPCITEMIDLIST)
Definition: IStreamPidl.cpp:15
static FN_IStream_WritePidl g_fnIStream_WritePidl
Definition: IStreamPidl.cpp:18
static void Test_RoundTrip_MultiItemPidl(void)
static FN_IStream_ReadPidl g_fnIStream_ReadPidl
Definition: IStreamPidl.cpp:17
HRESULT(WINAPI * FN_IStream_WritePidl)(IStream *, LPCITEMIDLIST)
Definition: IStreamPidl.cpp:14
static void Test_RoundTrip_EmptyPidl(void)
Definition: IStreamPidl.cpp:86
static FN_ILGetSize g_fnILGetSize
Definition: IStreamPidl.cpp:19
static void Test_Write_StreamPosition(void)
static void Test_Read_EmptyStream(void)
static LPITEMIDLIST MakeSimplePidl(const BYTE *data, UINT dataLen)
Definition: IStreamPidl.cpp:21
HRESULT(WINAPI * FN_IStream_ReadPidl)(IStream *, _Out_ LPITEMIDLIST *)
Definition: IStreamPidl.cpp:13
static void Test_RoundTrip_SimplePidl(void)
Definition: IStreamPidl.cpp:42
static void Test_Read_TruncatedData(void)
static void Test_Read_OutputNullOnFailure(void)
static void Test_Read_MissingTerminator(void)
static void Test_Read_TooSmallCbSize(void)
#define ok_eq_longlong(value, expected)
Definition: apitest.h:121
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_int(expression, result)
Definition: atltest.h:134
HRESULT hr
Definition: delayimp.cpp:573
#define NULL
Definition: types.h:112
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: combase.c:2842
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
#define LoadLibraryW(x)
Definition: compat.h:747
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:531
#define L(x)
Definition: resources.c:13
#define UlongToPtr(u)
Definition: config.h:106
LARGE_INTEGER li
Definition: fxtimerapi.cpp:235
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLfloat GLfloat p
Definition: glext.h:8902
HRESULT Write([in, size_is(cb)] const void *pv, [in] ULONG cb, [out] ULONG *pcbWritten)
HRESULT Seek([in] LARGE_INTEGER dlibMove, [in] DWORD dwOrigin, [out] ULARGE_INTEGER *plibNewPosition)
ULONG Release()
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
void *WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: malloc.c:381
void WINAPI CoTaskMemFree(void *ptr)
Definition: malloc.c:389
#define ZeroMemory
Definition: minwinbase.h:31
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static unsigned char rawData[2356]
Definition: data.c:573
unsigned int UINT
Definition: ndis.h:50
#define _Out_
Definition: no_sal2.h:160
BYTE * PBYTE
Definition: pedump.c:66
unsigned short USHORT
Definition: pedump.c:61
IStream *WINAPI SHCreateMemStream(const BYTE *lpbData, UINT dwDataLen)
Definition: regstream.c:652
int zero
Definition: sehframes.cpp:29
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define MAKEINTRESOURCEA(i)
Definition: winuser.h:581
unsigned char BYTE
Definition: xxhash.c:193