1 /* Unit test suite for Twain DSM functions
3 * Copyright 2009 Jeremy White, CodeWeavers, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/test.h"
31 static DSMENTRYPROC pDSM_Entry
;
33 static BOOL
dsm_RegisterWindowClasses(void)
38 cls
.lpfnWndProc
= DefWindowProc
;
41 cls
.hInstance
= GetModuleHandleA(0);
43 cls
.hCursor
= LoadCursorA(0, IDC_ARROW
);
44 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
45 cls
.lpszMenuName
= NULL
;
46 cls
.lpszClassName
= "TWAIN_dsm_class";
47 if (!RegisterClassA(&cls
)) return FALSE
;
53 static void get_condition_code(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_STATUS
*status
)
56 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_STATUS
, MSG_GET
, status
);
57 ok(rc
== TWRC_SUCCESS
, "Condition code not available, rc %d\n", rc
);
60 static BOOL
get_onevalue(TW_HANDLE hcontainer
, TW_UINT32
*ret
, TW_UINT16
*type
)
63 onev
= GlobalLock(hcontainer
);
68 *type
= onev
->ItemType
;
69 GlobalUnlock(hcontainer
);
75 static TW_HANDLE
alloc_and_set_onevalue(TW_UINT32 val
, TW_UINT16 type
)
79 hcontainer
= GlobalAlloc(0, sizeof(*onev
));
82 onev
= GlobalLock(hcontainer
);
85 onev
->ItemType
= type
;
87 GlobalUnlock(hcontainer
);
91 GlobalFree(hcontainer
);
98 static void check_get(TW_CAPABILITY
*pCapability
, TW_INT32 actual_support
,
99 TW_UINT32 orig_value
, TW_UINT32 default_value
, TW_UINT32
*suggested_set_value
)
102 if (suggested_set_value
)
103 *suggested_set_value
= orig_value
+ 1;
104 p
= GlobalLock(pCapability
->hContainer
);
107 if (pCapability
->ConType
== TWON_ONEVALUE
)
109 TW_ONEVALUE
*onev
= p
;
110 ok(onev
->Item
== orig_value
|| !(actual_support
& TWQC_GETCURRENT
), "MSG_GET of 0x%x returned 0x%x, expecting 0x%x\n",
111 pCapability
->Cap
, onev
->Item
, orig_value
);
112 trace("MSG_GET of 0x%x returned val 0x%x, type %d\n", pCapability
->Cap
, onev
->Item
, onev
->ItemType
);
113 if (suggested_set_value
)
114 *suggested_set_value
= onev
->Item
;
116 else if (pCapability
->ConType
== TWON_ENUMERATION
)
122 TW_ENUMERATION
*enumv
= p
;
123 p8
= enumv
->ItemList
;
124 p16
= (TW_UINT16
*) p8
;
125 p32
= (TW_UINT32
*) p8
;
126 trace("MSG_GET of 0x%x returned %d items:\n", pCapability
->Cap
, enumv
->NumItems
);
127 for (i
= 0; i
< enumv
->NumItems
; i
++)
129 if (enumv
->ItemType
== TWTY_UINT8
|| enumv
->ItemType
== TWTY_INT8
)
130 trace(" %d: 0x%x\n", i
, p8
[i
]);
131 if (enumv
->ItemType
== TWTY_UINT16
|| enumv
->ItemType
== TWTY_INT16
)
132 trace(" %d: 0x%x\n", i
, p16
[i
]);
133 if (enumv
->ItemType
== TWTY_UINT32
|| enumv
->ItemType
== TWTY_INT32
)
134 trace(" %d: 0x%x\n", i
, p32
[i
]);
136 if (enumv
->ItemType
== TWTY_UINT16
|| enumv
->ItemType
== TWTY_INT16
)
138 ok(p16
[enumv
->CurrentIndex
] == orig_value
,
139 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETCURRENT (0x%x) do not match.\n",
140 pCapability
->Cap
, p16
[enumv
->CurrentIndex
], orig_value
);
141 ok(p16
[enumv
->DefaultIndex
] == default_value
,
142 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETDEFAULT (0x%x) do not match.\n",
143 pCapability
->Cap
, p16
[enumv
->DefaultIndex
], default_value
);
144 if (suggested_set_value
)
145 *suggested_set_value
= p16
[(enumv
->CurrentIndex
+ 1) % enumv
->NumItems
];
147 if (enumv
->ItemType
== TWTY_UINT32
|| enumv
->ItemType
== TWTY_INT32
)
149 ok(p32
[enumv
->CurrentIndex
] == orig_value
,
150 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETCURRENT (0x%x) do not match.\n",
151 pCapability
->Cap
, p32
[enumv
->CurrentIndex
], orig_value
);
152 ok(p32
[enumv
->DefaultIndex
] == default_value
,
153 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETDEFAULT (0x%x) do not match.\n",
154 pCapability
->Cap
, p32
[enumv
->DefaultIndex
], default_value
);
155 if (suggested_set_value
)
156 *suggested_set_value
= p32
[(enumv
->CurrentIndex
+ 1) % enumv
->NumItems
];
160 trace("MSG_GET on type 0x%x returned type 0x%x, which we didn't check.\n", pCapability
->Cap
, pCapability
->ConType
);
161 GlobalUnlock(pCapability
->hContainer
);
165 static void test_onevalue_cap(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_UINT16 type
, TW_INT32 minimum_support
)
171 TW_UINT32 orig_value
= 0;
173 TW_UINT32 default_value
= 0;
174 TW_INT32 actual_support
;
176 memset(&cap
, 0, sizeof(cap
));
178 cap
.ConType
= TWON_DONTCARE16
;
180 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
181 get_condition_code(appid
, source
, &status
);
182 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
183 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
184 if (rc
!= TWRC_SUCCESS
)
186 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
187 ok((actual_support
& minimum_support
) == minimum_support
,
188 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
189 captype
, actual_support
);
192 if (actual_support
& TWQC_GETCURRENT
)
194 memset(&cap
, 0, sizeof(cap
));
196 cap
.ConType
= TWON_DONTCARE16
;
198 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
199 get_condition_code(appid
, source
, &status
);
200 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
201 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
202 if (rc
== TWRC_SUCCESS
)
204 ok(get_onevalue(cap
.hContainer
, &orig_value
, &rtype
), "Returned cap.hContainer invalid for GETCURRENT on type 0x%x\n", captype
);
205 ok(rtype
== type
, "Returned GETCURRENT type 0x%x for cap 0x%x is not expected 0x%x\n", rtype
, captype
, type
);
206 GlobalFree(cap
.hContainer
);
210 if (actual_support
& TWQC_GETDEFAULT
)
212 memset(&cap
, 0, sizeof(cap
));
214 cap
.ConType
= TWON_DONTCARE16
;
216 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
217 get_condition_code(appid
, source
, &status
);
218 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
219 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
220 if (rc
== TWRC_SUCCESS
)
222 ok(get_onevalue(cap
.hContainer
, &default_value
, &rtype
), "Returned cap.hContainer invalid for GETDEFAULT on type 0x%x\n", captype
);
223 ok(rtype
== type
, "Returned GETDEFAULT type 0x%x for cap 0x%x is not expected 0x%x\n", rtype
, captype
, type
);
224 GlobalFree(cap
.hContainer
);
228 new_value
= orig_value
;
229 if (actual_support
& TWQC_GET
)
231 memset(&cap
, 0, sizeof(cap
));
233 cap
.ConType
= TWON_DONTCARE16
;
235 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
236 get_condition_code(appid
, source
, &status
);
237 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
238 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
239 check_get(&cap
, actual_support
, orig_value
, default_value
, &new_value
);
240 if (rc
== TWRC_SUCCESS
)
241 GlobalFree(cap
.hContainer
);
244 if (actual_support
& TWQC_SET
)
246 memset(&cap
, 0, sizeof(cap
));
248 cap
.ConType
= TWON_ONEVALUE
;
249 cap
.hContainer
= alloc_and_set_onevalue(new_value
, type
);
251 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
252 get_condition_code(appid
, source
, &status
);
253 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
254 "Error [rc %d|cc %d] doing MSG_SET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
255 GlobalFree(cap
.hContainer
);
258 if (actual_support
& TWQC_RESET
)
260 memset(&cap
, 0, sizeof(cap
));
262 cap
.ConType
= TWON_DONTCARE16
;
264 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
265 get_condition_code(appid
, source
, &status
);
266 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
267 "Error [rc %d|cc %d] doing MSG_RESET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
268 if (rc
== TWRC_SUCCESS
)
269 GlobalFree(cap
.hContainer
);
273 static void test_resolution(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_INT32 minimum_support
)
280 TW_INT32 actual_support
;
281 TW_FIX32 orig_value
= { 0, 0 };
282 TW_UINT32 new_value
= 0;
283 TW_FIX32 default_value
= { 0, 0 };
285 memset(&cap
, 0, sizeof(cap
));
287 cap
.ConType
= TWON_DONTCARE16
;
289 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
290 get_condition_code(appid
, source
, &status
);
291 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
292 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
293 if (rc
!= TWRC_SUCCESS
)
295 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
296 ok((actual_support
& minimum_support
) == minimum_support
,
297 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
298 captype
, actual_support
);
301 if (actual_support
& TWQC_GETCURRENT
)
303 memset(&cap
, 0, sizeof(cap
));
305 cap
.ConType
= TWON_DONTCARE16
;
307 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
308 get_condition_code(appid
, source
, &status
);
309 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
310 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
311 if (rc
== TWRC_SUCCESS
)
313 get_onevalue(cap
.hContainer
, &val
, &type
);
314 ok(type
== TWTY_FIX32
, "GETCURRENT for RESOLUTION is not type FIX32, is type %d\n", type
);
315 memcpy(&orig_value
, &val
, sizeof(orig_value
));
316 GlobalFree(cap
.hContainer
);
320 if (actual_support
& TWQC_GETDEFAULT
)
322 memset(&cap
, 0, sizeof(cap
));
324 cap
.ConType
= TWON_DONTCARE16
;
326 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
327 get_condition_code(appid
, source
, &status
);
328 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
329 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
330 if (rc
== TWRC_SUCCESS
)
332 ok(type
== TWTY_FIX32
, "GETDEFAULT for RESOLUTION is not type FIX32, is type %d\n", type
);
333 memcpy(&default_value
, &val
, sizeof(default_value
));
334 GlobalFree(cap
.hContainer
);
338 if (actual_support
& TWQC_GET
)
340 memset(&cap
, 0, sizeof(cap
));
342 cap
.ConType
= TWON_DONTCARE16
;
344 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
345 get_condition_code(appid
, source
, &status
);
346 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
347 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
348 if (rc
== TWRC_SUCCESS
)
351 ok(cap
.ConType
== TWON_RANGE
, "MSG_GET for ICAP_[XY]RESOLUTION did not return TWON_RANGE, but %d\n", cap
.ConType
);
352 range
= GlobalLock(cap
.hContainer
);
353 trace("MSG_GET of 0x%x returned [ItemType %d|MinValue %d|MaxValue %d|StepSize %d|DefaultValue %d|CurrentValue %d]:\n",
354 cap
.Cap
, range
->ItemType
, range
->MinValue
, range
->MaxValue
, range
->StepSize
,
355 range
->DefaultValue
, range
->CurrentValue
);
356 for (new_value
= range
->MinValue
; new_value
< range
->MaxValue
; new_value
+= range
->StepSize
)
357 if (new_value
!= range
->CurrentValue
)
359 GlobalUnlock(cap
.hContainer
);
360 GlobalFree(cap
.hContainer
);
364 if (actual_support
& TWQC_SET
)
366 memset(&cap
, 0, sizeof(cap
));
368 cap
.ConType
= TWON_ONEVALUE
;
369 cap
.hContainer
= alloc_and_set_onevalue(new_value
, TWTY_FIX32
);
371 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
372 get_condition_code(appid
, source
, &status
);
373 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
374 "Error [rc %d|cc %d] doing MSG_SET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
375 GlobalFree(cap
.hContainer
);
379 if (actual_support
& TWQC_RESET
)
381 memset(&cap
, 0, sizeof(cap
));
383 cap
.ConType
= TWON_DONTCARE16
;
385 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
386 get_condition_code(appid
, source
, &status
);
387 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
388 "Error [rc %d|cc %d] doing MSG_RESET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
389 if (rc
== TWRC_SUCCESS
)
390 GlobalFree(cap
.hContainer
);
394 static void test_physical(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_INT32 minimum_support
)
401 TW_INT32 actual_support
;
403 memset(&cap
, 0, sizeof(cap
));
405 cap
.ConType
= TWON_DONTCARE16
;
407 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
408 get_condition_code(appid
, source
, &status
);
409 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
410 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
411 if (rc
!= TWRC_SUCCESS
)
413 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
414 ok((actual_support
& minimum_support
) == minimum_support
,
415 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
416 captype
, actual_support
);
419 if (actual_support
& TWQC_GETCURRENT
)
421 memset(&cap
, 0, sizeof(cap
));
423 cap
.ConType
= TWON_DONTCARE16
;
425 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
426 get_condition_code(appid
, source
, &status
);
427 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
428 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
429 if (rc
== TWRC_SUCCESS
)
431 get_onevalue(cap
.hContainer
, &val
, &type
);
432 ok(type
== TWTY_FIX32
, "GETCURRENT for PHYSICALXXX is not type FIX32, is type %d\n", type
);
433 GlobalFree(cap
.hContainer
);
437 if (actual_support
& TWQC_GETDEFAULT
)
439 memset(&cap
, 0, sizeof(cap
));
441 cap
.ConType
= TWON_DONTCARE16
;
443 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
444 get_condition_code(appid
, source
, &status
);
445 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
446 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
447 if (rc
== TWRC_SUCCESS
)
449 get_onevalue(cap
.hContainer
, &val
, &type
);
450 ok(type
== TWTY_FIX32
, "GETDEFAULT for PHYSICALXXX is not type FIX32, is type %d\n", type
);
451 GlobalFree(cap
.hContainer
);
455 if (actual_support
& TWQC_GET
)
457 memset(&cap
, 0, sizeof(cap
));
459 cap
.ConType
= TWON_DONTCARE16
;
461 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
462 get_condition_code(appid
, source
, &status
);
463 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
464 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
465 if (rc
== TWRC_SUCCESS
)
467 get_onevalue(cap
.hContainer
, &val
, &type
);
468 ok(type
== TWTY_FIX32
, "GET for PHYSICALXXX is not type FIX32, is type %d\n", type
);
469 trace("GET for Physical type 0x%x returns 0x%x\n", captype
, val
);
470 GlobalFree(cap
.hContainer
);
476 static void test_supported_sizes(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_INT32 minimum_support
)
483 TW_INT32 actual_support
;
484 TW_UINT32 orig_value
;
485 TW_UINT32 default_value
;
486 TW_UINT32 new_value
= TWSS_NONE
;
489 memset(&cap
, 0, sizeof(cap
));
490 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
491 cap
.ConType
= TWON_DONTCARE16
;
493 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
494 get_condition_code(appid
, source
, &status
);
495 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
496 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
497 if (rc
!= TWRC_SUCCESS
)
499 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on ICAP_SUPPORTEDSIZES\n");
500 ok((actual_support
& minimum_support
) == minimum_support
,
501 "Error: minimum support 0x%x for ICAP_SUPPORTEDSIZES, got 0x%x\n", minimum_support
, actual_support
);
503 if (actual_support
& TWQC_GETCURRENT
)
505 memset(&cap
, 0, sizeof(cap
));
506 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
507 cap
.ConType
= TWON_DONTCARE16
;
509 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
510 get_condition_code(appid
, source
, &status
);
511 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
512 "Error [rc %d|cc %d] doing MSG_GETCURRENT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
513 if (rc
== TWRC_SUCCESS
)
515 get_onevalue(cap
.hContainer
, &val
, &type
);
516 ok(type
== TWTY_UINT16
, "GETCURRENT for ICAP_SUPPORTEDSIZES is not type UINT16, is type %d\n", type
);
517 trace("Current size is %d\n", val
);
518 GlobalFree(cap
.hContainer
);
523 if (actual_support
& TWQC_GETDEFAULT
)
525 memset(&cap
, 0, sizeof(cap
));
526 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
527 cap
.ConType
= TWON_DONTCARE16
;
529 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
530 get_condition_code(appid
, source
, &status
);
531 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
532 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
533 if (rc
== TWRC_SUCCESS
)
535 get_onevalue(cap
.hContainer
, &val
, &type
);
536 ok(type
== TWTY_UINT16
, "GETDEFAULT for PHYSICALXXX is not type TWTY_UINT16, is type %d\n", type
);
537 trace("Default size is %d\n", val
);
538 GlobalFree(cap
.hContainer
);
543 if (actual_support
& TWQC_GET
)
545 memset(&cap
, 0, sizeof(cap
));
546 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
547 cap
.ConType
= TWON_DONTCARE16
;
549 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
550 get_condition_code(appid
, source
, &status
);
551 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
552 "Error [rc %d|cc %d] doing MSG_GET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
553 check_get(&cap
, actual_support
, orig_value
, default_value
, &new_value
);
556 if (actual_support
& TWQC_SET
)
558 memset(&cap
, 0, sizeof(cap
));
559 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
560 cap
.ConType
= TWON_ONEVALUE
;
561 cap
.hContainer
= alloc_and_set_onevalue(new_value
, TWTY_UINT16
);
563 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
564 get_condition_code(appid
, source
, &status
);
565 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
566 "Error [rc %d|cc %d] doing MSG_SET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
567 GlobalFree(cap
.hContainer
);
571 if (actual_support
& TWQC_RESET
)
573 memset(&cap
, 0, sizeof(cap
));
574 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
575 cap
.ConType
= TWON_DONTCARE16
;
577 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
578 get_condition_code(appid
, source
, &status
);
579 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
580 "Error [rc %d|cc %d] doing MSG_RESET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
581 if (rc
== TWRC_SUCCESS
)
582 GlobalFree(cap
.hContainer
);
587 static void test_single_source(TW_IDENTITY
*appid
, TW_IDENTITY
*source
)
592 UINT16 capabilities
[CAP_CUSTOMBASE
];
594 memset(&cap
, 0, sizeof(cap
));
595 cap
.Cap
= CAP_SUPPORTEDCAPS
;
596 cap
.ConType
= TWON_DONTCARE16
;
598 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
599 get_condition_code(appid
, source
, &status
);
600 ok(rc
== TWRC_SUCCESS
|| status
.ConditionCode
== TWCC_SUCCESS
,
601 "Error obtaining CAP_SUPPORTEDCAPS\n");
603 memset(capabilities
, 0, sizeof(capabilities
));
604 if (rc
== TWRC_SUCCESS
&& cap
.ConType
== TWON_ARRAY
)
607 a
= GlobalLock(cap
.hContainer
);
610 if (a
->ItemType
== TWTY_UINT16
)
613 UINT16
*u
= (UINT16
*) a
->ItemList
;
614 trace("%d Capabilities:\n", a
->NumItems
);
615 for (i
= 0; i
< a
->NumItems
; i
++)
616 if (u
[i
] < sizeof(capabilities
) / sizeof(capabilities
[0]))
618 capabilities
[u
[i
]] = 1;
619 trace(" %d: 0x%x\n", i
, u
[i
]);
622 GlobalUnlock(cap
.hContainer
);
626 /* For Twain 1.6, all sources must support: */
627 ok(capabilities
[CAP_SUPPORTEDCAPS
], "CAP_SUPPORTEDCAPS not supported\n");
628 ok(capabilities
[CAP_XFERCOUNT
], "CAP_XFERCOUNT not supported\n");
629 if (capabilities
[CAP_XFERCOUNT
])
630 test_onevalue_cap(appid
, source
, CAP_XFERCOUNT
, TWTY_INT16
,
631 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
632 ok(capabilities
[CAP_UICONTROLLABLE
], "CAP_UICONTROLLABLE not supported\n");
633 if (capabilities
[CAP_UICONTROLLABLE
])
634 test_onevalue_cap(appid
, source
, CAP_UICONTROLLABLE
, TWTY_BOOL
, TWQC_GET
);
636 if (source
->SupportedGroups
& DG_IMAGE
)
639 Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
640 MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT on:
642 ok(capabilities
[ICAP_COMPRESSION
], "ICAP_COMPRESSION not supported\n");
643 if (capabilities
[ICAP_COMPRESSION
])
644 test_onevalue_cap(appid
, source
, ICAP_COMPRESSION
, TWTY_UINT16
,
645 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
647 ok(capabilities
[ICAP_PLANARCHUNKY
], "ICAP_PLANARCHUNKY not supported\n");
648 ok(capabilities
[ICAP_PHYSICALHEIGHT
], "ICAP_PHYSICALHEIGHT not supported\n");
649 if (capabilities
[ICAP_PHYSICALHEIGHT
])
650 test_physical(appid
, source
, ICAP_PHYSICALHEIGHT
,
651 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
652 ok(capabilities
[ICAP_PHYSICALWIDTH
], "ICAP_PHYSICALWIDTH not supported\n");
653 if (capabilities
[ICAP_PHYSICALWIDTH
])
654 test_physical(appid
, source
, ICAP_PHYSICALWIDTH
,
655 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
656 ok(capabilities
[ICAP_PIXELFLAVOR
], "ICAP_PIXELFLAVOR not supported\n");
657 if (capabilities
[ICAP_PIXELFLAVOR
])
658 test_onevalue_cap(appid
, source
, ICAP_PIXELFLAVOR
, TWTY_UINT16
,
659 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
662 Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
663 MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT, MSG_RESET and MSG_SET on:
665 ok(capabilities
[ICAP_BITDEPTH
], "ICAP_BITDEPTH not supported\n");
666 if (capabilities
[ICAP_BITDEPTH
])
667 test_onevalue_cap(appid
, source
, ICAP_BITDEPTH
, TWTY_UINT16
,
668 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
670 ok(capabilities
[ICAP_BITORDER
], "ICAP_BITORDER not supported\n");
671 ok(capabilities
[ICAP_PIXELTYPE
], "ICAP_PIXELTYPE not supported\n");
672 if (capabilities
[ICAP_PIXELTYPE
])
673 test_onevalue_cap(appid
, source
, ICAP_PIXELTYPE
, TWTY_UINT16
,
674 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
675 ok(capabilities
[ICAP_UNITS
], "ICAP_UNITS not supported\n");
676 if (capabilities
[ICAP_UNITS
])
677 test_onevalue_cap(appid
, source
, ICAP_UNITS
, TWTY_UINT16
,
678 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
679 ok(capabilities
[ICAP_XFERMECH
], "ICAP_XFERMECH not supported\n");
680 if (capabilities
[ICAP_XFERMECH
])
681 test_onevalue_cap(appid
, source
, ICAP_XFERMECH
, TWTY_UINT16
,
682 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
683 ok(capabilities
[ICAP_XRESOLUTION
], "ICAP_XRESOLUTION not supported\n");
684 if (capabilities
[ICAP_XRESOLUTION
])
685 test_resolution(appid
, source
, ICAP_XRESOLUTION
,
686 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
687 ok(capabilities
[ICAP_YRESOLUTION
], "ICAP_YRESOLUTION not supported\n");
688 if (capabilities
[ICAP_YRESOLUTION
])
689 test_resolution(appid
, source
, ICAP_YRESOLUTION
,
690 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
692 /* Optional capabilities */
693 if (capabilities
[CAP_AUTOFEED
])
694 test_onevalue_cap(appid
, source
, CAP_AUTOFEED
, TWTY_BOOL
,
695 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
696 if (capabilities
[CAP_FEEDERENABLED
])
697 test_onevalue_cap(appid
, source
, CAP_FEEDERENABLED
, TWTY_BOOL
,
698 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
699 if (capabilities
[ICAP_SUPPORTEDSIZES
])
700 test_supported_sizes(appid
, source
,
701 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
706 static void test_sources(TW_IDENTITY
*appid
)
711 int scannercount
= 0;
713 memset(&source
, 0, sizeof(source
));
714 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETFIRST
, &source
);
715 get_condition_code(appid
, NULL
, &status
);
716 ok( (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
) ||
717 (rc
== TWRC_FAILURE
&& status
.ConditionCode
== TWCC_NODS
),
718 "Get first invalid condition code, rc %d, cc %d\n", rc
, status
.ConditionCode
);
720 while (rc
== TWRC_SUCCESS
)
723 trace("[Scanner %d|Version %d.%d(%s)|Protocol %d.%d|SupportedGroups 0x%x|Manufacturer %s|Family %s|ProductName %s]\n",
725 source
.Version
.MajorNum
, source
.Version
.MinorNum
, source
.Version
.Info
,
726 source
.ProtocolMajor
, source
.ProtocolMinor
, source
.SupportedGroups
,
727 source
.Manufacturer
, source
.ProductFamily
, source
.ProductName
);
728 memset(&source
, 0, sizeof(source
));
729 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETNEXT
, &source
);
730 get_condition_code(appid
, NULL
, &status
);
731 ok(rc
== TWRC_SUCCESS
|| rc
== TWRC_ENDOFLIST
, "Get next source failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
734 memset(&source
, 0, sizeof(source
));
735 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETDEFAULT
, &source
);
736 get_condition_code(appid
, NULL
, &status
);
737 ok( (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
) ||
738 (rc
== TWRC_FAILURE
&& status
.ConditionCode
== TWCC_NODS
),
739 "Get default invalid condition code, rc %d, cc %d\n", rc
, status
.ConditionCode
);
741 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
743 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &source
);
744 get_condition_code(appid
, NULL
, &status
);
746 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
748 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &source
);
749 get_condition_code(appid
, NULL
, &status
);
750 ok(rc
== TWRC_SUCCESS
, "Close DS Failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
754 if (winetest_interactive
)
756 trace("Interactive, so trying userselect\n");
757 memset(&source
, 0, sizeof(source
));
758 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_USERSELECT
, &source
);
759 get_condition_code(appid
, NULL
, &status
);
760 ok(rc
== TWRC_SUCCESS
|| rc
== TWRC_CANCEL
, "Userselect failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
762 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
764 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &source
);
765 get_condition_code(appid
, NULL
, &status
);
766 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
768 test_single_source(appid
, &source
);
769 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &source
);
770 get_condition_code(appid
, NULL
, &status
);
771 ok(rc
== TWRC_SUCCESS
, "Close DS Failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
785 if (!dsm_RegisterWindowClasses()) assert(0);
787 htwain
= LoadLibraryA("twain_32.dll");
790 win_skip("twain_32.dll not available, skipping tests\n");
793 pDSM_Entry
= (void*)GetProcAddress(htwain
, "DSM_Entry");
794 ok(pDSM_Entry
!= NULL
, "Unable to GetProcAddress DSM_Entry\n");
797 win_skip("DSM_Entry not available, skipping tests\n");
801 memset(&appid
, 0, sizeof(appid
));
802 appid
.Version
.Language
= TWLG_ENGLISH_USA
;
803 appid
.Version
.Country
= TWCY_USA
;
804 appid
.ProtocolMajor
= TWON_PROTOCOLMAJOR
;
805 appid
.ProtocolMinor
= TWON_PROTOCOLMINOR
;
806 appid
.SupportedGroups
= DG_CONTROL
| DG_IMAGE
;
808 hwnd
= CreateWindow("TWAIN_dsm_class", "Twain Test", 0,
809 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
810 NULL
, NULL
, GetModuleHandleA(0), NULL
);
812 rc
= pDSM_Entry(&appid
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_OPENDSM
, (TW_MEMREF
) &hwnd
);
813 ok(rc
== TWRC_SUCCESS
, "MSG_OPENDSM returned %d\n", rc
);
815 test_sources(&appid
);
817 rc
= pDSM_Entry(&appid
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_CLOSEDSM
, (TW_MEMREF
) &hwnd
);
818 ok(rc
== TWRC_SUCCESS
, "MSG_CLOSEDSM returned %d\n", rc
);