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 get_onevalue(cap
.hContainer
, &val
, &type
);
333 ok(type
== TWTY_FIX32
, "GETDEFAULT for RESOLUTION is not type FIX32, is type %d\n", type
);
334 memcpy(&default_value
, &val
, sizeof(default_value
));
335 GlobalFree(cap
.hContainer
);
339 if (actual_support
& TWQC_GET
)
341 memset(&cap
, 0, sizeof(cap
));
343 cap
.ConType
= TWON_DONTCARE16
;
345 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
346 get_condition_code(appid
, source
, &status
);
347 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
348 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
349 if (rc
== TWRC_SUCCESS
)
352 ok(cap
.ConType
== TWON_RANGE
, "MSG_GET for ICAP_[XY]RESOLUTION did not return TWON_RANGE, but %d\n", cap
.ConType
);
353 range
= GlobalLock(cap
.hContainer
);
354 trace("MSG_GET of 0x%x returned [ItemType %d|MinValue %d|MaxValue %d|StepSize %d|DefaultValue %d|CurrentValue %d]:\n",
355 cap
.Cap
, range
->ItemType
, range
->MinValue
, range
->MaxValue
, range
->StepSize
,
356 range
->DefaultValue
, range
->CurrentValue
);
357 for (new_value
= range
->MinValue
; new_value
< range
->MaxValue
; new_value
+= range
->StepSize
)
358 if (new_value
!= range
->CurrentValue
)
360 GlobalUnlock(cap
.hContainer
);
361 GlobalFree(cap
.hContainer
);
365 if (actual_support
& TWQC_SET
)
367 memset(&cap
, 0, sizeof(cap
));
369 cap
.ConType
= TWON_ONEVALUE
;
370 cap
.hContainer
= alloc_and_set_onevalue(new_value
, TWTY_FIX32
);
372 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
373 get_condition_code(appid
, source
, &status
);
374 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
375 "Error [rc %d|cc %d] doing MSG_SET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
376 GlobalFree(cap
.hContainer
);
380 if (actual_support
& TWQC_RESET
)
382 memset(&cap
, 0, sizeof(cap
));
384 cap
.ConType
= TWON_DONTCARE16
;
386 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
387 get_condition_code(appid
, source
, &status
);
388 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
389 "Error [rc %d|cc %d] doing MSG_RESET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
390 if (rc
== TWRC_SUCCESS
)
391 GlobalFree(cap
.hContainer
);
395 static void test_physical(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_INT32 minimum_support
)
402 TW_INT32 actual_support
;
404 memset(&cap
, 0, sizeof(cap
));
406 cap
.ConType
= TWON_DONTCARE16
;
408 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
409 get_condition_code(appid
, source
, &status
);
410 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
411 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
412 if (rc
!= TWRC_SUCCESS
)
414 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
415 ok((actual_support
& minimum_support
) == minimum_support
,
416 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
417 captype
, actual_support
);
420 if (actual_support
& TWQC_GETCURRENT
)
422 memset(&cap
, 0, sizeof(cap
));
424 cap
.ConType
= TWON_DONTCARE16
;
426 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
427 get_condition_code(appid
, source
, &status
);
428 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
429 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
430 if (rc
== TWRC_SUCCESS
)
432 get_onevalue(cap
.hContainer
, &val
, &type
);
433 ok(type
== TWTY_FIX32
, "GETCURRENT for PHYSICALXXX is not type FIX32, is type %d\n", type
);
434 GlobalFree(cap
.hContainer
);
438 if (actual_support
& TWQC_GETDEFAULT
)
440 memset(&cap
, 0, sizeof(cap
));
442 cap
.ConType
= TWON_DONTCARE16
;
444 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
445 get_condition_code(appid
, source
, &status
);
446 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
447 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
448 if (rc
== TWRC_SUCCESS
)
450 get_onevalue(cap
.hContainer
, &val
, &type
);
451 ok(type
== TWTY_FIX32
, "GETDEFAULT for PHYSICALXXX is not type FIX32, is type %d\n", type
);
452 GlobalFree(cap
.hContainer
);
456 if (actual_support
& TWQC_GET
)
458 memset(&cap
, 0, sizeof(cap
));
460 cap
.ConType
= TWON_DONTCARE16
;
462 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
463 get_condition_code(appid
, source
, &status
);
464 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
465 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
466 if (rc
== TWRC_SUCCESS
)
468 get_onevalue(cap
.hContainer
, &val
, &type
);
469 ok(type
== TWTY_FIX32
, "GET for PHYSICALXXX is not type FIX32, is type %d\n", type
);
470 trace("GET for Physical type 0x%x returns 0x%x\n", captype
, val
);
471 GlobalFree(cap
.hContainer
);
477 static void test_supported_sizes(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_INT32 minimum_support
)
484 TW_INT32 actual_support
;
485 TW_UINT32 orig_value
= TWSS_NONE
;
486 TW_UINT32 default_value
= TWSS_NONE
;
487 TW_UINT32 new_value
= TWSS_NONE
;
490 memset(&cap
, 0, sizeof(cap
));
491 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
492 cap
.ConType
= TWON_DONTCARE16
;
494 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
495 get_condition_code(appid
, source
, &status
);
496 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
497 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
498 if (rc
!= TWRC_SUCCESS
)
500 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on ICAP_SUPPORTEDSIZES\n");
501 ok((actual_support
& minimum_support
) == minimum_support
,
502 "Error: minimum support 0x%x for ICAP_SUPPORTEDSIZES, got 0x%x\n", minimum_support
, actual_support
);
504 if (actual_support
& TWQC_GETCURRENT
)
506 memset(&cap
, 0, sizeof(cap
));
507 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
508 cap
.ConType
= TWON_DONTCARE16
;
510 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
511 get_condition_code(appid
, source
, &status
);
512 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
513 "Error [rc %d|cc %d] doing MSG_GETCURRENT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
514 if (rc
== TWRC_SUCCESS
)
516 get_onevalue(cap
.hContainer
, &val
, &type
);
517 ok(type
== TWTY_UINT16
, "GETCURRENT for ICAP_SUPPORTEDSIZES is not type UINT16, is type %d\n", type
);
518 trace("Current size is %d\n", val
);
519 GlobalFree(cap
.hContainer
);
524 if (actual_support
& TWQC_GETDEFAULT
)
526 memset(&cap
, 0, sizeof(cap
));
527 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
528 cap
.ConType
= TWON_DONTCARE16
;
530 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
531 get_condition_code(appid
, source
, &status
);
532 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
533 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
534 if (rc
== TWRC_SUCCESS
)
536 get_onevalue(cap
.hContainer
, &val
, &type
);
537 ok(type
== TWTY_UINT16
, "GETDEFAULT for PHYSICALXXX is not type TWTY_UINT16, is type %d\n", type
);
538 trace("Default size is %d\n", val
);
539 GlobalFree(cap
.hContainer
);
544 if (actual_support
& TWQC_GET
)
546 memset(&cap
, 0, sizeof(cap
));
547 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
548 cap
.ConType
= TWON_DONTCARE16
;
550 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
551 get_condition_code(appid
, source
, &status
);
552 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
553 "Error [rc %d|cc %d] doing MSG_GET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
554 check_get(&cap
, actual_support
, orig_value
, default_value
, &new_value
);
557 if (actual_support
& TWQC_SET
)
559 memset(&cap
, 0, sizeof(cap
));
560 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
561 cap
.ConType
= TWON_ONEVALUE
;
562 cap
.hContainer
= alloc_and_set_onevalue(new_value
, TWTY_UINT16
);
564 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
565 get_condition_code(appid
, source
, &status
);
566 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
567 "Error [rc %d|cc %d] doing MSG_SET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
568 GlobalFree(cap
.hContainer
);
572 if (actual_support
& TWQC_RESET
)
574 memset(&cap
, 0, sizeof(cap
));
575 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
576 cap
.ConType
= TWON_DONTCARE16
;
578 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
579 get_condition_code(appid
, source
, &status
);
580 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
581 "Error [rc %d|cc %d] doing MSG_RESET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
582 if (rc
== TWRC_SUCCESS
)
583 GlobalFree(cap
.hContainer
);
587 static void test_imagelayout(TW_IDENTITY
*appid
, TW_IDENTITY
*source
)
591 TW_IMAGELAYOUT layout
;
593 rc
= pDSM_Entry(appid
, source
, DG_IMAGE
, DAT_IMAGELAYOUT
, MSG_GET
, &layout
);
594 get_condition_code(appid
, source
, &status
);
595 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
596 "Error [rc %d|cc %d] doing MSG_GET for DG_IMAGE/DAT_IMAGELAYOUT\n", rc
, status
.ConditionCode
);
597 if (rc
!= TWRC_SUCCESS
)
599 trace("ImageLayout [Left %x.%x|Top %x.%x|Right %x.%x|Bottom %x.%x|Document %d|Page %d|Frame %d]\n",
600 layout
.Frame
.Left
.Whole
, layout
.Frame
.Left
.Frac
,
601 layout
.Frame
.Top
.Whole
, layout
.Frame
.Top
.Frac
,
602 layout
.Frame
.Right
.Whole
, layout
.Frame
.Right
.Frac
,
603 layout
.Frame
.Bottom
.Whole
, layout
.Frame
.Bottom
.Frac
,
604 layout
.DocumentNumber
, layout
.PageNumber
, layout
.FrameNumber
);
606 memset(&layout
, 0, sizeof(layout
));
607 layout
.Frame
.Left
.Whole
= 1;
608 layout
.Frame
.Right
.Whole
= 2;
609 layout
.Frame
.Top
.Whole
= 1;
610 layout
.Frame
.Bottom
.Whole
= 2;
611 rc
= pDSM_Entry(appid
, source
, DG_IMAGE
, DAT_IMAGELAYOUT
, MSG_SET
, &layout
);
612 get_condition_code(appid
, source
, &status
);
613 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
614 "Error [rc %d|cc %d] doing MSG_SET for DG_IMAGE/DAT_IMAGELAYOUT\n", rc
, status
.ConditionCode
);
615 if (rc
!= TWRC_SUCCESS
)
618 rc
= pDSM_Entry(appid
, source
, DG_IMAGE
, DAT_IMAGELAYOUT
, MSG_GET
, &layout
);
619 get_condition_code(appid
, source
, &status
);
620 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
621 "Error [rc %d|cc %d] doing MSG_GET for DG_IMAGE/DAT_IMAGELAYOUT\n", rc
, status
.ConditionCode
);
622 if (rc
!= TWRC_SUCCESS
)
624 trace("ImageLayout after set [Left %x.%x|Top %x.%x|Right %x.%x|Bottom %x.%x|Document %d|Page %d|Frame %d]\n",
625 layout
.Frame
.Left
.Whole
, layout
.Frame
.Left
.Frac
,
626 layout
.Frame
.Top
.Whole
, layout
.Frame
.Top
.Frac
,
627 layout
.Frame
.Right
.Whole
, layout
.Frame
.Right
.Frac
,
628 layout
.Frame
.Bottom
.Whole
, layout
.Frame
.Bottom
.Frac
,
629 layout
.DocumentNumber
, layout
.PageNumber
, layout
.FrameNumber
);
633 static void test_single_source(TW_IDENTITY
*appid
, TW_IDENTITY
*source
)
638 UINT16 capabilities
[CAP_CUSTOMBASE
];
640 memset(&cap
, 0, sizeof(cap
));
641 cap
.Cap
= CAP_SUPPORTEDCAPS
;
642 cap
.ConType
= TWON_DONTCARE16
;
644 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
645 get_condition_code(appid
, source
, &status
);
646 ok(rc
== TWRC_SUCCESS
|| status
.ConditionCode
== TWCC_SUCCESS
,
647 "Error obtaining CAP_SUPPORTEDCAPS\n");
649 memset(capabilities
, 0, sizeof(capabilities
));
650 if (rc
== TWRC_SUCCESS
&& cap
.ConType
== TWON_ARRAY
)
653 a
= GlobalLock(cap
.hContainer
);
656 if (a
->ItemType
== TWTY_UINT16
)
659 UINT16
*u
= (UINT16
*) a
->ItemList
;
660 trace("%d Capabilities:\n", a
->NumItems
);
661 for (i
= 0; i
< a
->NumItems
; i
++)
662 if (u
[i
] < sizeof(capabilities
) / sizeof(capabilities
[0]))
664 capabilities
[u
[i
]] = 1;
665 trace(" %d: 0x%x\n", i
, u
[i
]);
668 GlobalUnlock(cap
.hContainer
);
672 /* All sources must support: */
673 ok(capabilities
[CAP_SUPPORTEDCAPS
], "CAP_SUPPORTEDCAPS not supported\n");
674 ok(capabilities
[CAP_XFERCOUNT
], "CAP_XFERCOUNT not supported\n");
675 if (capabilities
[CAP_XFERCOUNT
])
676 test_onevalue_cap(appid
, source
, CAP_XFERCOUNT
, TWTY_INT16
,
677 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
678 ok(capabilities
[CAP_UICONTROLLABLE
], "CAP_UICONTROLLABLE not supported\n");
679 if (capabilities
[CAP_UICONTROLLABLE
])
680 test_onevalue_cap(appid
, source
, CAP_UICONTROLLABLE
, TWTY_BOOL
, TWQC_GET
);
682 if (source
->SupportedGroups
& DG_IMAGE
)
685 Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
686 MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT on:
688 ok(capabilities
[ICAP_COMPRESSION
], "ICAP_COMPRESSION not supported\n");
689 if (capabilities
[ICAP_COMPRESSION
])
690 test_onevalue_cap(appid
, source
, ICAP_COMPRESSION
, TWTY_UINT16
,
691 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
693 ok(capabilities
[ICAP_PLANARCHUNKY
], "ICAP_PLANARCHUNKY not supported\n");
694 ok(capabilities
[ICAP_PHYSICALHEIGHT
], "ICAP_PHYSICALHEIGHT not supported\n");
695 if (capabilities
[ICAP_PHYSICALHEIGHT
])
696 test_physical(appid
, source
, ICAP_PHYSICALHEIGHT
,
697 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
698 ok(capabilities
[ICAP_PHYSICALWIDTH
], "ICAP_PHYSICALWIDTH not supported\n");
699 if (capabilities
[ICAP_PHYSICALWIDTH
])
700 test_physical(appid
, source
, ICAP_PHYSICALWIDTH
,
701 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
702 ok(capabilities
[ICAP_PIXELFLAVOR
], "ICAP_PIXELFLAVOR not supported\n");
703 if (capabilities
[ICAP_PIXELFLAVOR
])
704 test_onevalue_cap(appid
, source
, ICAP_PIXELFLAVOR
, TWTY_UINT16
,
705 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
708 Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
709 MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT, MSG_RESET and MSG_SET on:
711 ok(capabilities
[ICAP_BITDEPTH
], "ICAP_BITDEPTH not supported\n");
712 if (capabilities
[ICAP_BITDEPTH
])
713 test_onevalue_cap(appid
, source
, ICAP_BITDEPTH
, TWTY_UINT16
,
714 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
716 ok(capabilities
[ICAP_BITORDER
], "ICAP_BITORDER not supported\n");
717 ok(capabilities
[ICAP_PIXELTYPE
], "ICAP_PIXELTYPE not supported\n");
718 if (capabilities
[ICAP_PIXELTYPE
])
719 test_onevalue_cap(appid
, source
, ICAP_PIXELTYPE
, TWTY_UINT16
,
720 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
721 ok(capabilities
[ICAP_UNITS
], "ICAP_UNITS not supported\n");
722 if (capabilities
[ICAP_UNITS
])
723 test_onevalue_cap(appid
, source
, ICAP_UNITS
, TWTY_UINT16
,
724 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
725 ok(capabilities
[ICAP_XFERMECH
], "ICAP_XFERMECH not supported\n");
726 if (capabilities
[ICAP_XFERMECH
])
727 test_onevalue_cap(appid
, source
, ICAP_XFERMECH
, TWTY_UINT16
,
728 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
729 ok(capabilities
[ICAP_XRESOLUTION
], "ICAP_XRESOLUTION not supported\n");
730 if (capabilities
[ICAP_XRESOLUTION
])
731 test_resolution(appid
, source
, ICAP_XRESOLUTION
,
732 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
733 ok(capabilities
[ICAP_YRESOLUTION
], "ICAP_YRESOLUTION not supported\n");
734 if (capabilities
[ICAP_YRESOLUTION
])
735 test_resolution(appid
, source
, ICAP_YRESOLUTION
,
736 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
738 /* Optional capabilities */
739 if (capabilities
[CAP_AUTOFEED
])
740 test_onevalue_cap(appid
, source
, CAP_AUTOFEED
, TWTY_BOOL
,
741 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
742 if (capabilities
[CAP_FEEDERENABLED
])
743 test_onevalue_cap(appid
, source
, CAP_FEEDERENABLED
, TWTY_BOOL
,
744 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
745 if (capabilities
[ICAP_SUPPORTEDSIZES
])
746 test_supported_sizes(appid
, source
,
747 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
749 /* Additional tests */
750 test_imagelayout(appid
, source
);
755 static void test_sources(TW_IDENTITY
*appid
)
760 int scannercount
= 0;
762 memset(&source
, 0, sizeof(source
));
763 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETFIRST
, &source
);
764 get_condition_code(appid
, NULL
, &status
);
765 ok( (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
) ||
766 (rc
== TWRC_FAILURE
&& status
.ConditionCode
== TWCC_NODS
),
767 "Get first invalid condition code, rc %d, cc %d\n", rc
, status
.ConditionCode
);
769 while (rc
== TWRC_SUCCESS
)
772 trace("[Scanner %d|Version %d.%d(%s)|Protocol %d.%d|SupportedGroups 0x%x|Manufacturer %s|Family %s|ProductName %s]\n",
774 source
.Version
.MajorNum
, source
.Version
.MinorNum
, source
.Version
.Info
,
775 source
.ProtocolMajor
, source
.ProtocolMinor
, source
.SupportedGroups
,
776 source
.Manufacturer
, source
.ProductFamily
, source
.ProductName
);
777 memset(&source
, 0, sizeof(source
));
778 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETNEXT
, &source
);
779 get_condition_code(appid
, NULL
, &status
);
780 ok(rc
== TWRC_SUCCESS
|| rc
== TWRC_ENDOFLIST
, "Get next source failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
783 memset(&source
, 0, sizeof(source
));
784 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETDEFAULT
, &source
);
785 get_condition_code(appid
, NULL
, &status
);
786 ok( (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
) ||
787 (rc
== TWRC_FAILURE
&& status
.ConditionCode
== TWCC_NODS
),
788 "Get default invalid condition code, rc %d, cc %d\n", rc
, status
.ConditionCode
);
790 /* A DS might display a Popup during MSG_OPENDS, when the scanner is not connected */
791 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
&& winetest_interactive
)
793 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &source
);
794 get_condition_code(appid
, NULL
, &status
);
796 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
798 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &source
);
799 get_condition_code(appid
, NULL
, &status
);
800 ok(rc
== TWRC_SUCCESS
, "Close DS Failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
804 if (winetest_interactive
)
806 trace("Interactive, so trying userselect\n");
807 memset(&source
, 0, sizeof(source
));
808 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_USERSELECT
, &source
);
809 get_condition_code(appid
, NULL
, &status
);
810 ok(rc
== TWRC_SUCCESS
|| rc
== TWRC_CANCEL
, "Userselect failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
812 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
814 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &source
);
815 get_condition_code(appid
, NULL
, &status
);
816 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
818 test_single_source(appid
, &source
);
819 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &source
);
820 get_condition_code(appid
, NULL
, &status
);
821 ok(rc
== TWRC_SUCCESS
, "Close DS Failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
835 if (!dsm_RegisterWindowClasses()) assert(0);
837 htwain
= LoadLibraryA("twain_32.dll");
840 win_skip("twain_32.dll not available, skipping tests\n");
843 pDSM_Entry
= (void*)GetProcAddress(htwain
, "DSM_Entry");
844 ok(pDSM_Entry
!= NULL
, "Unable to GetProcAddress DSM_Entry\n");
847 win_skip("DSM_Entry not available, skipping tests\n");
851 memset(&appid
, 0, sizeof(appid
));
852 appid
.Version
.Language
= TWLG_ENGLISH_USA
;
853 appid
.Version
.Country
= TWCY_USA
;
854 appid
.ProtocolMajor
= TWON_PROTOCOLMAJOR
;
855 appid
.ProtocolMinor
= TWON_PROTOCOLMINOR
;
856 appid
.SupportedGroups
= DG_CONTROL
| DG_IMAGE
;
858 hwnd
= CreateWindow("TWAIN_dsm_class", "Twain Test", 0,
859 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
860 NULL
, NULL
, GetModuleHandleA(0), NULL
);
862 rc
= pDSM_Entry(&appid
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_OPENDSM
, (TW_MEMREF
) &hwnd
);
863 ok(rc
== TWRC_SUCCESS
, "MSG_OPENDSM returned %d\n", rc
);
865 test_sources(&appid
);
867 rc
= pDSM_Entry(&appid
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_CLOSEDSM
, (TW_MEMREF
) &hwnd
);
868 ok(rc
== TWRC_SUCCESS
, "MSG_CLOSEDSM returned %d\n", rc
);