ReactOS  0.4.13-dev-52-g0efcfec
dpa.c
Go to the documentation of this file.
1 /*
2  * Unit tests for DPA functions
3  *
4  * Copyright 2003 Uwe Bonnes
5  * Copyright 2005 Felix Nawothnig
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 #define COBJMACROS
23 
24 #include <stdarg.h>
25 
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "commctrl.h"
30 #include "objidl.h"
31 
32 #include "wine/test.h"
33 #include "v6util.h"
34 
35 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
36 
37 typedef struct _STREAMDATA
38 {
39  DWORD dwSize;
40  DWORD dwData2;
41  DWORD dwItems;
43 
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 INT (WINAPI *pDPA_GetPtr)(HDPA,INT);
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);
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);
62 
63 static void init_functions(void)
64 {
65  HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
66 
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);
82 
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
90 }
91 
92 /* Callbacks */
93 static INT CALLBACK CB_CmpLT(PVOID p1, PVOID p2, LPARAM lp)
94 {
95  ok(lp == 0x1abe11ed, "lp=%ld\n", lp);
96  return p1 < p2 ? -1 : p1 > p2 ? 1 : 0;
97 }
98 
99 static INT CALLBACK CB_CmpGT(PVOID p1, PVOID p2, LPARAM lp)
100 {
101  ok(lp == 0x1abe11ed, "lp=%ld\n", lp);
102  return p1 > p2 ? -1 : p1 < p2 ? 1 : 0;
103 }
104 
105 /* merge callback messages counter
106  DPAMM_MERGE 1
107  DPAMM_DELETE 2
108  DPAMM_INSERT 3 */
109 static INT nMessages[4];
110 
112 {
113  nMessages[op]++;
114  ok(lp == 0x1abe11ed, "lp=%ld\n", lp);
115  return p1;
116 }
117 
119 {
120  nMessages[op]++;
121  ok(lp == 0x1abe11ed, "lp=%ld\n", lp);
122  return ((PCHAR)p2)+1;
123 }
124 
125 static INT nEnum;
126 
128 {
129  INT i;
130 
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;
136 }
137 
139 {
140  HRESULT hRes;
141 
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;
148 }
149 
151 {
152  HRESULT hRes;
153  INT iOldPos;
154 
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;
163 }
164 
166 {
167  DWORD dwOut = 0;
168  INT i;
169 
170  for(i = 0; i < 8;)
171  {
172  ULONG_PTR ulItem = (ULONG_PTR)pDPA_GetPtr(dpa, i++);
173  if(!ulItem) break;
174  dwOut = dwOut << 4 | (ulItem & 0xf);
175  }
176 
177  *pdwOut = dwOut;
178 
179  if(dwOut != dwIn)
180  {
181  pDPA_DeleteAllPtrs(dpa);
182 
183  do
184  {
185  pDPA_InsertPtr(dpa, 0, (PVOID)(ULONG_PTR)(dwIn & 0xf));
186  dwIn >>= 4;
187  }
188  while(dwIn);
189 
190  return FALSE;
191  }
192 
193  return TRUE;
194 }
195 
196 static void test_dpa(void)
197 {
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;
205 
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);
213  "ret=%d error=%d\n", ret, GetLastError());
214 
215  dpa = pDPA_Create(0);
216  ok(dpa != NULL, "\n");
217 
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);
224 
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);
237 
238  rc=CheckDPA(dpa, 0x516324, &dw);
239  ok(rc, "dw=0x%x\n", dw);
240 
241  for(i = 1; i <= 6; i++)
242  {
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);
248  }
249 
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);
254 
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");
262 
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);
268 
269  /* Clone into an old DPA */
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);
275 
276  for(i = 1; i <= 6; i++)
277  {
278  INT j;
279 
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);
285 
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);
292  }
293 
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);
297 
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);
303 
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);
309 
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);
322 
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);
328 
329  /* When doing a binary search while claiming reverse order all indexes
330  * should be bogus */
331  for(i = 0; i < 6; i++)
332  {
333  INT j = pDPA_Search(dpa, (PVOID)(INT_PTR)i, 0, CB_CmpGT, 0x1abe11ed,
335  ok(j != i, "i=%d\n", i);
336  }
337 
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);
342 
343  pDPA_DeleteAllPtrs(dpa2);
344  rc=CheckDPA(dpa2, 0, &dw2);
345  ok(rc, "dw2=0x%x\n", dw2);
346 
347  pDPA_Destroy(dpa);
348  pDPA_Destroy(dpa2);
349  pDPA_Destroy(dpa3);
350 }
351 
352 static void test_DPA_Merge(void)
353 {
354  HDPA dpa, dpa2, dpa3;
355  INT ret, i;
356  DWORD dw;
357  BOOL rc;
358 
359  if(!pDPA_Merge)
360  {
361  win_skip("DPA_Merge() not available\n");
362  return;
363  }
364 
365  dpa = pDPA_Create(0);
366  dpa2 = pDPA_Create(0);
367  dpa3 = pDPA_Create(0);
368 
369  ret = pDPA_InsertPtr(dpa, 0, (PVOID)1);
370  ok(ret == 0, "ret=%d\n", ret);
371  ret = pDPA_InsertPtr(dpa, 1, (PVOID)3);
372  ok(ret == 1, "ret=%d\n", ret);
373  ret = pDPA_InsertPtr(dpa, 2, (PVOID)5);
374  ok(ret == 2, "ret=%d\n", ret);
375 
376  rc = CheckDPA(dpa, 0x135, &dw);
377  ok(rc, "dw=0x%x\n", dw);
378 
379  for (i = 0; i < 6; i++)
380  {
381  ret = pDPA_InsertPtr(dpa2, i, (PVOID)(INT_PTR)(6-i));
382  ok(ret == i, "ret=%d\n", ret);
383  ret = pDPA_InsertPtr(dpa3, i, (PVOID)(INT_PTR)(i+1));
384  ok(ret == i, "ret=%d\n", ret);
385  }
386 
387  rc = CheckDPA(dpa2, 0x654321, &dw);
388  ok(rc, "dw=0x%x\n", dw);
389  rc = CheckDPA(dpa3, 0x123456, &dw);
390  ok(rc, "dw=0x%x\n", dw);
391 
392  /* Delete all odd entries from dpa2 */
393  memset(nMessages, 0, sizeof(nMessages));
394  pDPA_Merge(dpa2, dpa, DPAM_INTERSECT,
395  CB_CmpLT, CB_MergeDeleteOddSrc, 0x1abe11ed);
396  rc = CheckDPA(dpa2, 0x246, &dw);
397  ok(rc, "dw=0x%x\n", dw);
398 
402 
403  for (i = 0; i < 6; i++)
404  {
405  ret = pDPA_InsertPtr(dpa2, i, (PVOID)(INT_PTR)(6-i));
406  ok(ret == i, "ret=%d\n", ret);
407  }
408 
409  /* DPAM_INTERSECT - returning source while merging */
410  memset(nMessages, 0, sizeof(nMessages));
411  pDPA_Merge(dpa2, dpa, DPAM_INTERSECT,
412  CB_CmpLT, CB_MergeInsertSrc, 0x1abe11ed);
413  rc = CheckDPA(dpa2, 0x135, &dw);
414  ok(rc, "dw=0x%x\n", dw);
415 
419 
420  /* DPAM_UNION */
421  pDPA_DeleteAllPtrs(dpa);
422  pDPA_InsertPtr(dpa, 0, (PVOID)1);
423  pDPA_InsertPtr(dpa, 1, (PVOID)3);
424  pDPA_InsertPtr(dpa, 2, (PVOID)5);
425  pDPA_DeleteAllPtrs(dpa2);
426  pDPA_InsertPtr(dpa2, 0, (PVOID)2);
427  pDPA_InsertPtr(dpa2, 1, (PVOID)4);
428  pDPA_InsertPtr(dpa2, 2, (PVOID)6);
429 
430  memset(nMessages, 0, sizeof(nMessages));
431  pDPA_Merge(dpa2, dpa, DPAM_UNION,
432  CB_CmpLT, CB_MergeInsertSrc, 0x1abe11ed);
433  rc = CheckDPA(dpa2, 0x123456, &dw);
434  ok(rc ||
435  broken(!rc && dw == 0x23456), /* 4.7x */
436  "dw=0x%x\n", dw);
437 
440  ok(nMessages[DPAMM_INSERT] == 3 ||
441  broken(nMessages[DPAMM_INSERT] == 2), /* 4.7x */
442  "Expected 3, got %d\n", nMessages[DPAMM_INSERT]);
443 
444  /* Merge dpa3 into dpa2 and dpa */
445  memset(nMessages, 0, sizeof(nMessages));
446  pDPA_Merge(dpa, dpa3, DPAM_UNION|DPAM_SORTED,
447  CB_CmpLT, CB_MergeInsertSrc, 0x1abe11ed);
451 
452 
453  pDPA_DeleteAllPtrs(dpa2);
454  pDPA_InsertPtr(dpa2, 0, (PVOID)2);
455  pDPA_InsertPtr(dpa2, 1, (PVOID)4);
456  pDPA_InsertPtr(dpa2, 2, (PVOID)6);
457 
458  memset(nMessages, 0, sizeof(nMessages));
459  pDPA_Merge(dpa2, dpa3, DPAM_UNION|DPAM_SORTED,
460  CB_CmpLT, CB_MergeInsertSrc, 0x1abe11ed);
463  ok(nMessages[DPAMM_INSERT] == 3 ||
464  broken(nMessages[DPAMM_INSERT] == 2), /* 4.7x */
465  "Expected 3, got %d\n", nMessages[DPAMM_INSERT]);
466 
467  rc = CheckDPA(dpa, 0x123456, &dw);
468  ok(rc, "dw=0x%x\n", dw);
469  rc = CheckDPA(dpa2, 0x123456, &dw);
470  ok(rc ||
471  broken(!rc), /* win98 */
472  "dw=0x%x\n", dw);
473  rc = CheckDPA(dpa3, 0x123456, &dw);
474  ok(rc, "dw=0x%x\n", dw);
475 
476  pDPA_Destroy(dpa);
477  pDPA_Destroy(dpa2);
478  pDPA_Destroy(dpa3);
479 }
480 
481 static void test_DPA_EnumCallback(void)
482 {
483  HDPA dpa;
484  BOOL rc;
485  DWORD dw;
486  INT i, ret;
487 
488  if(!pDPA_EnumCallback)
489  {
490  win_skip("DPA_EnumCallback() not available\n");
491  return;
492  }
493 
494  dpa = pDPA_Create(0);
495 
496  for (i = 0; i < 6; i++)
497  {
498  ret = pDPA_InsertPtr(dpa, i, (PVOID)(INT_PTR)(i+1));
499  ok(ret == i, "ret=%d\n", ret);
500  }
501 
502  rc = CheckDPA(dpa, 0x123456, &dw);
503  ok(rc, "dw=0x%x\n", dw);
504 
505  nEnum = 0;
506  /* test callback sets first 3 items to 7 */
507  pDPA_EnumCallback(dpa, CB_EnumFirstThree, dpa);
508  rc = CheckDPA(dpa, 0x777456, &dw);
509  ok(rc, "dw=0x%x\n", dw);
510  ok(nEnum == 3, "nEnum=%d\n", nEnum);
511 
512  pDPA_Destroy(dpa);
513 }
514 
515 static void test_DPA_DestroyCallback(void)
516 {
517  HDPA dpa;
518  INT i, ret;
519 
520  if(!pDPA_DestroyCallback)
521  {
522  win_skip("DPA_DestroyCallback() not available\n");
523  return;
524  }
525 
526  dpa = pDPA_Create(0);
527 
528  for (i = 0; i < 3; i++)
529  {
530  ret = pDPA_InsertPtr(dpa, i, (PVOID)(INT_PTR)(i+1));
531  ok(ret == i, "ret=%d\n", ret);
532  }
533 
534  nEnum = 0;
535  pDPA_DestroyCallback(dpa, CB_EnumFirstThree, dpa);
536  ok(nEnum == 3, "nEnum=%d\n", nEnum);
537 }
538 
539 static void test_DPA_LoadStream(void)
540 {
541  static const WCHAR szStg[] = { 'S','t','g',0 };
542  IStorage* pStg = NULL;
543  IStream* pStm = NULL;
544  LARGE_INTEGER li;
545  ULARGE_INTEGER uli;
546  DWORD dwMode;
547  HRESULT hRes;
549  ULONG written, ret;
550  HDPA dpa;
551 
552  if(!pDPA_LoadStream)
553  {
554  win_skip("DPA_LoadStream() not available. Skipping stream tests.\n");
555  return;
556  }
557 
558  hRes = CoInitialize(NULL);
559  if (hRes != S_OK)
560  {
561  ok(0, "hResult: %d\n", hRes);
562  return;
563  }
564 
566  hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
567  expect(S_OK, hRes);
568 
569  hRes = IStorage_CreateStream(pStg, szStg, dwMode, 0, 0, &pStm);
570  expect(S_OK, hRes);
571 
572  /* write less than header size */
573  li.QuadPart = 0;
574  hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
575  expect(S_OK, hRes);
576 
577  memset(&header, 0, sizeof(header));
578  written = 0;
579  uli.QuadPart = sizeof(header)-1;
580  hRes = IStream_SetSize(pStm, uli);
581  expect(S_OK, hRes);
582  hRes = IStream_Write(pStm, &header, sizeof(header)-1, &written);
583  expect(S_OK, hRes);
584  written -= sizeof(header)-1;
585  expect(0, written);
586 
587  li.QuadPart = 0;
588  hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
589  expect(S_OK, hRes);
590 
591  hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, NULL);
592  expect(E_FAIL, hRes);
593 
594  /* check stream position after header read failed */
595  li.QuadPart = 0;
596  uli.QuadPart = 1;
597  hRes = IStream_Seek(pStm, li, STREAM_SEEK_CUR, &uli);
598  expect(S_OK, hRes);
599  ok(uli.QuadPart == 0, "Expected to position reset\n");
600 
601  /* write valid header for empty DPA */
602  header.dwSize = sizeof(header);
603  header.dwData2 = 1;
604  header.dwItems = 0;
605  written = 0;
606 
607  li.QuadPart = 0;
608  hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
609  expect(S_OK, hRes);
610 
611  uli.QuadPart = sizeof(header);
612  hRes = IStream_SetSize(pStm, uli);
613  expect(S_OK, hRes);
614 
615  hRes = IStream_Write(pStm, &header, sizeof(header), &written);
616  expect(S_OK, hRes);
617  written -= sizeof(header);
618  expect(0, written);
619 
620  li.QuadPart = 0;
621  hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
622  expect(S_OK, hRes);
623 
624  dpa = NULL;
625  hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, NULL);
626  expect(S_OK, hRes);
627  pDPA_Destroy(dpa);
628 
629  /* try with altered dwData2 field */
630  header.dwSize = sizeof(header);
631  header.dwData2 = 2;
632  header.dwItems = 0;
633 
634  li.QuadPart = 0;
635  hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
636  expect(S_OK, hRes);
637  hRes = IStream_Write(pStm, &header, sizeof(header), &written);
638  expect(S_OK, hRes);
639  written -= sizeof(header);
640  expect(0, written);
641 
642  li.QuadPart = 0;
643  hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
644  expect(S_OK, hRes);
645 
646  hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, (void*)0xdeadbeef);
647  expect(E_FAIL, hRes);
648 
649  ret = IStream_Release(pStm);
650  ok(!ret, "ret=%d\n", ret);
651 
652  ret = IStorage_Release(pStg);
653  ok(!ret, "ret=%d\n", ret);
654 
655  CoUninitialize();
656 }
657 
658 static void test_DPA_SaveStream(void)
659 {
660  HDPA dpa;
661  static const WCHAR szStg[] = { 'S','t','g',0 };
662  IStorage* pStg = NULL;
663  IStream* pStm = NULL;
664  DWORD dwMode, dw;
665  HRESULT hRes;
666  INT ret;
667  INT i;
668  BOOL rc;
669  LARGE_INTEGER liZero;
670 
671  if(!pDPA_SaveStream)
672  {
673  win_skip("DPA_SaveStream() not available. Skipping stream tests.\n");
674  return;
675  }
676 
677  hRes = CoInitialize(NULL);
678  if (hRes != S_OK)
679  {
680  ok(0, "hResult: %d\n", hRes);
681  return;
682  }
683 
685  hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
686  expect(S_OK, hRes);
687 
688  hRes = IStorage_CreateStream(pStg, szStg, dwMode, 0, 0, &pStm);
689  expect(S_OK, hRes);
690 
691  dpa = pDPA_Create(0);
692 
693  /* simple parameter check */
694  hRes = pDPA_SaveStream(dpa, NULL, pStm, NULL);
695  ok(hRes == E_INVALIDARG ||
696  broken(hRes == S_OK) /* XP and below */, "Wrong result, %d\n", hRes);
697 if (0) {
698  /* crashes on XP */
699  hRes = pDPA_SaveStream(NULL, CB_Save, pStm, NULL);
700  expect(E_INVALIDARG, hRes);
701 
702  hRes = pDPA_SaveStream(dpa, CB_Save, NULL, NULL);
703  expect(E_INVALIDARG, hRes);
704 }
705 
706  /* saving/loading */
707  for (i = 0; i < 6; i++)
708  {
709  ret = pDPA_InsertPtr(dpa, i, (PVOID)(INT_PTR)(i+1));
710  ok(ret == i, "ret=%d\n", ret);
711  }
712 
713  liZero.QuadPart = 0;
714  hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
715  expect(S_OK, hRes);
716 
717  hRes = pDPA_SaveStream(dpa, CB_Save, pStm, (void*)0xdeadbeef);
718  expect(S_OK, hRes);
719  pDPA_Destroy(dpa);
720 
721  liZero.QuadPart = 0;
722  hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
723  expect(S_OK, hRes);
724  hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, (void*)0xdeadbeef);
725  expect(S_OK, hRes);
726  rc = CheckDPA(dpa, 0x123456, &dw);
727  ok(rc, "dw=0x%x\n", dw);
728  pDPA_Destroy(dpa);
729 
730  ret = IStream_Release(pStm);
731  ok(!ret, "ret=%d\n", ret);
732 
733  ret = IStorage_Release(pStg);
734  ok(!ret, "ret=%d\n", ret);
735 
736  CoUninitialize();
737 }
738 
740 {
741  ULONG_PTR cookie;
742  HANDLE ctxt;
743 
744  init_functions();
745 
746  test_dpa();
747  test_DPA_Merge();
752 
753  if (!load_v6_module(&cookie, &ctxt))
754  return;
755 
756  init_functions();
757 
758  test_dpa();
759  test_DPA_Merge();
764 
765  unload_v6_module(cookie, ctxt);
766 }
#define expect(expected, got)
Definition: dpa.c:35
static HANDLE
Definition: dpa.c:46
signed char * PCHAR
Definition: retypes.h:7
void WINAPI DPA_DestroyCallback(HDPA hdpa, PFNDPAENUMCALLBACK enumProc, LPVOID lParam)
Definition: dpa.c:1003
#define TRUE
Definition: types.h:120
static PFNDPASTREAM
Definition: dpa.c:56
HDPA WINAPI DPA_Create(INT nGrow)
Definition: dpa.c:950
static HRESULT(WINAPI *pDPA_LoadStream)(HDPA *
static INT nEnum
Definition: dpa.c:125
#define ERROR_SUCCESS
Definition: deptool.c:10
static BOOL CheckDPA(HDPA dpa, DWORD dwIn, PDWORD pdwOut)
Definition: dpa.c:165
#define DPAS_SORTED
Definition: commctrl.h:4833
static PFNDPAENUMCALLBACK
Definition: dpa.c:50
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:922
BOOL WINAPI DPA_Destroy(HDPA hdpa)
Definition: dpa.c:396
LPVOID WINAPI DPA_GetPtr(HDPA hdpa, INT nIndex)
Definition: dpa.c:527
HANDLE WINAPI HeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize)
Definition: heapmem.c:45
#define DPAS_INSERTAFTER
Definition: commctrl.h:4835
static INT
Definition: dpa.c:48
#define STGM_CREATE
Definition: objbase.h:925
DWORD dwData2
Definition: dpa.c:60
#define CALLBACK
Definition: compat.h:27
BOOL WINAPI DPA_Merge(HDPA hdpa1, HDPA hdpa2, DWORD dwFlags, PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
Definition: dpa.c:265
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static void unload_v6_module(ULONG_PTR cookie, HANDLE hCtx)
Definition: v6util.h:63
struct _STREAMDATA * PSTREAMDATA
int32_t INT_PTR
Definition: typedefs.h:62
DWORD dwItems
Definition: dpa.c:61
#define E_FAIL
Definition: ddrawi.h:102
#define DPAMM_INSERT
Definition: commctrl.h:4940
int32_t INT
Definition: typedefs.h:56
HDPA WINAPI DPA_CreateEx(INT nGrow, HANDLE hHeap)
Definition: dpa.c:909
uint32_t ULONG_PTR
Definition: typedefs.h:63
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HRESULT WINAPI DPA_SaveStream(HDPA hDpa, PFNDPASTREAM saveProc, IStream *pStream, LPVOID pData)
Definition: dpa.c:179
struct _STREAMDATA STREAMDATA
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
static BOOL load_v6_module(ULONG_PTR *pcookie, HANDLE *hCtx)
Definition: v6util.h:71
unsigned int BOOL
Definition: ntddk_ex.h:94
static HRESULT CALLBACK CB_Load(DPASTREAMINFO *pInfo, IStream *pStm, LPVOID lp)
Definition: dpa.c:150
#define DPAM_SORTED
Definition: commctrl.h:4933
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
#define ok(value,...)
static PVOID CALLBACK CB_MergeInsertSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
Definition: dpa.c:111
#define E_INVALIDARG
Definition: ddrawi.h:101
static void test_DPA_SaveStream(void)
Definition: dpa.c:658
HDPA WINAPI DPA_Clone(const HDPA hdpa, HDPA hdpaNew)
Definition: dpa.c:470
smooth NULL
Definition: ftsmooth.c:416
#define STGM_DELETEONRELEASE
Definition: objbase.h:924
LONG_PTR LPARAM
Definition: windef.h:208
static INT nMessages[4]
Definition: dpa.c:109
static DWORD
Definition: dpa.c:57
static void init_functions(void)
Definition: dpa.c:63
#define DPAM_INTERSECT
Definition: commctrl.h:4936
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
HRESULT WINAPI DPA_LoadStream(HDPA *phDpa, PFNDPASTREAM loadProc, IStream *pStream, LPVOID pData)
Definition: dpa.c:82
static HRESULT CALLBACK CB_Save(DPASTREAMINFO *pInfo, IStream *pStm, LPVOID lp)
Definition: dpa.c:138
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
#define STGM_DIRECT
Definition: objbase.h:913
static PVOID
Definition: dpa.c:50
#define WINAPI
Definition: msvc.h:8
BOOL WINAPI DPA_DeleteAllPtrs(HDPA hdpa)
Definition: dpa.c:730
static LPARAM
Definition: dpa.c:57
static PFNDPAMERGE
Definition: dpa.c:57
unsigned long DWORD
Definition: ntddk_ex.h:95
INT WINAPI DPA_GetPtrIndex(HDPA hdpa, LPCVOID p)
Definition: dpa.c:561
#define SetLastError(x)
Definition: compat.h:409
REFIID LPVOID DWORD dw
Definition: atlbase.h:40
static void test_DPA_DestroyCallback(void)
Definition: dpa.c:515
int ret
static IStream LPVOID
Definition: dpa.c:56
INT WINAPI DPA_InsertPtr(HDPA hdpa, INT i, LPVOID p)
Definition: dpa.c:591
static void test_DPA_EnumCallback(void)
Definition: dpa.c:481
BOOL WINAPI DPA_Sort(HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
Definition: dpa.c:813
HRESULT WINAPI StgCreateDocfile(LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8637
VOID WINAPI DPA_EnumCallback(HDPA hdpa, PFNDPAENUMCALLBACK enumProc, LPVOID lParam)
Definition: dpa.c:969
static void test_DPA_LoadStream(void)
Definition: dpa.c:539
#define STGM_READWRITE
Definition: objbase.h:918
static BOOL(WINAPI *pDPA_Destroy)(HDPA)
static HDPA
Definition: dpa.c:44
#define DPAMM_MERGE
Definition: commctrl.h:4938
#define broken(x)
Definition: _sntprintf.h:21
DWORD dwSize
Definition: dpa.c:59
#define DPAM_UNION
Definition: commctrl.h:4935
static INT CALLBACK CB_CmpGT(PVOID p1, PVOID p2, LPARAM lp)
Definition: dpa.c:99
BOOL WINAPI DPA_Grow(HDPA hdpa, INT nGrow)
Definition: dpa.c:423
#define S_OK
Definition: intsafe.h:59
DWORD dwPageSize
Definition: winbase.h:1126
static INT CALLBACK CB_EnumFirstThree(PVOID pItem, PVOID lp)
Definition: dpa.c:127
#define DPA_APPEND
Definition: commctrl.h:4755
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:1991
#define X2(f, ord)
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:142
#define DPAMM_DELETE
Definition: commctrl.h:4939
unsigned int UINT
Definition: ndis.h:50
#define DPA_ERR
Definition: commctrl.h:4756
DWORD * PDWORD
Definition: pedump.c:68
_In_ UINT _In_ DWORD dwIn
Definition: ntgdi.h:248
static void test_DPA_Merge(void)
Definition: dpa.c:352
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1897
static UINT
Definition: dpa.c:59
LPVOID WINAPI DPA_DeletePtr(HDPA hdpa, INT i)
Definition: dpa.c:677
unsigned int ULONG
Definition: retypes.h:1
static VOID(WINAPI *pDPA_DestroyCallback)(HDPA
#define ULONG_PTR
Definition: config.h:101
UINT op
Definition: effect.c:223
_Out_ PDWORD pdwOut
Definition: ntgdi.h:1813
static INT CALLBACK CB_CmpLT(PVOID p1, PVOID p2, LPARAM lp)
Definition: dpa.c:93
GLfloat GLfloat p
Definition: glext.h:8902
void * pvItem
Definition: commctrl.h:4856
static PVOID CALLBACK CB_MergeDeleteOddSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
Definition: dpa.c:118
static PFNDPACOMPARE
Definition: dpa.c:57
#define memset(x, y, z)
Definition: compat.h:39
#define win_skip
Definition: test.h:141
int k
Definition: mpi.c:3369
#define DPAS_INSERTBEFORE
Definition: commctrl.h:4834
INT WINAPI DPA_Search(HDPA hdpa, LPVOID pFind, INT nStart, PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
Definition: dpa.c:845
START_TEST(dpa)
Definition: dpa.c:739
struct CFHEADER header
Definition: fdi.c:109
static void test_dpa(void)
Definition: dpa.c:196
LONGLONG QuadPart
Definition: typedefs.h:112
Definition: dpa.c:48
BOOL WINAPI DPA_SetPtr(HDPA hdpa, INT i, LPVOID p)
Definition: dpa.c:626