b72214533bba14a42310fa48f507f15067c09981
2 * Unit tests for DPA functions
4 * Copyright 2003 Uwe Bonnes
5 * Copyright 2005 Felix Nawothnig
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
26 typedef struct _STREAMDATA
31 } STREAMDATA
, *PSTREAMDATA
;
33 static HDPA (WINAPI
*pDPA_Clone
)(const HDPA
,HDPA
);
34 static HDPA (WINAPI
*pDPA_Create
)(INT
);
35 static HDPA (WINAPI
*pDPA_CreateEx
)(INT
,HANDLE
);
36 static PVOID (WINAPI
*pDPA_DeleteAllPtrs
)(HDPA
);
37 static PVOID (WINAPI
*pDPA_DeletePtr
)(HDPA
,INT
);
38 static BOOL (WINAPI
*pDPA_Destroy
)(HDPA
);
39 static VOID (WINAPI
*pDPA_DestroyCallback
)(HDPA
,PFNDPAENUMCALLBACK
,PVOID
);
40 static VOID (WINAPI
*pDPA_EnumCallback
)(HDPA
,PFNDPAENUMCALLBACK
,PVOID
);
41 static INT (WINAPI
*pDPA_GetPtr
)(HDPA
,INT
);
42 static INT (WINAPI
*pDPA_GetPtrIndex
)(HDPA
,PVOID
);
43 static BOOL (WINAPI
*pDPA_Grow
)(HDPA
,INT
);
44 static INT (WINAPI
*pDPA_InsertPtr
)(HDPA
,INT
,PVOID
);
45 static HRESULT (WINAPI
*pDPA_LoadStream
)(HDPA
*,PFNDPASTREAM
,IStream
*,LPVOID
);
46 static BOOL (WINAPI
*pDPA_Merge
)(HDPA
,HDPA
,DWORD
,PFNDPACOMPARE
,PFNDPAMERGE
,LPARAM
);
47 static HRESULT (WINAPI
*pDPA_SaveStream
)(HDPA
,PFNDPASTREAM
,IStream
*,LPVOID
);
48 static INT (WINAPI
*pDPA_Search
)(HDPA
,PVOID
,INT
,PFNDPACOMPARE
,LPARAM
,UINT
);
49 static BOOL (WINAPI
*pDPA_SetPtr
)(HDPA
,INT
,PVOID
);
50 static BOOL (WINAPI
*pDPA_Sort
)(HDPA
,PFNDPACOMPARE
,LPARAM
);
52 #define COMCTL32_GET_PROC(func, ord) \
53 ((p ## func = (PVOID)GetProcAddress(hcomctl32,(LPCSTR)ord)) ? 1 \
54 : (trace( #func " not exported\n"), 0))
56 static BOOL
InitFunctionPtrs(HMODULE hcomctl32
)
59 if(COMCTL32_GET_PROC(DPA_Clone
, 331) &&
60 COMCTL32_GET_PROC(DPA_Create
, 328) &&
61 COMCTL32_GET_PROC(DPA_CreateEx
, 340) &&
62 COMCTL32_GET_PROC(DPA_DeleteAllPtrs
, 337) &&
63 COMCTL32_GET_PROC(DPA_DeletePtr
, 336) &&
64 COMCTL32_GET_PROC(DPA_Destroy
, 329) &&
65 COMCTL32_GET_PROC(DPA_GetPtr
, 332) &&
66 COMCTL32_GET_PROC(DPA_GetPtrIndex
, 333) &&
67 COMCTL32_GET_PROC(DPA_Grow
, 330) &&
68 COMCTL32_GET_PROC(DPA_InsertPtr
, 334) &&
69 COMCTL32_GET_PROC(DPA_Search
, 339) &&
70 COMCTL32_GET_PROC(DPA_SetPtr
, 335) &&
71 COMCTL32_GET_PROC(DPA_Sort
, 338))
74 COMCTL32_GET_PROC(DPA_DestroyCallback
, 386) &&
75 COMCTL32_GET_PROC(DPA_EnumCallback
, 385) &&
76 COMCTL32_GET_PROC(DPA_LoadStream
, 9) &&
77 COMCTL32_GET_PROC(DPA_Merge
, 11) &&
78 COMCTL32_GET_PROC(DPA_SaveStream
, 10);
87 static INT CALLBACK
CB_CmpLT(PVOID p1
, PVOID p2
, LPARAM lp
)
89 ok(lp
== 0x1abe11ed, "lp=%ld\n", lp
);
90 return p1
< p2
? -1 : p1
> p2
? 1 : 0;
93 static INT CALLBACK
CB_CmpGT(PVOID p1
, PVOID p2
, LPARAM lp
)
95 ok(lp
== 0x1abe11ed, "lp=%ld\n", lp
);
96 return p1
> p2
? -1 : p1
< p2
? 1 : 0;
99 /* merge callback messages counter
103 static INT nMessages
[4];
105 static PVOID CALLBACK
CB_MergeInsertSrc(UINT op
, PVOID p1
, PVOID p2
, LPARAM lp
)
108 ok(lp
== 0x1abe11ed, "lp=%ld\n", lp
);
112 static PVOID CALLBACK
CB_MergeDeleteOddSrc(UINT op
, PVOID p1
, PVOID p2
, LPARAM lp
)
115 ok(lp
== 0x1abe11ed, "lp=%ld\n", lp
);
116 return ((PCHAR
)p2
)+1;
121 static INT CALLBACK
CB_EnumFirstThree(PVOID pItem
, PVOID lp
)
125 i
= pDPA_GetPtrIndex(lp
, pItem
);
126 ok(i
== nEnum
, "i=%d nEnum=%d\n", i
, nEnum
);
128 pDPA_SetPtr(lp
, i
, (PVOID
)7);
129 return pItem
!= (PVOID
)3;
132 static HRESULT CALLBACK
CB_Save(DPASTREAMINFO
*pInfo
, IStream
*pStm
, LPVOID lp
)
136 ok(lp
== (LPVOID
)0xdeadbeef, "lp=%p\n", lp
);
137 hRes
= IStream_Write(pStm
, &pInfo
->iPos
, sizeof(INT
), NULL
);
139 hRes
= IStream_Write(pStm
, &pInfo
->pvItem
, sizeof(PVOID
), NULL
);
144 static HRESULT CALLBACK
CB_Load(DPASTREAMINFO
*pInfo
, IStream
*pStm
, LPVOID lp
)
149 iOldPos
= pInfo
->iPos
;
150 ok(lp
== (LPVOID
)0xdeadbeef, "lp=%p\n", lp
);
151 hRes
= IStream_Read(pStm
, &pInfo
->iPos
, sizeof(INT
), NULL
);
153 ok(pInfo
->iPos
== iOldPos
, "iPos=%d iOldPos=%d\n", pInfo
->iPos
, iOldPos
);
154 hRes
= IStream_Read(pStm
, &pInfo
->pvItem
, sizeof(PVOID
), NULL
);
159 static BOOL
CheckDPA(HDPA dpa
, DWORD dwIn
, PDWORD pdwOut
)
166 ULONG_PTR ulItem
= (ULONG_PTR
)pDPA_GetPtr(dpa
, i
++);
168 dwOut
= dwOut
<< 4 | (ulItem
& 0xf);
175 pDPA_DeleteAllPtrs(dpa
);
179 pDPA_InsertPtr(dpa
, 0, (PVOID
)(ULONG_PTR
)(dwIn
& 0xf));
190 static void test_dpa(void)
194 HDPA dpa
, dpa2
, dpa3
;
201 hHeap
= HeapCreate(0, 1, 2);
202 ok(hHeap
!= NULL
, "error=%d\n", GetLastError());
203 dpa3
= pDPA_CreateEx(0, hHeap
);
204 ok(dpa3
!= NULL
, "\n");
205 ret
= pDPA_Grow(dpa3
, si
.dwPageSize
+ 1);
206 ok(!ret
&& GetLastError() == ERROR_NOT_ENOUGH_MEMORY
,
207 "ret=%d error=%d\n", ret
, GetLastError());
209 dpa
= pDPA_Create(0);
210 ok(dpa
!= NULL
, "\n");
212 /* Set item with out of bound index */
213 ok(pDPA_SetPtr(dpa
, 1, (PVOID
)6), "\n");
214 /* Fill the created gap */
215 ok(pDPA_SetPtr(dpa
, 0, (PVOID
)5), "\n");
216 rc
=CheckDPA(dpa
, 0x56, &dw
);
217 ok(rc
, "dw=0x%x\n", dw
);
220 ret
= pDPA_InsertPtr(dpa
, 1, (PVOID
)1);
221 ok(ret
== 1, "ret=%d\n", ret
);
222 /* Append item using correct index */
223 ret
= pDPA_InsertPtr(dpa
, 3, (PVOID
)3);
224 ok(ret
== 3, "ret=%d\n", ret
);
225 /* Append item using out of bound index */
226 ret
= pDPA_InsertPtr(dpa
, 5, (PVOID
)2);
227 ok(ret
== 4, "ret=%d\n", ret
);
228 /* Append item using DPA_APPEND */
229 ret
= pDPA_InsertPtr(dpa
, DPA_APPEND
, (PVOID
)4);
230 ok(ret
== 5, "ret=%d\n", ret
);
232 rc
=CheckDPA(dpa
, 0x516324, &dw
);
233 ok(rc
, "dw=0x%x\n", dw
);
235 for(i
= 1; i
<= 6; i
++)
238 k
= pDPA_GetPtrIndex(dpa
, (PVOID
)(INT_PTR
)i
);
239 /* Linear searches should work on unsorted DPAs */
240 j
= pDPA_Search(dpa
, (PVOID
)(INT_PTR
)i
, 0, CB_CmpLT
, 0x1abe11ed, 0);
241 ok(j
== k
, "j=%d k=%d\n", j
, k
);
245 ok(pDPA_Sort(dpa
, CB_CmpGT
, 0x1abe11ed), "\n");
246 rc
=CheckDPA(dpa
, 0x654321, &dw
);
247 ok(rc
, "dw=0x%x\n", dw
);
249 /* Clone into a new DPA */
250 dpa2
= pDPA_Clone(dpa
, NULL
);
251 ok(dpa2
!= NULL
, "\n");
252 /* The old data should have been preserved */
253 rc
=CheckDPA(dpa2
, 0x654321, &dw2
);
254 ok(rc
, "dw=0x%x\n", dw2
);
255 ok(pDPA_Sort(dpa
, CB_CmpLT
, 0x1abe11ed), "\n");
257 /* Test if the DPA itself was really copied */
258 rc
=CheckDPA(dpa
, 0x123456, &dw
);
259 ok(rc
, "dw=0x%x\n", dw
);
260 rc
=CheckDPA(dpa2
, 0x654321, &dw2
);
261 ok(rc
, "dw2=0x%x\n", dw2
);
263 /* Clone into an old DPA */
264 SetLastError(ERROR_SUCCESS
);
265 p
= pDPA_Clone(dpa
, dpa3
);
266 ok(p
== dpa3
, "p=%p\n", p
);
267 rc
=CheckDPA(dpa3
, 0x123456, &dw3
);
268 ok(rc
, "dw3=0x%x\n", dw3
);
270 for(i
= 1; i
<= 6; i
++)
274 /* The array is in order so ptr == index+1 */
275 j
= pDPA_GetPtrIndex(dpa
, (PVOID
)(INT_PTR
)i
);
276 ok(j
+1 == i
, "j=%d i=%d\n", j
, i
);
277 j
= pDPA_Search(dpa
, (PVOID
)(INT_PTR
)i
, 0, CB_CmpLT
, 0x1abe11ed, DPAS_SORTED
);
278 ok(j
+1 == i
, "j=%d i=%d\n", j
, i
);
280 /* Linear searches respect iStart ... */
281 j
= pDPA_Search(dpa
, (PVOID
)(INT_PTR
)i
, i
+1, CB_CmpLT
, 0x1abe11ed, 0);
282 ok(j
== DPA_ERR
, "j=%d\n", j
);
283 /* ... but for a binary search it's ignored */
284 j
= pDPA_Search(dpa
, (PVOID
)(INT_PTR
)i
, i
+1, CB_CmpLT
, 0x1abe11ed, DPAS_SORTED
);
285 ok(j
+1 == i
, "j=%d i=%d\n", j
, i
);
288 /* Try to get the index of a nonexistent item */
289 i
= pDPA_GetPtrIndex(dpa
, (PVOID
)7);
290 ok(i
== DPA_ERR
, "i=%d\n", i
);
292 /* Try to delete out of bound indexes */
293 p
= pDPA_DeletePtr(dpa
, -1);
294 ok(p
== NULL
, "p=%p\n", p
);
295 p
= pDPA_DeletePtr(dpa
, 6);
296 ok(p
== NULL
, "p=%p\n", p
);
298 /* Delete the third item */
299 p
= pDPA_DeletePtr(dpa
, 2);
300 ok(p
== (PVOID
)3, "p=%p\n", p
);
301 rc
=CheckDPA(dpa
, 0x12456, &dw
);
302 ok(rc
, "dw=0x%x\n", dw
);
304 /* Check where to re-insert the deleted item */
305 i
= pDPA_Search(dpa
, (PVOID
)3, 0,
306 CB_CmpLT
, 0x1abe11ed, DPAS_SORTED
|DPAS_INSERTAFTER
);
307 ok(i
== 2, "i=%d\n", i
);
308 /* DPAS_INSERTBEFORE works just like DPAS_INSERTAFTER */
309 i
= pDPA_Search(dpa
, (PVOID
)3, 0,
310 CB_CmpLT
, 0x1abe11ed, DPAS_SORTED
|DPAS_INSERTBEFORE
);
311 ok(i
== 2, "i=%d\n", i
);
312 /* without DPAS_INSERTBEFORE/AFTER */
313 i
= pDPA_Search(dpa
, (PVOID
)3, 0,
314 CB_CmpLT
, 0x1abe11ed, DPAS_SORTED
);
315 ok(i
== -1, "i=%d\n", i
);
317 /* Re-insert the item */
318 ret
= pDPA_InsertPtr(dpa
, 2, (PVOID
)3);
319 ok(ret
== 2, "ret=%d i=%d\n", ret
, 2);
320 rc
=CheckDPA(dpa
, 0x123456, &dw
);
321 ok(rc
, "dw=0x%x\n", dw
);
323 /* When doing a binary search while claiming reverse order all indexes
325 for(i
= 0; i
< 6; i
++)
327 INT j
= pDPA_Search(dpa
, (PVOID
)(INT_PTR
)i
, 0, CB_CmpGT
, 0x1abe11ed,
328 DPAS_SORTED
|DPAS_INSERTBEFORE
);
329 ok(j
!= i
, "i=%d\n", i
);
332 /* Setting item with huge index should work */
333 ok(pDPA_SetPtr(dpa2
, 0x12345, (PVOID
)0xdeadbeef), "\n");
334 ret
= pDPA_GetPtrIndex(dpa2
, (PVOID
)0xdeadbeef);
335 ok(ret
== 0x12345, "ret=%d\n", ret
);
337 pDPA_DeleteAllPtrs(dpa2
);
338 rc
=CheckDPA(dpa2
, 0, &dw2
);
339 ok(rc
, "dw2=0x%x\n", dw2
);
346 static void test_DPA_Merge(void)
348 HDPA dpa
, dpa2
, dpa3
;
355 win_skip("DPA_Merge() not available\n");
359 dpa
= pDPA_Create(0);
360 dpa2
= pDPA_Create(0);
361 dpa3
= pDPA_Create(0);
363 ret
= pDPA_InsertPtr(dpa
, 0, (PVOID
)1);
364 ok(ret
== 0, "ret=%d\n", ret
);
365 ret
= pDPA_InsertPtr(dpa
, 1, (PVOID
)3);
366 ok(ret
== 1, "ret=%d\n", ret
);
367 ret
= pDPA_InsertPtr(dpa
, 2, (PVOID
)5);
368 ok(ret
== 2, "ret=%d\n", ret
);
370 rc
= CheckDPA(dpa
, 0x135, &dw
);
371 ok(rc
, "dw=0x%x\n", dw
);
373 for (i
= 0; i
< 6; i
++)
375 ret
= pDPA_InsertPtr(dpa2
, i
, (PVOID
)(INT_PTR
)(6-i
));
376 ok(ret
== i
, "ret=%d\n", ret
);
377 ret
= pDPA_InsertPtr(dpa3
, i
, (PVOID
)(INT_PTR
)(i
+1));
378 ok(ret
== i
, "ret=%d\n", ret
);
381 rc
= CheckDPA(dpa2
, 0x654321, &dw
);
382 ok(rc
, "dw=0x%x\n", dw
);
383 rc
= CheckDPA(dpa3
, 0x123456, &dw
);
384 ok(rc
, "dw=0x%x\n", dw
);
386 /* Delete all odd entries from dpa2 */
387 memset(nMessages
, 0, sizeof(nMessages
));
388 pDPA_Merge(dpa2
, dpa
, DPAM_INTERSECT
,
389 CB_CmpLT
, CB_MergeDeleteOddSrc
, 0x1abe11ed);
390 rc
= CheckDPA(dpa2
, 0x246, &dw
);
391 ok(rc
, "dw=0x%x\n", dw
);
393 expect(3, nMessages
[DPAMM_MERGE
]);
394 expect(3, nMessages
[DPAMM_DELETE
]);
395 expect(0, nMessages
[DPAMM_INSERT
]);
397 for (i
= 0; i
< 6; i
++)
399 ret
= pDPA_InsertPtr(dpa2
, i
, (PVOID
)(INT_PTR
)(6-i
));
400 ok(ret
== i
, "ret=%d\n", ret
);
403 /* DPAM_INTERSECT - returning source while merging */
404 memset(nMessages
, 0, sizeof(nMessages
));
405 pDPA_Merge(dpa2
, dpa
, DPAM_INTERSECT
,
406 CB_CmpLT
, CB_MergeInsertSrc
, 0x1abe11ed);
407 rc
= CheckDPA(dpa2
, 0x135, &dw
);
408 ok(rc
, "dw=0x%x\n", dw
);
410 expect(3, nMessages
[DPAMM_MERGE
]);
411 expect(6, nMessages
[DPAMM_DELETE
]);
412 expect(0, nMessages
[DPAMM_INSERT
]);
415 pDPA_DeleteAllPtrs(dpa
);
416 pDPA_InsertPtr(dpa
, 0, (PVOID
)1);
417 pDPA_InsertPtr(dpa
, 1, (PVOID
)3);
418 pDPA_InsertPtr(dpa
, 2, (PVOID
)5);
419 pDPA_DeleteAllPtrs(dpa2
);
420 pDPA_InsertPtr(dpa2
, 0, (PVOID
)2);
421 pDPA_InsertPtr(dpa2
, 1, (PVOID
)4);
422 pDPA_InsertPtr(dpa2
, 2, (PVOID
)6);
424 memset(nMessages
, 0, sizeof(nMessages
));
425 pDPA_Merge(dpa2
, dpa
, DPAM_UNION
,
426 CB_CmpLT
, CB_MergeInsertSrc
, 0x1abe11ed);
427 rc
= CheckDPA(dpa2
, 0x123456, &dw
);
429 broken(!rc
&& dw
== 0x23456), /* 4.7x */
432 expect(0, nMessages
[DPAMM_MERGE
]);
433 expect(0, nMessages
[DPAMM_DELETE
]);
434 ok(nMessages
[DPAMM_INSERT
] == 3 ||
435 broken(nMessages
[DPAMM_INSERT
] == 2), /* 4.7x */
436 "Expected 3, got %d\n", nMessages
[DPAMM_INSERT
]);
438 /* Merge dpa3 into dpa2 and dpa */
439 memset(nMessages
, 0, sizeof(nMessages
));
440 pDPA_Merge(dpa
, dpa3
, DPAM_UNION
|DPAM_SORTED
,
441 CB_CmpLT
, CB_MergeInsertSrc
, 0x1abe11ed);
442 expect(3, nMessages
[DPAMM_MERGE
]);
443 expect(0, nMessages
[DPAMM_DELETE
]);
444 expect(3, nMessages
[DPAMM_INSERT
]);
447 pDPA_DeleteAllPtrs(dpa2
);
448 pDPA_InsertPtr(dpa2
, 0, (PVOID
)2);
449 pDPA_InsertPtr(dpa2
, 1, (PVOID
)4);
450 pDPA_InsertPtr(dpa2
, 2, (PVOID
)6);
452 memset(nMessages
, 0, sizeof(nMessages
));
453 pDPA_Merge(dpa2
, dpa3
, DPAM_UNION
|DPAM_SORTED
,
454 CB_CmpLT
, CB_MergeInsertSrc
, 0x1abe11ed);
455 expect(3, nMessages
[DPAMM_MERGE
]);
456 expect(0, nMessages
[DPAMM_DELETE
]);
457 ok(nMessages
[DPAMM_INSERT
] == 3 ||
458 broken(nMessages
[DPAMM_INSERT
] == 2), /* 4.7x */
459 "Expected 3, got %d\n", nMessages
[DPAMM_INSERT
]);
461 rc
= CheckDPA(dpa
, 0x123456, &dw
);
462 ok(rc
, "dw=0x%x\n", dw
);
463 rc
= CheckDPA(dpa2
, 0x123456, &dw
);
465 broken(!rc
), /* win98 */
467 rc
= CheckDPA(dpa3
, 0x123456, &dw
);
468 ok(rc
, "dw=0x%x\n", dw
);
475 static void test_DPA_EnumCallback(void)
482 if(!pDPA_EnumCallback
)
484 win_skip("DPA_EnumCallback() not available\n");
488 dpa
= pDPA_Create(0);
490 for (i
= 0; i
< 6; i
++)
492 ret
= pDPA_InsertPtr(dpa
, i
, (PVOID
)(INT_PTR
)(i
+1));
493 ok(ret
== i
, "ret=%d\n", ret
);
496 rc
= CheckDPA(dpa
, 0x123456, &dw
);
497 ok(rc
, "dw=0x%x\n", dw
);
500 /* test callback sets first 3 items to 7 */
501 pDPA_EnumCallback(dpa
, CB_EnumFirstThree
, dpa
);
502 rc
= CheckDPA(dpa
, 0x777456, &dw
);
503 ok(rc
, "dw=0x%x\n", dw
);
504 ok(nEnum
== 3, "nEnum=%d\n", nEnum
);
509 static void test_DPA_DestroyCallback(void)
514 if(!pDPA_DestroyCallback
)
516 win_skip("DPA_DestroyCallback() not available\n");
520 dpa
= pDPA_Create(0);
522 for (i
= 0; i
< 3; i
++)
524 ret
= pDPA_InsertPtr(dpa
, i
, (PVOID
)(INT_PTR
)(i
+1));
525 ok(ret
== i
, "ret=%d\n", ret
);
529 pDPA_DestroyCallback(dpa
, CB_EnumFirstThree
, dpa
);
530 ok(nEnum
== 3, "nEnum=%d\n", nEnum
);
533 static void test_DPA_LoadStream(void)
535 static const WCHAR szStg
[] = { 'S','t','g',0 };
536 IStorage
* pStg
= NULL
;
537 IStream
* pStm
= NULL
;
548 win_skip("DPA_LoadStream() not available. Skipping stream tests.\n");
552 hRes
= CoInitialize(NULL
);
555 ok(0, "hResult: %d\n", hRes
);
559 dwMode
= STGM_DIRECT
|STGM_CREATE
|STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
;
560 hRes
= StgCreateDocfile(NULL
, dwMode
|STGM_DELETEONRELEASE
, 0, &pStg
);
563 hRes
= IStorage_CreateStream(pStg
, szStg
, dwMode
, 0, 0, &pStm
);
566 /* write less than header size */
568 hRes
= IStream_Seek(pStm
, li
, STREAM_SEEK_SET
, NULL
);
571 memset(&header
, 0, sizeof(header
));
573 uli
.QuadPart
= sizeof(header
)-1;
574 hRes
= IStream_SetSize(pStm
, uli
);
576 hRes
= IStream_Write(pStm
, &header
, sizeof(header
)-1, &written
);
578 written
-= sizeof(header
)-1;
582 hRes
= IStream_Seek(pStm
, li
, STREAM_SEEK_SET
, NULL
);
585 hRes
= pDPA_LoadStream(&dpa
, CB_Load
, pStm
, NULL
);
586 expect(E_FAIL
, hRes
);
588 /* check stream position after header read failed */
591 hRes
= IStream_Seek(pStm
, li
, STREAM_SEEK_CUR
, &uli
);
593 ok(uli
.QuadPart
== 0, "Expected to position reset\n");
595 /* write valid header for empty DPA */
596 header
.dwSize
= sizeof(header
);
602 hRes
= IStream_Seek(pStm
, li
, STREAM_SEEK_SET
, NULL
);
605 uli
.QuadPart
= sizeof(header
);
606 hRes
= IStream_SetSize(pStm
, uli
);
609 hRes
= IStream_Write(pStm
, &header
, sizeof(header
), &written
);
611 written
-= sizeof(header
);
615 hRes
= IStream_Seek(pStm
, li
, STREAM_SEEK_SET
, NULL
);
619 hRes
= pDPA_LoadStream(&dpa
, CB_Load
, pStm
, NULL
);
623 /* try with altered dwData2 field */
624 header
.dwSize
= sizeof(header
);
629 hRes
= IStream_Seek(pStm
, li
, STREAM_SEEK_SET
, NULL
);
631 hRes
= IStream_Write(pStm
, &header
, sizeof(header
), &written
);
633 written
-= sizeof(header
);
637 hRes
= IStream_Seek(pStm
, li
, STREAM_SEEK_SET
, NULL
);
640 hRes
= pDPA_LoadStream(&dpa
, CB_Load
, pStm
, (void*)0xdeadbeef);
641 expect(E_FAIL
, hRes
);
643 ret
= IStream_Release(pStm
);
644 ok(!ret
, "ret=%d\n", ret
);
646 ret
= IStorage_Release(pStg
);
647 ok(!ret
, "ret=%d\n", ret
);
652 static void test_DPA_SaveStream(void)
655 static const WCHAR szStg
[] = { 'S','t','g',0 };
656 IStorage
* pStg
= NULL
;
657 IStream
* pStm
= NULL
;
663 LARGE_INTEGER liZero
;
667 win_skip("DPA_SaveStream() not available. Skipping stream tests.\n");
671 hRes
= CoInitialize(NULL
);
674 ok(0, "hResult: %d\n", hRes
);
678 dwMode
= STGM_DIRECT
|STGM_CREATE
|STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
;
679 hRes
= StgCreateDocfile(NULL
, dwMode
|STGM_DELETEONRELEASE
, 0, &pStg
);
682 hRes
= IStorage_CreateStream(pStg
, szStg
, dwMode
, 0, 0, &pStm
);
685 dpa
= pDPA_Create(0);
687 /* simple parameter check */
688 hRes
= pDPA_SaveStream(dpa
, NULL
, pStm
, NULL
);
689 ok(hRes
== E_INVALIDARG
||
690 broken(hRes
== S_OK
) /* XP and below */, "Wrong result, %d\n", hRes
);
693 hRes
= pDPA_SaveStream(NULL
, CB_Save
, pStm
, NULL
);
694 expect(E_INVALIDARG
, hRes
);
696 hRes
= pDPA_SaveStream(dpa
, CB_Save
, NULL
, NULL
);
697 expect(E_INVALIDARG
, hRes
);
701 for (i
= 0; i
< 6; i
++)
703 ret
= pDPA_InsertPtr(dpa
, i
, (PVOID
)(INT_PTR
)(i
+1));
704 ok(ret
== i
, "ret=%d\n", ret
);
708 hRes
= IStream_Seek(pStm
, liZero
, STREAM_SEEK_SET
, NULL
);
711 hRes
= pDPA_SaveStream(dpa
, CB_Save
, pStm
, (void*)0xdeadbeef);
716 hRes
= IStream_Seek(pStm
, liZero
, STREAM_SEEK_SET
, NULL
);
718 hRes
= pDPA_LoadStream(&dpa
, CB_Load
, pStm
, (void*)0xdeadbeef);
720 rc
= CheckDPA(dpa
, 0x123456, &dw
);
721 ok(rc
, "dw=0x%x\n", dw
);
724 ret
= IStream_Release(pStm
);
725 ok(!ret
, "ret=%d\n", ret
);
727 ret
= IStorage_Release(pStg
);
728 ok(!ret
, "ret=%d\n", ret
);
737 hcomctl32
= GetModuleHandleA("comctl32.dll");
739 if(!InitFunctionPtrs(hcomctl32
))
741 win_skip("Needed functions are not available\n");
747 test_DPA_EnumCallback();
748 test_DPA_DestroyCallback();
749 test_DPA_LoadStream();
750 test_DPA_SaveStream();