wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / comctl32 / tests / dpa.c
blob4a446a8e2c5f99068002e4902733f22aa1dc3390
1 /*
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
22 #define COBJMACROS
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "commctrl.h"
30 #include "objidl.h"
32 #include "wine/test.h"
33 #include "v6util.h"
35 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
37 typedef struct _STREAMDATA
39 DWORD dwSize;
40 DWORD dwData2;
41 DWORD dwItems;
42 } STREAMDATA, *PSTREAMDATA;
44 static HDPA (WINAPI *pDPA_Clone)(const HDPA,HDPA);
45 static HDPA (WINAPI *pDPA_Create)(INT);
46 static HDPA (WINAPI *pDPA_CreateEx)(INT,HANDLE);
47 static PVOID (WINAPI *pDPA_DeleteAllPtrs)(HDPA);
48 static PVOID (WINAPI *pDPA_DeletePtr)(HDPA,INT);
49 static BOOL (WINAPI *pDPA_Destroy)(HDPA);
50 static VOID (WINAPI *pDPA_DestroyCallback)(HDPA,PFNDPAENUMCALLBACK,PVOID);
51 static VOID (WINAPI *pDPA_EnumCallback)(HDPA,PFNDPAENUMCALLBACK,PVOID);
52 static PVOID (WINAPI *pDPA_GetPtr)(HDPA,INT_PTR);
53 static INT (WINAPI *pDPA_GetPtrIndex)(HDPA,PVOID);
54 static BOOL (WINAPI *pDPA_Grow)(HDPA,INT);
55 static INT (WINAPI *pDPA_InsertPtr)(HDPA,INT,PVOID);
56 static HRESULT (WINAPI *pDPA_LoadStream)(HDPA*,PFNDPASTREAM,IStream*,LPVOID);
57 static BOOL (WINAPI *pDPA_Merge)(HDPA,HDPA,DWORD,PFNDPACOMPARE,PFNDPAMERGE,LPARAM);
58 static HRESULT (WINAPI *pDPA_SaveStream)(HDPA,PFNDPASTREAM,IStream*,LPVOID);
59 static INT (WINAPI *pDPA_Search)(HDPA,PVOID,INT,PFNDPACOMPARE,LPARAM,UINT);
60 static BOOL (WINAPI *pDPA_SetPtr)(HDPA,INT,PVOID);
61 static BOOL (WINAPI *pDPA_Sort)(HDPA,PFNDPACOMPARE,LPARAM);
63 static void init_functions(void)
65 HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
67 #define X2(f, ord) p##f = (void*)GetProcAddress(hComCtl32, (const char *)ord);
68 /* 4.00+ */
69 X2(DPA_Clone, 331);
70 X2(DPA_Create, 328);
71 X2(DPA_CreateEx, 340);
72 X2(DPA_DeleteAllPtrs, 337);
73 X2(DPA_DeletePtr, 336);
74 X2(DPA_Destroy, 329);
75 X2(DPA_GetPtr, 332);
76 X2(DPA_GetPtrIndex, 333);
77 X2(DPA_Grow, 330);
78 X2(DPA_InsertPtr, 334);
79 X2(DPA_Search, 339);
80 X2(DPA_SetPtr, 335);
81 X2(DPA_Sort, 338);
83 /* 4.71+ */
84 X2(DPA_DestroyCallback, 386);
85 X2(DPA_EnumCallback, 385);
86 X2(DPA_LoadStream, 9);
87 X2(DPA_Merge, 11);
88 X2(DPA_SaveStream, 10);
89 #undef X2
92 /* Callbacks */
93 static INT CALLBACK CB_CmpLT(PVOID p1, PVOID p2, LPARAM lp)
95 ok(lp == 0x1abe11ed, "lp=%ld\n", lp);
96 return p1 < p2 ? -1 : p1 > p2 ? 1 : 0;
99 static INT CALLBACK CB_CmpGT(PVOID p1, PVOID p2, LPARAM lp)
101 ok(lp == 0x1abe11ed, "lp=%ld\n", lp);
102 return p1 > p2 ? -1 : p1 < p2 ? 1 : 0;
105 /* merge callback messages counter
106 DPAMM_MERGE 1
107 DPAMM_DELETE 2
108 DPAMM_INSERT 3 */
109 static INT nMessages[4];
111 static PVOID CALLBACK CB_MergeInsertSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
113 nMessages[op]++;
114 ok(lp == 0x1abe11ed, "lp=%ld\n", lp);
115 return p1;
118 static PVOID CALLBACK CB_MergeDeleteOddSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
120 nMessages[op]++;
121 ok(lp == 0x1abe11ed, "lp=%ld\n", lp);
122 return ((PCHAR)p2)+1;
125 static INT nEnum;
127 static INT CALLBACK CB_EnumFirstThree(PVOID pItem, PVOID lp)
129 INT i;
131 i = pDPA_GetPtrIndex(lp, pItem);
132 ok(i == nEnum, "i=%d nEnum=%d\n", i, nEnum);
133 nEnum++;
134 pDPA_SetPtr(lp, i, (PVOID)7);
135 return pItem != (PVOID)3;
138 static HRESULT CALLBACK CB_Save(DPASTREAMINFO *pInfo, IStream *pStm, LPVOID lp)
140 HRESULT hRes;
142 ok(lp == (LPVOID)0xdeadbeef, "lp=%p\n", lp);
143 hRes = IStream_Write(pStm, &pInfo->iPos, sizeof(INT), NULL);
144 expect(S_OK, hRes);
145 hRes = IStream_Write(pStm, &pInfo->pvItem, sizeof(PVOID), NULL);
146 expect(S_OK, hRes);
147 return S_OK;
150 static HRESULT CALLBACK CB_Load(DPASTREAMINFO *pInfo, IStream *pStm, LPVOID lp)
152 HRESULT hRes;
153 INT iOldPos;
155 iOldPos = pInfo->iPos;
156 ok(lp == (LPVOID)0xdeadbeef, "lp=%p\n", lp);
157 hRes = IStream_Read(pStm, &pInfo->iPos, sizeof(INT), NULL);
158 expect(S_OK, hRes);
159 ok(pInfo->iPos == iOldPos, "iPos=%d iOldPos=%d\n", pInfo->iPos, iOldPos);
160 hRes = IStream_Read(pStm, &pInfo->pvItem, sizeof(PVOID), NULL);
161 expect(S_OK, hRes);
162 return S_OK;
165 static BOOL CheckDPA(HDPA dpa, DWORD dwIn, PDWORD pdwOut)
167 DWORD dwOut = 0;
168 INT i;
170 for(i = 0; i < 8;)
172 ULONG_PTR ulItem = (ULONG_PTR)pDPA_GetPtr(dpa, i++);
173 if(!ulItem) break;
174 dwOut = dwOut << 4 | (ulItem & 0xf);
177 *pdwOut = dwOut;
179 if(dwOut != dwIn)
181 pDPA_DeleteAllPtrs(dpa);
185 pDPA_InsertPtr(dpa, 0, (PVOID)(ULONG_PTR)(dwIn & 0xf));
186 dwIn >>= 4;
188 while(dwIn);
190 return FALSE;
193 return TRUE;
196 static void test_dpa(void)
198 SYSTEM_INFO si;
199 HANDLE hHeap;
200 HDPA dpa, dpa2, dpa3;
201 INT ret, i;
202 PVOID p;
203 DWORD dw, dw2, dw3;
204 BOOL rc;
206 GetSystemInfo(&si);
207 hHeap = HeapCreate(0, 1, 2);
208 ok(hHeap != NULL, "error=%d\n", GetLastError());
209 dpa3 = pDPA_CreateEx(0, hHeap);
210 ok(dpa3 != NULL, "\n");
211 ret = pDPA_Grow(dpa3, si.dwPageSize + 1);
212 ok(!ret && GetLastError() == ERROR_NOT_ENOUGH_MEMORY,
213 "ret=%d error=%d\n", ret, GetLastError());
215 dpa = pDPA_Create(0);
216 ok(dpa != NULL, "\n");
218 /* Set item with out of bound index */
219 ok(pDPA_SetPtr(dpa, 1, (PVOID)6), "\n");
220 /* Fill the created gap */
221 ok(pDPA_SetPtr(dpa, 0, (PVOID)5), "\n");
222 rc=CheckDPA(dpa, 0x56, &dw);
223 ok(rc, "dw=0x%x\n", dw);
225 /* Prepend item */
226 ret = pDPA_InsertPtr(dpa, 1, (PVOID)1);
227 ok(ret == 1, "ret=%d\n", ret);
228 /* Append item using correct index */
229 ret = pDPA_InsertPtr(dpa, 3, (PVOID)3);
230 ok(ret == 3, "ret=%d\n", ret);
231 /* Append item using out of bound index */
232 ret = pDPA_InsertPtr(dpa, 5, (PVOID)2);
233 ok(ret == 4, "ret=%d\n", ret);
234 /* Append item using DPA_APPEND */
235 ret = pDPA_InsertPtr(dpa, DPA_APPEND, (PVOID)4);
236 ok(ret == 5, "ret=%d\n", ret);
238 rc=CheckDPA(dpa, 0x516324, &dw);
239 ok(rc, "dw=0x%x\n", dw);
241 for(i = 1; i <= 6; i++)
243 INT j, k;
244 k = pDPA_GetPtrIndex(dpa, (PVOID)(INT_PTR)i);
245 /* Linear searches should work on unsorted DPAs */
246 j = pDPA_Search(dpa, (PVOID)(INT_PTR)i, 0, CB_CmpLT, 0x1abe11ed, 0);
247 ok(j == k, "j=%d k=%d\n", j, k);
250 /* Sort DPA */
251 ok(pDPA_Sort(dpa, CB_CmpGT, 0x1abe11ed), "\n");
252 rc=CheckDPA(dpa, 0x654321, &dw);
253 ok(rc, "dw=0x%x\n", dw);
255 /* Clone into a new DPA */
256 dpa2 = pDPA_Clone(dpa, NULL);
257 ok(dpa2 != NULL, "\n");
258 /* The old data should have been preserved */
259 rc=CheckDPA(dpa2, 0x654321, &dw2);
260 ok(rc, "dw=0x%x\n", dw2);
261 ok(pDPA_Sort(dpa, CB_CmpLT, 0x1abe11ed), "\n");
263 /* Test if the DPA itself was really copied */
264 rc=CheckDPA(dpa, 0x123456, &dw);
265 ok(rc, "dw=0x%x\n", dw );
266 rc=CheckDPA(dpa2, 0x654321, &dw2);
267 ok(rc, "dw2=0x%x\n", dw2);
269 /* Clone into an old DPA */
270 SetLastError(ERROR_SUCCESS);
271 p = pDPA_Clone(dpa, dpa3);
272 ok(p == dpa3, "p=%p\n", p);
273 rc=CheckDPA(dpa3, 0x123456, &dw3);
274 ok(rc, "dw3=0x%x\n", dw3);
276 for(i = 1; i <= 6; i++)
278 INT j;
280 /* The array is in order so ptr == index+1 */
281 j = pDPA_GetPtrIndex(dpa, (PVOID)(INT_PTR)i);
282 ok(j+1 == i, "j=%d i=%d\n", j, i);
283 j = pDPA_Search(dpa, (PVOID)(INT_PTR)i, 0, CB_CmpLT, 0x1abe11ed, DPAS_SORTED);
284 ok(j+1 == i, "j=%d i=%d\n", j, i);
286 /* Linear searches respect iStart ... */
287 j = pDPA_Search(dpa, (PVOID)(INT_PTR)i, i+1, CB_CmpLT, 0x1abe11ed, 0);
288 ok(j == DPA_ERR, "j=%d\n", j);
289 /* ... but for a binary search it's ignored */
290 j = pDPA_Search(dpa, (PVOID)(INT_PTR)i, i+1, CB_CmpLT, 0x1abe11ed, DPAS_SORTED);
291 ok(j+1 == i, "j=%d i=%d\n", j, i);
294 /* Try to get the index of a nonexistent item */
295 i = pDPA_GetPtrIndex(dpa, (PVOID)7);
296 ok(i == DPA_ERR, "i=%d\n", i);
298 /* Try to delete out of bound indexes */
299 p = pDPA_DeletePtr(dpa, -1);
300 ok(p == NULL, "p=%p\n", p);
301 p = pDPA_DeletePtr(dpa, 6);
302 ok(p == NULL, "p=%p\n", p);
304 /* Delete the third item */
305 p = pDPA_DeletePtr(dpa, 2);
306 ok(p == (PVOID)3, "p=%p\n", p);
307 rc=CheckDPA(dpa, 0x12456, &dw);
308 ok(rc, "dw=0x%x\n", dw);
310 /* Check where to re-insert the deleted item */
311 i = pDPA_Search(dpa, (PVOID)3, 0,
312 CB_CmpLT, 0x1abe11ed, DPAS_SORTED|DPAS_INSERTAFTER);
313 ok(i == 2, "i=%d\n", i);
314 /* DPAS_INSERTBEFORE works just like DPAS_INSERTAFTER */
315 i = pDPA_Search(dpa, (PVOID)3, 0,
316 CB_CmpLT, 0x1abe11ed, DPAS_SORTED|DPAS_INSERTBEFORE);
317 ok(i == 2, "i=%d\n", i);
318 /* without DPAS_INSERTBEFORE/AFTER */
319 i = pDPA_Search(dpa, (PVOID)3, 0,
320 CB_CmpLT, 0x1abe11ed, DPAS_SORTED);
321 ok(i == -1, "i=%d\n", i);
323 /* Re-insert the item */
324 ret = pDPA_InsertPtr(dpa, 2, (PVOID)3);
325 ok(ret == 2, "ret=%d i=%d\n", ret, 2);
326 rc=CheckDPA(dpa, 0x123456, &dw);
327 ok(rc, "dw=0x%x\n", dw);
329 /* When doing a binary search while claiming reverse order all indexes
330 * should be bogus */
331 for(i = 0; i < 6; i++)
333 INT j = pDPA_Search(dpa, (PVOID)(INT_PTR)i, 0, CB_CmpGT, 0x1abe11ed,
334 DPAS_SORTED|DPAS_INSERTBEFORE);
335 ok(j != i, "i=%d\n", i);
338 /* Setting item with huge index should work */
339 ok(pDPA_SetPtr(dpa2, 0x12345, (PVOID)0xdeadbeef), "\n");
340 ret = pDPA_GetPtrIndex(dpa2, (PVOID)0xdeadbeef);
341 ok(ret == 0x12345, "ret=%d\n", ret);
343 pDPA_DeleteAllPtrs(dpa2);
344 rc=CheckDPA(dpa2, 0, &dw2);
345 ok(rc, "dw2=0x%x\n", dw2);
347 pDPA_Destroy(dpa);
348 pDPA_Destroy(dpa2);
349 pDPA_Destroy(dpa3);
352 static void test_DPA_Merge(void)
354 HDPA dpa, dpa2, dpa3;
355 INT ret, i;
356 DWORD dw;
357 BOOL rc;
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]);
414 /* DPAM_UNION */
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);
428 ok(rc ||
429 broken(!rc && dw == 0x23456), /* 4.7x */
430 "dw=0x%x\n", dw);
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);
464 ok(rc ||
465 broken(!rc), /* win98 */
466 "dw=0x%x\n", dw);
467 rc = CheckDPA(dpa3, 0x123456, &dw);
468 ok(rc, "dw=0x%x\n", dw);
470 pDPA_Destroy(dpa);
471 pDPA_Destroy(dpa2);
472 pDPA_Destroy(dpa3);
475 static void test_DPA_EnumCallback(void)
477 HDPA dpa;
478 BOOL rc;
479 DWORD dw;
480 INT i, ret;
482 dpa = pDPA_Create(0);
484 for (i = 0; i < 6; i++)
486 ret = pDPA_InsertPtr(dpa, i, (PVOID)(INT_PTR)(i+1));
487 ok(ret == i, "ret=%d\n", ret);
490 rc = CheckDPA(dpa, 0x123456, &dw);
491 ok(rc, "dw=0x%x\n", dw);
493 nEnum = 0;
494 /* test callback sets first 3 items to 7 */
495 pDPA_EnumCallback(dpa, CB_EnumFirstThree, dpa);
496 rc = CheckDPA(dpa, 0x777456, &dw);
497 ok(rc, "dw=0x%x\n", dw);
498 ok(nEnum == 3, "nEnum=%d\n", nEnum);
500 pDPA_Destroy(dpa);
503 static void test_DPA_DestroyCallback(void)
505 HDPA dpa;
506 INT i, ret;
508 dpa = pDPA_Create(0);
510 for (i = 0; i < 3; i++)
512 ret = pDPA_InsertPtr(dpa, i, (PVOID)(INT_PTR)(i+1));
513 ok(ret == i, "ret=%d\n", ret);
516 nEnum = 0;
517 pDPA_DestroyCallback(dpa, CB_EnumFirstThree, dpa);
518 ok(nEnum == 3, "nEnum=%d\n", nEnum);
521 static void test_DPA_LoadStream(void)
523 IStorage* pStg = NULL;
524 IStream* pStm = NULL;
525 LARGE_INTEGER li;
526 ULARGE_INTEGER uli;
527 DWORD dwMode;
528 HRESULT hRes;
529 STREAMDATA header;
530 ULONG written, ret;
531 HDPA dpa;
533 hRes = CoInitialize(NULL);
534 ok(hRes == S_OK, "Failed to initialize COM, hr %#x.\n", hRes);
536 dwMode = STGM_DIRECT|STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
537 hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
538 expect(S_OK, hRes);
540 hRes = IStorage_CreateStream(pStg, L"Stg", dwMode, 0, 0, &pStm);
541 expect(S_OK, hRes);
543 /* write less than header size */
544 li.QuadPart = 0;
545 hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
546 expect(S_OK, hRes);
548 memset(&header, 0, sizeof(header));
549 written = 0;
550 uli.QuadPart = sizeof(header)-1;
551 hRes = IStream_SetSize(pStm, uli);
552 expect(S_OK, hRes);
553 hRes = IStream_Write(pStm, &header, sizeof(header)-1, &written);
554 expect(S_OK, hRes);
555 written -= sizeof(header)-1;
556 expect(0, written);
558 li.QuadPart = 0;
559 hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
560 expect(S_OK, hRes);
562 hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, NULL);
563 expect(E_FAIL, hRes);
565 /* check stream position after header read failed */
566 li.QuadPart = 0;
567 uli.QuadPart = 1;
568 hRes = IStream_Seek(pStm, li, STREAM_SEEK_CUR, &uli);
569 expect(S_OK, hRes);
570 ok(uli.QuadPart == 0, "Expected to position reset\n");
572 /* write valid header for empty DPA */
573 header.dwSize = sizeof(header);
574 header.dwData2 = 1;
575 header.dwItems = 0;
576 written = 0;
578 li.QuadPart = 0;
579 hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
580 expect(S_OK, hRes);
582 uli.QuadPart = sizeof(header);
583 hRes = IStream_SetSize(pStm, uli);
584 expect(S_OK, hRes);
586 hRes = IStream_Write(pStm, &header, sizeof(header), &written);
587 expect(S_OK, hRes);
588 written -= sizeof(header);
589 expect(0, written);
591 li.QuadPart = 0;
592 hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
593 expect(S_OK, hRes);
595 dpa = NULL;
596 hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, NULL);
597 expect(S_OK, hRes);
598 pDPA_Destroy(dpa);
600 /* try with altered dwData2 field */
601 header.dwSize = sizeof(header);
602 header.dwData2 = 2;
603 header.dwItems = 0;
605 li.QuadPart = 0;
606 hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
607 expect(S_OK, hRes);
608 hRes = IStream_Write(pStm, &header, sizeof(header), &written);
609 expect(S_OK, hRes);
610 written -= sizeof(header);
611 expect(0, written);
613 li.QuadPart = 0;
614 hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
615 expect(S_OK, hRes);
617 hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, (void*)0xdeadbeef);
618 expect(E_FAIL, hRes);
620 ret = IStream_Release(pStm);
621 ok(!ret, "ret=%d\n", ret);
623 ret = IStorage_Release(pStg);
624 ok(!ret, "ret=%d\n", ret);
626 CoUninitialize();
629 static void test_DPA_SaveStream(void)
631 HDPA dpa;
632 IStorage* pStg = NULL;
633 IStream* pStm = NULL;
634 DWORD dwMode, dw;
635 HRESULT hRes;
636 INT ret;
637 INT i;
638 BOOL rc;
639 LARGE_INTEGER liZero;
641 hRes = CoInitialize(NULL);
642 ok(hRes == S_OK, "Failed to initialize COM, hr %#x.\n", hRes);
644 dwMode = STGM_DIRECT|STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
645 hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
646 expect(S_OK, hRes);
648 hRes = IStorage_CreateStream(pStg, L"Stg", dwMode, 0, 0, &pStm);
649 expect(S_OK, hRes);
651 dpa = pDPA_Create(0);
653 /* simple parameter check */
654 hRes = pDPA_SaveStream(dpa, NULL, pStm, NULL);
655 ok(hRes == E_INVALIDARG ||
656 broken(hRes == S_OK) /* XP and below */, "Wrong result, %d\n", hRes);
657 if (0) {
658 /* crashes on XP */
659 hRes = pDPA_SaveStream(NULL, CB_Save, pStm, NULL);
660 expect(E_INVALIDARG, hRes);
662 hRes = pDPA_SaveStream(dpa, CB_Save, NULL, NULL);
663 expect(E_INVALIDARG, hRes);
666 /* saving/loading */
667 for (i = 0; i < 6; i++)
669 ret = pDPA_InsertPtr(dpa, i, (PVOID)(INT_PTR)(i+1));
670 ok(ret == i, "ret=%d\n", ret);
673 liZero.QuadPart = 0;
674 hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
675 expect(S_OK, hRes);
677 hRes = pDPA_SaveStream(dpa, CB_Save, pStm, (void*)0xdeadbeef);
678 expect(S_OK, hRes);
679 pDPA_Destroy(dpa);
681 liZero.QuadPart = 0;
682 hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
683 expect(S_OK, hRes);
684 hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, (void*)0xdeadbeef);
685 expect(S_OK, hRes);
686 rc = CheckDPA(dpa, 0x123456, &dw);
687 ok(rc, "dw=0x%x\n", dw);
688 pDPA_Destroy(dpa);
690 ret = IStream_Release(pStm);
691 ok(!ret, "ret=%d\n", ret);
693 ret = IStorage_Release(pStg);
694 ok(!ret, "ret=%d\n", ret);
696 CoUninitialize();
699 START_TEST(dpa)
701 ULONG_PTR cookie;
702 HANDLE ctxt;
704 init_functions();
706 test_dpa();
707 test_DPA_Merge();
708 test_DPA_EnumCallback();
709 test_DPA_DestroyCallback();
710 test_DPA_LoadStream();
711 test_DPA_SaveStream();
713 if (!load_v6_module(&cookie, &ctxt))
714 return;
716 init_functions();
718 test_dpa();
719 test_DPA_Merge();
720 test_DPA_EnumCallback();
721 test_DPA_DestroyCallback();
722 test_DPA_LoadStream();
723 test_DPA_SaveStream();
725 unload_v6_module(cookie, ctxt);