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)
39 cls
.lpfnWndProc
= DefWindowProcA
;
42 cls
.hInstance
= GetModuleHandleA(0);
44 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
45 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
46 cls
.lpszMenuName
= NULL
;
47 cls
.lpszClassName
= "TWAIN_dsm_class";
49 rc
= RegisterClassA(&cls
);
50 ok(rc
, "RegisterClassA failed: le=%u\n", GetLastError());
55 static void get_condition_code(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_STATUS
*status
)
58 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_STATUS
, MSG_GET
, status
);
59 ok(rc
== TWRC_SUCCESS
, "Condition code not available, rc %d\n", rc
);
62 static BOOL
get_onevalue(TW_HANDLE hcontainer
, TW_UINT32
*ret
, TW_UINT16
*type
)
65 onev
= GlobalLock(hcontainer
);
70 *type
= onev
->ItemType
;
71 GlobalUnlock(hcontainer
);
82 static TW_HANDLE
alloc_and_set_onevalue(TW_UINT32 val
, TW_UINT16 type
)
86 hcontainer
= GlobalAlloc(0, sizeof(*onev
));
89 onev
= GlobalLock(hcontainer
);
92 onev
->ItemType
= type
;
94 GlobalUnlock(hcontainer
);
98 GlobalFree(hcontainer
);
105 static void check_get(TW_CAPABILITY
*pCapability
, TW_INT32 actual_support
,
106 TW_UINT32 orig_value
, TW_UINT32 default_value
, TW_UINT32
*suggested_set_value
)
109 if (suggested_set_value
)
110 *suggested_set_value
= orig_value
+ 1;
111 p
= GlobalLock(pCapability
->hContainer
);
114 if (pCapability
->ConType
== TWON_ONEVALUE
)
116 TW_ONEVALUE
*onev
= p
;
117 ok(onev
->Item
== orig_value
|| !(actual_support
& TWQC_GETCURRENT
), "MSG_GET of 0x%x returned 0x%x, expecting 0x%x\n",
118 pCapability
->Cap
, onev
->Item
, orig_value
);
119 trace("MSG_GET of 0x%x returned val 0x%x, type %d\n", pCapability
->Cap
, onev
->Item
, onev
->ItemType
);
120 if (suggested_set_value
)
121 *suggested_set_value
= onev
->Item
;
123 else if (pCapability
->ConType
== TWON_ENUMERATION
)
129 TW_ENUMERATION
*enumv
= p
;
130 p8
= enumv
->ItemList
;
131 p16
= (TW_UINT16
*) p8
;
132 p32
= (TW_UINT32
*) p8
;
133 trace("MSG_GET of 0x%x returned %d items:\n", pCapability
->Cap
, enumv
->NumItems
);
134 for (i
= 0; i
< enumv
->NumItems
; i
++)
136 if (enumv
->ItemType
== TWTY_UINT8
|| enumv
->ItemType
== TWTY_INT8
)
137 trace(" %d: 0x%x\n", i
, p8
[i
]);
138 if (enumv
->ItemType
== TWTY_UINT16
|| enumv
->ItemType
== TWTY_INT16
)
139 trace(" %d: 0x%x\n", i
, p16
[i
]);
140 if (enumv
->ItemType
== TWTY_UINT32
|| enumv
->ItemType
== TWTY_INT32
)
141 trace(" %d: 0x%x\n", i
, p32
[i
]);
143 if (enumv
->ItemType
== TWTY_UINT16
|| enumv
->ItemType
== TWTY_INT16
)
145 ok(p16
[enumv
->CurrentIndex
] == orig_value
,
146 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETCURRENT (0x%x) do not match.\n",
147 pCapability
->Cap
, p16
[enumv
->CurrentIndex
], orig_value
);
148 ok(p16
[enumv
->DefaultIndex
] == default_value
,
149 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETDEFAULT (0x%x) do not match.\n",
150 pCapability
->Cap
, p16
[enumv
->DefaultIndex
], default_value
);
151 if (suggested_set_value
)
152 *suggested_set_value
= p16
[(enumv
->CurrentIndex
+ 1) % enumv
->NumItems
];
154 if (enumv
->ItemType
== TWTY_UINT32
|| enumv
->ItemType
== TWTY_INT32
)
156 ok(p32
[enumv
->CurrentIndex
] == orig_value
,
157 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETCURRENT (0x%x) do not match.\n",
158 pCapability
->Cap
, p32
[enumv
->CurrentIndex
], orig_value
);
159 ok(p32
[enumv
->DefaultIndex
] == default_value
,
160 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETDEFAULT (0x%x) do not match.\n",
161 pCapability
->Cap
, p32
[enumv
->DefaultIndex
], default_value
);
162 if (suggested_set_value
)
163 *suggested_set_value
= p32
[(enumv
->CurrentIndex
+ 1) % enumv
->NumItems
];
167 trace("MSG_GET on type 0x%x returned type 0x%x, which we didn't check.\n", pCapability
->Cap
, pCapability
->ConType
);
168 GlobalUnlock(pCapability
->hContainer
);
172 static void test_onevalue_cap(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_UINT16 type
, TW_INT32 minimum_support
)
178 TW_UINT32 orig_value
= 0;
180 TW_UINT32 default_value
= 0;
181 TW_INT32 actual_support
;
183 memset(&cap
, 0, sizeof(cap
));
185 cap
.ConType
= TWON_DONTCARE16
;
187 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
188 get_condition_code(appid
, source
, &status
);
189 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
190 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
191 if (rc
!= TWRC_SUCCESS
)
193 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
194 ok((actual_support
& minimum_support
) == minimum_support
,
195 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
196 captype
, actual_support
);
199 if (actual_support
& TWQC_GETCURRENT
)
201 memset(&cap
, 0, sizeof(cap
));
203 cap
.ConType
= TWON_DONTCARE16
;
205 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
206 get_condition_code(appid
, source
, &status
);
207 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
208 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
209 if (rc
== TWRC_SUCCESS
)
211 ok(get_onevalue(cap
.hContainer
, &orig_value
, &rtype
), "Returned cap.hContainer invalid for GETCURRENT on type 0x%x\n", captype
);
212 ok(rtype
== type
, "Returned GETCURRENT type 0x%x for cap 0x%x is not expected 0x%x\n", rtype
, captype
, type
);
213 GlobalFree(cap
.hContainer
);
217 if (actual_support
& TWQC_GETDEFAULT
)
219 memset(&cap
, 0, sizeof(cap
));
221 cap
.ConType
= TWON_DONTCARE16
;
223 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
224 get_condition_code(appid
, source
, &status
);
225 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
226 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
227 if (rc
== TWRC_SUCCESS
)
229 ok(get_onevalue(cap
.hContainer
, &default_value
, &rtype
), "Returned cap.hContainer invalid for GETDEFAULT on type 0x%x\n", captype
);
230 ok(rtype
== type
, "Returned GETDEFAULT type 0x%x for cap 0x%x is not expected 0x%x\n", rtype
, captype
, type
);
231 GlobalFree(cap
.hContainer
);
235 new_value
= orig_value
;
236 if (actual_support
& TWQC_GET
)
238 memset(&cap
, 0, sizeof(cap
));
240 cap
.ConType
= TWON_DONTCARE16
;
242 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
243 get_condition_code(appid
, source
, &status
);
244 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
245 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
246 check_get(&cap
, actual_support
, orig_value
, default_value
, &new_value
);
247 if (rc
== TWRC_SUCCESS
)
248 GlobalFree(cap
.hContainer
);
251 if (actual_support
& TWQC_SET
)
253 memset(&cap
, 0, sizeof(cap
));
255 cap
.ConType
= TWON_ONEVALUE
;
256 cap
.hContainer
= alloc_and_set_onevalue(new_value
, type
);
258 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
259 get_condition_code(appid
, source
, &status
);
260 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
261 "Error [rc %d|cc %d] doing MSG_SET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
262 GlobalFree(cap
.hContainer
);
265 if (actual_support
& TWQC_RESET
)
267 memset(&cap
, 0, sizeof(cap
));
269 cap
.ConType
= TWON_DONTCARE16
;
271 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
272 get_condition_code(appid
, source
, &status
);
273 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
274 "Error [rc %d|cc %d] doing MSG_RESET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
275 if (rc
== TWRC_SUCCESS
)
276 GlobalFree(cap
.hContainer
);
280 static void test_resolution(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_INT32 minimum_support
)
287 TW_INT32 actual_support
;
288 TW_FIX32 orig_value
= { 0, 0 };
289 TW_UINT32 new_value
= 0;
290 TW_FIX32 default_value
= { 0, 0 };
292 memset(&cap
, 0, sizeof(cap
));
294 cap
.ConType
= TWON_DONTCARE16
;
296 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
297 get_condition_code(appid
, source
, &status
);
298 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
299 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
300 if (rc
!= TWRC_SUCCESS
)
302 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
303 ok((actual_support
& minimum_support
) == minimum_support
,
304 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
305 captype
, actual_support
);
308 if (actual_support
& TWQC_GETCURRENT
)
310 memset(&cap
, 0, sizeof(cap
));
312 cap
.ConType
= TWON_DONTCARE16
;
314 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
315 get_condition_code(appid
, source
, &status
);
316 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
317 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
318 if (rc
== TWRC_SUCCESS
)
320 get_onevalue(cap
.hContainer
, &val
, &type
);
321 ok(type
== TWTY_FIX32
, "GETCURRENT for RESOLUTION is not type FIX32, is type %d\n", type
);
322 memcpy(&orig_value
, &val
, sizeof(orig_value
));
323 GlobalFree(cap
.hContainer
);
327 if (actual_support
& TWQC_GETDEFAULT
)
329 memset(&cap
, 0, sizeof(cap
));
331 cap
.ConType
= TWON_DONTCARE16
;
333 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
334 get_condition_code(appid
, source
, &status
);
335 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
336 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
337 if (rc
== TWRC_SUCCESS
)
339 get_onevalue(cap
.hContainer
, &val
, &type
);
340 ok(type
== TWTY_FIX32
, "GETDEFAULT for RESOLUTION is not type FIX32, is type %d\n", type
);
341 memcpy(&default_value
, &val
, sizeof(default_value
));
342 GlobalFree(cap
.hContainer
);
346 if (actual_support
& TWQC_GET
)
348 memset(&cap
, 0, sizeof(cap
));
350 cap
.ConType
= TWON_DONTCARE16
;
352 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
353 get_condition_code(appid
, source
, &status
);
354 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
355 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
356 if (rc
== TWRC_SUCCESS
)
359 ok(cap
.ConType
== TWON_RANGE
, "MSG_GET for ICAP_[XY]RESOLUTION did not return TWON_RANGE, but %d\n", cap
.ConType
);
360 range
= GlobalLock(cap
.hContainer
);
361 trace("MSG_GET of 0x%x returned [ItemType %d|MinValue %d|MaxValue %d|StepSize %d|DefaultValue %d|CurrentValue %d]:\n",
362 cap
.Cap
, range
->ItemType
, range
->MinValue
, range
->MaxValue
, range
->StepSize
,
363 range
->DefaultValue
, range
->CurrentValue
);
364 for (new_value
= range
->MinValue
; new_value
< range
->MaxValue
; new_value
+= range
->StepSize
)
365 if (new_value
!= range
->CurrentValue
)
367 GlobalUnlock(cap
.hContainer
);
368 GlobalFree(cap
.hContainer
);
372 if (actual_support
& TWQC_SET
)
374 memset(&cap
, 0, sizeof(cap
));
376 cap
.ConType
= TWON_ONEVALUE
;
377 cap
.hContainer
= alloc_and_set_onevalue(new_value
, TWTY_FIX32
);
379 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
380 get_condition_code(appid
, source
, &status
);
381 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
382 "Error [rc %d|cc %d] doing MSG_SET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
383 GlobalFree(cap
.hContainer
);
387 if (actual_support
& TWQC_RESET
)
389 memset(&cap
, 0, sizeof(cap
));
391 cap
.ConType
= TWON_DONTCARE16
;
393 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
394 get_condition_code(appid
, source
, &status
);
395 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
396 "Error [rc %d|cc %d] doing MSG_RESET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
397 if (rc
== TWRC_SUCCESS
)
398 GlobalFree(cap
.hContainer
);
402 static void test_physical(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_INT32 minimum_support
)
409 TW_INT32 actual_support
;
411 memset(&cap
, 0, sizeof(cap
));
413 cap
.ConType
= TWON_DONTCARE16
;
415 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
416 get_condition_code(appid
, source
, &status
);
417 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
418 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
419 if (rc
!= TWRC_SUCCESS
)
421 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
422 ok((actual_support
& minimum_support
) == minimum_support
,
423 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
424 captype
, actual_support
);
427 if (actual_support
& TWQC_GETCURRENT
)
429 memset(&cap
, 0, sizeof(cap
));
431 cap
.ConType
= TWON_DONTCARE16
;
433 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
434 get_condition_code(appid
, source
, &status
);
435 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
436 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
437 if (rc
== TWRC_SUCCESS
)
439 get_onevalue(cap
.hContainer
, &val
, &type
);
440 ok(type
== TWTY_FIX32
, "GETCURRENT for PHYSICALXXX is not type FIX32, is type %d\n", type
);
441 GlobalFree(cap
.hContainer
);
445 if (actual_support
& TWQC_GETDEFAULT
)
447 memset(&cap
, 0, sizeof(cap
));
449 cap
.ConType
= TWON_DONTCARE16
;
451 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
452 get_condition_code(appid
, source
, &status
);
453 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
454 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
455 if (rc
== TWRC_SUCCESS
)
457 get_onevalue(cap
.hContainer
, &val
, &type
);
458 ok(type
== TWTY_FIX32
, "GETDEFAULT for PHYSICALXXX is not type FIX32, is type %d\n", type
);
459 GlobalFree(cap
.hContainer
);
463 if (actual_support
& TWQC_GET
)
465 memset(&cap
, 0, sizeof(cap
));
467 cap
.ConType
= TWON_DONTCARE16
;
469 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
470 get_condition_code(appid
, source
, &status
);
471 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
472 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
473 if (rc
== TWRC_SUCCESS
)
475 get_onevalue(cap
.hContainer
, &val
, &type
);
476 ok(type
== TWTY_FIX32
, "GET for PHYSICALXXX is not type FIX32, is type %d\n", type
);
477 trace("GET for Physical type 0x%x returns 0x%x\n", captype
, val
);
478 GlobalFree(cap
.hContainer
);
484 static void test_supported_sizes(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_INT32 minimum_support
)
491 TW_INT32 actual_support
;
492 TW_UINT32 orig_value
= TWSS_NONE
;
493 TW_UINT32 default_value
= TWSS_NONE
;
494 TW_UINT32 new_value
= TWSS_NONE
;
497 memset(&cap
, 0, sizeof(cap
));
498 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
499 cap
.ConType
= TWON_DONTCARE16
;
501 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
502 get_condition_code(appid
, source
, &status
);
503 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
504 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
505 if (rc
!= TWRC_SUCCESS
)
507 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on ICAP_SUPPORTEDSIZES\n");
508 ok((actual_support
& minimum_support
) == minimum_support
,
509 "Error: minimum support 0x%x for ICAP_SUPPORTEDSIZES, got 0x%x\n", minimum_support
, actual_support
);
511 if (actual_support
& TWQC_GETCURRENT
)
513 memset(&cap
, 0, sizeof(cap
));
514 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
515 cap
.ConType
= TWON_DONTCARE16
;
517 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
518 get_condition_code(appid
, source
, &status
);
519 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
520 "Error [rc %d|cc %d] doing MSG_GETCURRENT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
521 if (rc
== TWRC_SUCCESS
)
523 get_onevalue(cap
.hContainer
, &val
, &type
);
524 ok(type
== TWTY_UINT16
, "GETCURRENT for ICAP_SUPPORTEDSIZES is not type UINT16, is type %d\n", type
);
525 trace("Current size is %d\n", val
);
526 GlobalFree(cap
.hContainer
);
531 if (actual_support
& TWQC_GETDEFAULT
)
533 memset(&cap
, 0, sizeof(cap
));
534 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
535 cap
.ConType
= TWON_DONTCARE16
;
537 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
538 get_condition_code(appid
, source
, &status
);
539 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
540 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
541 if (rc
== TWRC_SUCCESS
)
543 get_onevalue(cap
.hContainer
, &val
, &type
);
544 ok(type
== TWTY_UINT16
, "GETDEFAULT for PHYSICALXXX is not type TWTY_UINT16, is type %d\n", type
);
545 trace("Default size is %d\n", val
);
546 GlobalFree(cap
.hContainer
);
551 if (actual_support
& TWQC_GET
)
553 memset(&cap
, 0, sizeof(cap
));
554 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
555 cap
.ConType
= TWON_DONTCARE16
;
557 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
558 get_condition_code(appid
, source
, &status
);
559 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
560 "Error [rc %d|cc %d] doing MSG_GET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
561 check_get(&cap
, actual_support
, orig_value
, default_value
, &new_value
);
564 if (actual_support
& TWQC_SET
)
566 memset(&cap
, 0, sizeof(cap
));
567 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
568 cap
.ConType
= TWON_ONEVALUE
;
569 cap
.hContainer
= alloc_and_set_onevalue(new_value
, TWTY_UINT16
);
571 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
572 get_condition_code(appid
, source
, &status
);
573 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
574 "Error [rc %d|cc %d] doing MSG_SET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
575 GlobalFree(cap
.hContainer
);
579 if (actual_support
& TWQC_RESET
)
581 memset(&cap
, 0, sizeof(cap
));
582 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
583 cap
.ConType
= TWON_DONTCARE16
;
585 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
586 get_condition_code(appid
, source
, &status
);
587 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
588 "Error [rc %d|cc %d] doing MSG_RESET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
589 if (rc
== TWRC_SUCCESS
)
590 GlobalFree(cap
.hContainer
);
594 static void test_imagelayout(TW_IDENTITY
*appid
, TW_IDENTITY
*source
)
598 TW_IMAGELAYOUT layout
;
600 rc
= pDSM_Entry(appid
, source
, DG_IMAGE
, DAT_IMAGELAYOUT
, MSG_GET
, &layout
);
601 get_condition_code(appid
, source
, &status
);
602 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
603 "Error [rc %d|cc %d] doing MSG_GET for DG_IMAGE/DAT_IMAGELAYOUT\n", rc
, status
.ConditionCode
);
604 if (rc
!= TWRC_SUCCESS
)
606 trace("ImageLayout [Left %x.%x|Top %x.%x|Right %x.%x|Bottom %x.%x|Document %d|Page %d|Frame %d]\n",
607 layout
.Frame
.Left
.Whole
, layout
.Frame
.Left
.Frac
,
608 layout
.Frame
.Top
.Whole
, layout
.Frame
.Top
.Frac
,
609 layout
.Frame
.Right
.Whole
, layout
.Frame
.Right
.Frac
,
610 layout
.Frame
.Bottom
.Whole
, layout
.Frame
.Bottom
.Frac
,
611 layout
.DocumentNumber
, layout
.PageNumber
, layout
.FrameNumber
);
613 memset(&layout
, 0, sizeof(layout
));
614 layout
.Frame
.Left
.Whole
= 1;
615 layout
.Frame
.Right
.Whole
= 2;
616 layout
.Frame
.Top
.Whole
= 1;
617 layout
.Frame
.Bottom
.Whole
= 2;
618 rc
= pDSM_Entry(appid
, source
, DG_IMAGE
, DAT_IMAGELAYOUT
, MSG_SET
, &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_SET for DG_IMAGE/DAT_IMAGELAYOUT\n", rc
, status
.ConditionCode
);
622 if (rc
!= TWRC_SUCCESS
)
625 rc
= pDSM_Entry(appid
, source
, DG_IMAGE
, DAT_IMAGELAYOUT
, MSG_GET
, &layout
);
626 get_condition_code(appid
, source
, &status
);
627 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
628 "Error [rc %d|cc %d] doing MSG_GET for DG_IMAGE/DAT_IMAGELAYOUT\n", rc
, status
.ConditionCode
);
629 if (rc
!= TWRC_SUCCESS
)
631 trace("ImageLayout after set [Left %x.%x|Top %x.%x|Right %x.%x|Bottom %x.%x|Document %d|Page %d|Frame %d]\n",
632 layout
.Frame
.Left
.Whole
, layout
.Frame
.Left
.Frac
,
633 layout
.Frame
.Top
.Whole
, layout
.Frame
.Top
.Frac
,
634 layout
.Frame
.Right
.Whole
, layout
.Frame
.Right
.Frac
,
635 layout
.Frame
.Bottom
.Whole
, layout
.Frame
.Bottom
.Frac
,
636 layout
.DocumentNumber
, layout
.PageNumber
, layout
.FrameNumber
);
640 static void test_single_source(TW_IDENTITY
*appid
, TW_IDENTITY
*source
)
645 UINT16 capabilities
[CAP_CUSTOMBASE
];
647 memset(&cap
, 0, sizeof(cap
));
648 cap
.Cap
= CAP_SUPPORTEDCAPS
;
649 cap
.ConType
= TWON_DONTCARE16
;
651 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
652 get_condition_code(appid
, source
, &status
);
653 ok(rc
== TWRC_SUCCESS
|| status
.ConditionCode
== TWCC_SUCCESS
,
654 "Error obtaining CAP_SUPPORTEDCAPS\n");
656 memset(capabilities
, 0, sizeof(capabilities
));
657 if (rc
== TWRC_SUCCESS
&& cap
.ConType
== TWON_ARRAY
)
660 a
= GlobalLock(cap
.hContainer
);
663 if (a
->ItemType
== TWTY_UINT16
)
666 UINT16
*u
= (UINT16
*) a
->ItemList
;
667 trace("%d Capabilities:\n", a
->NumItems
);
668 for (i
= 0; i
< a
->NumItems
; i
++)
669 if (u
[i
] < ARRAY_SIZE(capabilities
))
671 capabilities
[u
[i
]] = 1;
672 trace(" %d: 0x%x\n", i
, u
[i
]);
675 GlobalUnlock(cap
.hContainer
);
679 /* All sources must support: */
680 ok(capabilities
[CAP_SUPPORTEDCAPS
], "CAP_SUPPORTEDCAPS not supported\n");
681 ok(capabilities
[CAP_XFERCOUNT
], "CAP_XFERCOUNT not supported\n");
682 if (capabilities
[CAP_XFERCOUNT
])
683 test_onevalue_cap(appid
, source
, CAP_XFERCOUNT
, TWTY_INT16
,
684 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
685 ok(capabilities
[CAP_UICONTROLLABLE
], "CAP_UICONTROLLABLE not supported\n");
686 if (capabilities
[CAP_UICONTROLLABLE
])
687 test_onevalue_cap(appid
, source
, CAP_UICONTROLLABLE
, TWTY_BOOL
, TWQC_GET
);
689 if (source
->SupportedGroups
& DG_IMAGE
)
692 Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
693 MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT on:
695 ok(capabilities
[ICAP_COMPRESSION
], "ICAP_COMPRESSION not supported\n");
696 if (capabilities
[ICAP_COMPRESSION
])
697 test_onevalue_cap(appid
, source
, ICAP_COMPRESSION
, TWTY_UINT16
,
698 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
700 ok(capabilities
[ICAP_PLANARCHUNKY
], "ICAP_PLANARCHUNKY not supported\n");
701 ok(capabilities
[ICAP_PHYSICALHEIGHT
], "ICAP_PHYSICALHEIGHT not supported\n");
702 if (capabilities
[ICAP_PHYSICALHEIGHT
])
703 test_physical(appid
, source
, ICAP_PHYSICALHEIGHT
,
704 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
705 ok(capabilities
[ICAP_PHYSICALWIDTH
], "ICAP_PHYSICALWIDTH not supported\n");
706 if (capabilities
[ICAP_PHYSICALWIDTH
])
707 test_physical(appid
, source
, ICAP_PHYSICALWIDTH
,
708 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
709 ok(capabilities
[ICAP_PIXELFLAVOR
], "ICAP_PIXELFLAVOR not supported\n");
710 if (capabilities
[ICAP_PIXELFLAVOR
])
711 test_onevalue_cap(appid
, source
, ICAP_PIXELFLAVOR
, TWTY_UINT16
,
712 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
715 Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
716 MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT, MSG_RESET and MSG_SET on:
718 ok(capabilities
[ICAP_BITDEPTH
], "ICAP_BITDEPTH not supported\n");
719 if (capabilities
[ICAP_BITDEPTH
])
720 test_onevalue_cap(appid
, source
, ICAP_BITDEPTH
, TWTY_UINT16
,
721 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
723 ok(capabilities
[ICAP_BITORDER
], "ICAP_BITORDER not supported\n");
724 ok(capabilities
[ICAP_PIXELTYPE
], "ICAP_PIXELTYPE not supported\n");
725 if (capabilities
[ICAP_PIXELTYPE
])
726 test_onevalue_cap(appid
, source
, ICAP_PIXELTYPE
, TWTY_UINT16
,
727 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
728 ok(capabilities
[ICAP_UNITS
], "ICAP_UNITS not supported\n");
729 if (capabilities
[ICAP_UNITS
])
730 test_onevalue_cap(appid
, source
, ICAP_UNITS
, TWTY_UINT16
,
731 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
732 ok(capabilities
[ICAP_XFERMECH
], "ICAP_XFERMECH not supported\n");
733 if (capabilities
[ICAP_XFERMECH
])
734 test_onevalue_cap(appid
, source
, ICAP_XFERMECH
, TWTY_UINT16
,
735 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
736 ok(capabilities
[ICAP_XRESOLUTION
], "ICAP_XRESOLUTION not supported\n");
737 if (capabilities
[ICAP_XRESOLUTION
])
738 test_resolution(appid
, source
, ICAP_XRESOLUTION
,
739 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
740 ok(capabilities
[ICAP_YRESOLUTION
], "ICAP_YRESOLUTION not supported\n");
741 if (capabilities
[ICAP_YRESOLUTION
])
742 test_resolution(appid
, source
, ICAP_YRESOLUTION
,
743 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
745 /* Optional capabilities */
746 if (capabilities
[CAP_AUTOFEED
])
747 test_onevalue_cap(appid
, source
, CAP_AUTOFEED
, TWTY_BOOL
,
748 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
749 if (capabilities
[CAP_FEEDERENABLED
])
750 test_onevalue_cap(appid
, source
, CAP_FEEDERENABLED
, TWTY_BOOL
,
751 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
752 if (capabilities
[ICAP_SUPPORTEDSIZES
])
753 test_supported_sizes(appid
, source
,
754 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
756 /* Additional tests */
757 test_imagelayout(appid
, source
);
762 static void test_sources(TW_IDENTITY
*appid
)
767 int scannercount
= 0;
769 memset(&source
, 0, sizeof(source
));
770 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETFIRST
, &source
);
771 get_condition_code(appid
, NULL
, &status
);
772 ok( (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
) ||
773 (rc
== TWRC_FAILURE
&& status
.ConditionCode
== TWCC_NODS
),
774 "Get first invalid condition code, rc %d, cc %d\n", rc
, status
.ConditionCode
);
776 while (rc
== TWRC_SUCCESS
)
779 trace("[Scanner %d|Version %d.%d(%s)|Protocol %d.%d|SupportedGroups 0x%x|Manufacturer %s|Family %s|ProductName %s]\n",
781 source
.Version
.MajorNum
, source
.Version
.MinorNum
, source
.Version
.Info
,
782 source
.ProtocolMajor
, source
.ProtocolMinor
, source
.SupportedGroups
,
783 source
.Manufacturer
, source
.ProductFamily
, source
.ProductName
);
784 memset(&source
, 0, sizeof(source
));
785 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETNEXT
, &source
);
786 get_condition_code(appid
, NULL
, &status
);
787 ok(rc
== TWRC_SUCCESS
|| rc
== TWRC_ENDOFLIST
, "Get next source failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
790 memset(&source
, 0, sizeof(source
));
791 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETDEFAULT
, &source
);
792 get_condition_code(appid
, NULL
, &status
);
793 ok( (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
) ||
794 (rc
== TWRC_FAILURE
&& status
.ConditionCode
== TWCC_NODS
),
795 "Get default invalid condition code, rc %d, cc %d\n", rc
, status
.ConditionCode
);
797 /* A DS might display a Popup during MSG_OPENDS, when the scanner is not connected */
798 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
&& winetest_interactive
)
800 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &source
);
801 get_condition_code(appid
, NULL
, &status
);
803 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
805 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &source
);
806 get_condition_code(appid
, NULL
, &status
);
807 ok(rc
== TWRC_SUCCESS
, "Close DS Failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
811 if (winetest_interactive
)
813 trace("Interactive, so trying userselect\n");
814 memset(&source
, 0, sizeof(source
));
815 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_USERSELECT
, &source
);
816 get_condition_code(appid
, NULL
, &status
);
817 ok(rc
== TWRC_SUCCESS
|| rc
== TWRC_CANCEL
, "Userselect failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
819 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
821 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &source
);
822 get_condition_code(appid
, NULL
, &status
);
823 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
825 test_single_source(appid
, &source
);
826 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &source
);
827 get_condition_code(appid
, NULL
, &status
);
828 ok(rc
== TWRC_SUCCESS
, "Close DS Failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
842 if (!dsm_RegisterWindowClasses())
844 skip("Could not register the test class, skipping tests\n");
848 htwain
= LoadLibraryA("twain_32.dll");
851 win_skip("twain_32.dll not available, skipping tests\n");
854 pDSM_Entry
= (void*)GetProcAddress(htwain
, "DSM_Entry");
855 ok(pDSM_Entry
!= NULL
, "Unable to GetProcAddress DSM_Entry\n");
858 win_skip("DSM_Entry not available, skipping tests\n");
862 memset(&appid
, 0, sizeof(appid
));
863 appid
.Version
.Language
= TWLG_ENGLISH_USA
;
864 appid
.Version
.Country
= TWCY_USA
;
865 appid
.ProtocolMajor
= TWON_PROTOCOLMAJOR
;
866 appid
.ProtocolMinor
= TWON_PROTOCOLMINOR
;
867 appid
.SupportedGroups
= DG_CONTROL
| DG_IMAGE
;
869 hwnd
= CreateWindowA("TWAIN_dsm_class", "Twain Test", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
870 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandleA(NULL
), NULL
);
872 rc
= pDSM_Entry(&appid
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_OPENDSM
, (TW_MEMREF
) &hwnd
);
873 ok(rc
== TWRC_SUCCESS
, "MSG_OPENDSM returned %d\n", rc
);
875 test_sources(&appid
);
877 rc
= pDSM_Entry(&appid
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_CLOSEDSM
, (TW_MEMREF
) &hwnd
);
878 ok(rc
== TWRC_SUCCESS
, "MSG_CLOSEDSM returned %d\n", rc
);