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
);
79 static TW_HANDLE
alloc_and_set_onevalue(TW_UINT32 val
, TW_UINT16 type
)
83 hcontainer
= GlobalAlloc(0, sizeof(*onev
));
86 onev
= GlobalLock(hcontainer
);
89 onev
->ItemType
= type
;
91 GlobalUnlock(hcontainer
);
95 GlobalFree(hcontainer
);
102 static void check_get(TW_CAPABILITY
*pCapability
, TW_INT32 actual_support
,
103 TW_UINT32 orig_value
, TW_UINT32 default_value
, TW_UINT32
*suggested_set_value
)
106 if (suggested_set_value
)
107 *suggested_set_value
= orig_value
+ 1;
108 p
= GlobalLock(pCapability
->hContainer
);
111 if (pCapability
->ConType
== TWON_ONEVALUE
)
113 TW_ONEVALUE
*onev
= p
;
114 ok(onev
->Item
== orig_value
|| !(actual_support
& TWQC_GETCURRENT
), "MSG_GET of 0x%x returned 0x%x, expecting 0x%x\n",
115 pCapability
->Cap
, onev
->Item
, orig_value
);
116 trace("MSG_GET of 0x%x returned val 0x%x, type %d\n", pCapability
->Cap
, onev
->Item
, onev
->ItemType
);
117 if (suggested_set_value
)
118 *suggested_set_value
= onev
->Item
;
120 else if (pCapability
->ConType
== TWON_ENUMERATION
)
126 TW_ENUMERATION
*enumv
= p
;
127 p8
= enumv
->ItemList
;
128 p16
= (TW_UINT16
*) p8
;
129 p32
= (TW_UINT32
*) p8
;
130 trace("MSG_GET of 0x%x returned %d items:\n", pCapability
->Cap
, enumv
->NumItems
);
131 for (i
= 0; i
< enumv
->NumItems
; i
++)
133 if (enumv
->ItemType
== TWTY_UINT8
|| enumv
->ItemType
== TWTY_INT8
)
134 trace(" %d: 0x%x\n", i
, p8
[i
]);
135 if (enumv
->ItemType
== TWTY_UINT16
|| enumv
->ItemType
== TWTY_INT16
)
136 trace(" %d: 0x%x\n", i
, p16
[i
]);
137 if (enumv
->ItemType
== TWTY_UINT32
|| enumv
->ItemType
== TWTY_INT32
)
138 trace(" %d: 0x%x\n", i
, p32
[i
]);
140 if (enumv
->ItemType
== TWTY_UINT16
|| enumv
->ItemType
== TWTY_INT16
)
142 ok(p16
[enumv
->CurrentIndex
] == orig_value
,
143 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETCURRENT (0x%x) do not match.\n",
144 pCapability
->Cap
, p16
[enumv
->CurrentIndex
], orig_value
);
145 ok(p16
[enumv
->DefaultIndex
] == default_value
,
146 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETDEFAULT (0x%x) do not match.\n",
147 pCapability
->Cap
, p16
[enumv
->DefaultIndex
], default_value
);
148 if (suggested_set_value
)
149 *suggested_set_value
= p16
[(enumv
->CurrentIndex
+ 1) % enumv
->NumItems
];
151 if (enumv
->ItemType
== TWTY_UINT32
|| enumv
->ItemType
== TWTY_INT32
)
153 ok(p32
[enumv
->CurrentIndex
] == orig_value
,
154 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETCURRENT (0x%x) do not match.\n",
155 pCapability
->Cap
, p32
[enumv
->CurrentIndex
], orig_value
);
156 ok(p32
[enumv
->DefaultIndex
] == default_value
,
157 "Type 0x%x, values from MSG_GET (0x%x) and MSG_GETDEFAULT (0x%x) do not match.\n",
158 pCapability
->Cap
, p32
[enumv
->DefaultIndex
], default_value
);
159 if (suggested_set_value
)
160 *suggested_set_value
= p32
[(enumv
->CurrentIndex
+ 1) % enumv
->NumItems
];
164 trace("MSG_GET on type 0x%x returned type 0x%x, which we didn't check.\n", pCapability
->Cap
, pCapability
->ConType
);
165 GlobalUnlock(pCapability
->hContainer
);
169 static void test_onevalue_cap(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_UINT16 type
, TW_INT32 minimum_support
)
175 TW_UINT32 orig_value
= 0;
177 TW_UINT32 default_value
= 0;
178 TW_INT32 actual_support
;
180 memset(&cap
, 0, sizeof(cap
));
182 cap
.ConType
= TWON_DONTCARE16
;
184 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
185 get_condition_code(appid
, source
, &status
);
186 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
187 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
188 if (rc
!= TWRC_SUCCESS
)
190 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
191 ok((actual_support
& minimum_support
) == minimum_support
,
192 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
193 captype
, actual_support
);
196 if (actual_support
& TWQC_GETCURRENT
)
198 memset(&cap
, 0, sizeof(cap
));
200 cap
.ConType
= TWON_DONTCARE16
;
202 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
203 get_condition_code(appid
, source
, &status
);
204 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
205 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
206 if (rc
== TWRC_SUCCESS
)
208 ok(get_onevalue(cap
.hContainer
, &orig_value
, &rtype
), "Returned cap.hContainer invalid for GETCURRENT on type 0x%x\n", captype
);
209 ok(rtype
== type
, "Returned GETCURRENT type 0x%x for cap 0x%x is not expected 0x%x\n", rtype
, captype
, type
);
210 GlobalFree(cap
.hContainer
);
214 if (actual_support
& TWQC_GETDEFAULT
)
216 memset(&cap
, 0, sizeof(cap
));
218 cap
.ConType
= TWON_DONTCARE16
;
220 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
221 get_condition_code(appid
, source
, &status
);
222 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
223 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
224 if (rc
== TWRC_SUCCESS
)
226 ok(get_onevalue(cap
.hContainer
, &default_value
, &rtype
), "Returned cap.hContainer invalid for GETDEFAULT on type 0x%x\n", captype
);
227 ok(rtype
== type
, "Returned GETDEFAULT type 0x%x for cap 0x%x is not expected 0x%x\n", rtype
, captype
, type
);
228 GlobalFree(cap
.hContainer
);
232 new_value
= orig_value
;
233 if (actual_support
& TWQC_GET
)
235 memset(&cap
, 0, sizeof(cap
));
237 cap
.ConType
= TWON_DONTCARE16
;
239 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
240 get_condition_code(appid
, source
, &status
);
241 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
242 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
243 check_get(&cap
, actual_support
, orig_value
, default_value
, &new_value
);
244 if (rc
== TWRC_SUCCESS
)
245 GlobalFree(cap
.hContainer
);
248 if (actual_support
& TWQC_SET
)
250 memset(&cap
, 0, sizeof(cap
));
252 cap
.ConType
= TWON_ONEVALUE
;
253 cap
.hContainer
= alloc_and_set_onevalue(new_value
, type
);
255 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
256 get_condition_code(appid
, source
, &status
);
257 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
258 "Error [rc %d|cc %d] doing MSG_SET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
259 GlobalFree(cap
.hContainer
);
262 if (actual_support
& TWQC_RESET
)
264 memset(&cap
, 0, sizeof(cap
));
266 cap
.ConType
= TWON_DONTCARE16
;
268 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
269 get_condition_code(appid
, source
, &status
);
270 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
271 "Error [rc %d|cc %d] doing MSG_RESET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
272 if (rc
== TWRC_SUCCESS
)
273 GlobalFree(cap
.hContainer
);
277 static void test_resolution(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_INT32 minimum_support
)
284 TW_INT32 actual_support
;
285 TW_FIX32 orig_value
= { 0, 0 };
286 TW_UINT32 new_value
= 0;
287 TW_FIX32 default_value
= { 0, 0 };
289 memset(&cap
, 0, sizeof(cap
));
291 cap
.ConType
= TWON_DONTCARE16
;
293 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
294 get_condition_code(appid
, source
, &status
);
295 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
296 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
297 if (rc
!= TWRC_SUCCESS
)
299 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
300 ok((actual_support
& minimum_support
) == minimum_support
,
301 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
302 captype
, actual_support
);
305 if (actual_support
& TWQC_GETCURRENT
)
307 memset(&cap
, 0, sizeof(cap
));
309 cap
.ConType
= TWON_DONTCARE16
;
311 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
312 get_condition_code(appid
, source
, &status
);
313 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
314 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
315 if (rc
== TWRC_SUCCESS
)
317 get_onevalue(cap
.hContainer
, &val
, &type
);
318 ok(type
== TWTY_FIX32
, "GETCURRENT for RESOLUTION is not type FIX32, is type %d\n", type
);
319 memcpy(&orig_value
, &val
, sizeof(orig_value
));
320 GlobalFree(cap
.hContainer
);
324 if (actual_support
& TWQC_GETDEFAULT
)
326 memset(&cap
, 0, sizeof(cap
));
328 cap
.ConType
= TWON_DONTCARE16
;
330 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
331 get_condition_code(appid
, source
, &status
);
332 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
333 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
334 if (rc
== TWRC_SUCCESS
)
336 get_onevalue(cap
.hContainer
, &val
, &type
);
337 ok(type
== TWTY_FIX32
, "GETDEFAULT for RESOLUTION is not type FIX32, is type %d\n", type
);
338 memcpy(&default_value
, &val
, sizeof(default_value
));
339 GlobalFree(cap
.hContainer
);
343 if (actual_support
& TWQC_GET
)
345 memset(&cap
, 0, sizeof(cap
));
347 cap
.ConType
= TWON_DONTCARE16
;
349 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
350 get_condition_code(appid
, source
, &status
);
351 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
352 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
353 if (rc
== TWRC_SUCCESS
)
356 ok(cap
.ConType
== TWON_RANGE
, "MSG_GET for ICAP_[XY]RESOLUTION did not return TWON_RANGE, but %d\n", cap
.ConType
);
357 range
= GlobalLock(cap
.hContainer
);
358 trace("MSG_GET of 0x%x returned [ItemType %d|MinValue %d|MaxValue %d|StepSize %d|DefaultValue %d|CurrentValue %d]:\n",
359 cap
.Cap
, range
->ItemType
, range
->MinValue
, range
->MaxValue
, range
->StepSize
,
360 range
->DefaultValue
, range
->CurrentValue
);
361 for (new_value
= range
->MinValue
; new_value
< range
->MaxValue
; new_value
+= range
->StepSize
)
362 if (new_value
!= range
->CurrentValue
)
364 GlobalUnlock(cap
.hContainer
);
365 GlobalFree(cap
.hContainer
);
369 if (actual_support
& TWQC_SET
)
371 memset(&cap
, 0, sizeof(cap
));
373 cap
.ConType
= TWON_ONEVALUE
;
374 cap
.hContainer
= alloc_and_set_onevalue(new_value
, TWTY_FIX32
);
376 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
377 get_condition_code(appid
, source
, &status
);
378 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
379 "Error [rc %d|cc %d] doing MSG_SET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
380 GlobalFree(cap
.hContainer
);
384 if (actual_support
& TWQC_RESET
)
386 memset(&cap
, 0, sizeof(cap
));
388 cap
.ConType
= TWON_DONTCARE16
;
390 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
391 get_condition_code(appid
, source
, &status
);
392 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
393 "Error [rc %d|cc %d] doing MSG_RESET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
394 if (rc
== TWRC_SUCCESS
)
395 GlobalFree(cap
.hContainer
);
399 static void test_physical(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_UINT16 captype
, TW_INT32 minimum_support
)
406 TW_INT32 actual_support
;
408 memset(&cap
, 0, sizeof(cap
));
410 cap
.ConType
= TWON_DONTCARE16
;
412 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
413 get_condition_code(appid
, source
, &status
);
414 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
415 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
416 if (rc
!= TWRC_SUCCESS
)
418 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on type 0x%x\n", captype
);
419 ok((actual_support
& minimum_support
) == minimum_support
,
420 "Error: minimum support 0x%x for type 0x%x, got 0x%x\n", minimum_support
,
421 captype
, actual_support
);
424 if (actual_support
& TWQC_GETCURRENT
)
426 memset(&cap
, 0, sizeof(cap
));
428 cap
.ConType
= TWON_DONTCARE16
;
430 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
431 get_condition_code(appid
, source
, &status
);
432 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
433 "Error [rc %d|cc %d] doing MSG_GETCURRENT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
434 if (rc
== TWRC_SUCCESS
)
436 get_onevalue(cap
.hContainer
, &val
, &type
);
437 ok(type
== TWTY_FIX32
, "GETCURRENT for PHYSICALXXX is not type FIX32, is type %d\n", type
);
438 GlobalFree(cap
.hContainer
);
442 if (actual_support
& TWQC_GETDEFAULT
)
444 memset(&cap
, 0, sizeof(cap
));
446 cap
.ConType
= TWON_DONTCARE16
;
448 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
449 get_condition_code(appid
, source
, &status
);
450 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
451 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
452 if (rc
== TWRC_SUCCESS
)
454 get_onevalue(cap
.hContainer
, &val
, &type
);
455 ok(type
== TWTY_FIX32
, "GETDEFAULT for PHYSICALXXX is not type FIX32, is type %d\n", type
);
456 GlobalFree(cap
.hContainer
);
460 if (actual_support
& TWQC_GET
)
462 memset(&cap
, 0, sizeof(cap
));
464 cap
.ConType
= TWON_DONTCARE16
;
466 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
467 get_condition_code(appid
, source
, &status
);
468 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
469 "Error [rc %d|cc %d] doing MSG_GET for type 0x%x\n", rc
, status
.ConditionCode
, captype
);
470 if (rc
== TWRC_SUCCESS
)
472 get_onevalue(cap
.hContainer
, &val
, &type
);
473 ok(type
== TWTY_FIX32
, "GET for PHYSICALXXX is not type FIX32, is type %d\n", type
);
474 trace("GET for Physical type 0x%x returns 0x%x\n", captype
, val
);
475 GlobalFree(cap
.hContainer
);
481 static void test_supported_sizes(TW_IDENTITY
*appid
, TW_IDENTITY
*source
, TW_INT32 minimum_support
)
488 TW_INT32 actual_support
;
489 TW_UINT32 orig_value
= TWSS_NONE
;
490 TW_UINT32 default_value
= TWSS_NONE
;
491 TW_UINT32 new_value
= TWSS_NONE
;
494 memset(&cap
, 0, sizeof(cap
));
495 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
496 cap
.ConType
= TWON_DONTCARE16
;
498 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_QUERYSUPPORT
, &cap
);
499 get_condition_code(appid
, source
, &status
);
500 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
501 "Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
502 if (rc
!= TWRC_SUCCESS
)
504 ok(get_onevalue(cap
.hContainer
, (TW_UINT32
*) &actual_support
, NULL
), "Returned cap.hContainer invalid for QuerySupport on ICAP_SUPPORTEDSIZES\n");
505 ok((actual_support
& minimum_support
) == minimum_support
,
506 "Error: minimum support 0x%x for ICAP_SUPPORTEDSIZES, got 0x%x\n", minimum_support
, actual_support
);
508 if (actual_support
& TWQC_GETCURRENT
)
510 memset(&cap
, 0, sizeof(cap
));
511 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
512 cap
.ConType
= TWON_DONTCARE16
;
514 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETCURRENT
, &cap
);
515 get_condition_code(appid
, source
, &status
);
516 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
517 "Error [rc %d|cc %d] doing MSG_GETCURRENT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
518 if (rc
== TWRC_SUCCESS
)
520 get_onevalue(cap
.hContainer
, &val
, &type
);
521 ok(type
== TWTY_UINT16
, "GETCURRENT for ICAP_SUPPORTEDSIZES is not type UINT16, is type %d\n", type
);
522 trace("Current size is %d\n", val
);
523 GlobalFree(cap
.hContainer
);
528 if (actual_support
& TWQC_GETDEFAULT
)
530 memset(&cap
, 0, sizeof(cap
));
531 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
532 cap
.ConType
= TWON_DONTCARE16
;
534 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GETDEFAULT
, &cap
);
535 get_condition_code(appid
, source
, &status
);
536 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
537 "Error [rc %d|cc %d] doing MSG_GETDEFAULT for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
538 if (rc
== TWRC_SUCCESS
)
540 get_onevalue(cap
.hContainer
, &val
, &type
);
541 ok(type
== TWTY_UINT16
, "GETDEFAULT for PHYSICALXXX is not type TWTY_UINT16, is type %d\n", type
);
542 trace("Default size is %d\n", val
);
543 GlobalFree(cap
.hContainer
);
548 if (actual_support
& TWQC_GET
)
550 memset(&cap
, 0, sizeof(cap
));
551 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
552 cap
.ConType
= TWON_DONTCARE16
;
554 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
555 get_condition_code(appid
, source
, &status
);
556 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
557 "Error [rc %d|cc %d] doing MSG_GET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
558 check_get(&cap
, actual_support
, orig_value
, default_value
, &new_value
);
561 if (actual_support
& TWQC_SET
)
563 memset(&cap
, 0, sizeof(cap
));
564 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
565 cap
.ConType
= TWON_ONEVALUE
;
566 cap
.hContainer
= alloc_and_set_onevalue(new_value
, TWTY_UINT16
);
568 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &cap
);
569 get_condition_code(appid
, source
, &status
);
570 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
571 "Error [rc %d|cc %d] doing MSG_SET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
572 GlobalFree(cap
.hContainer
);
576 if (actual_support
& TWQC_RESET
)
578 memset(&cap
, 0, sizeof(cap
));
579 cap
.Cap
= ICAP_SUPPORTEDSIZES
;
580 cap
.ConType
= TWON_DONTCARE16
;
582 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_RESET
, &cap
);
583 get_condition_code(appid
, source
, &status
);
584 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
585 "Error [rc %d|cc %d] doing MSG_RESET for ICAP_SUPPORTEDSIZES\n", rc
, status
.ConditionCode
);
586 if (rc
== TWRC_SUCCESS
)
587 GlobalFree(cap
.hContainer
);
591 static void test_imagelayout(TW_IDENTITY
*appid
, TW_IDENTITY
*source
)
595 TW_IMAGELAYOUT layout
;
597 rc
= pDSM_Entry(appid
, source
, DG_IMAGE
, DAT_IMAGELAYOUT
, MSG_GET
, &layout
);
598 get_condition_code(appid
, source
, &status
);
599 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
600 "Error [rc %d|cc %d] doing MSG_GET for DG_IMAGE/DAT_IMAGELAYOUT\n", rc
, status
.ConditionCode
);
601 if (rc
!= TWRC_SUCCESS
)
603 trace("ImageLayout [Left %x.%x|Top %x.%x|Right %x.%x|Bottom %x.%x|Document %d|Page %d|Frame %d]\n",
604 layout
.Frame
.Left
.Whole
, layout
.Frame
.Left
.Frac
,
605 layout
.Frame
.Top
.Whole
, layout
.Frame
.Top
.Frac
,
606 layout
.Frame
.Right
.Whole
, layout
.Frame
.Right
.Frac
,
607 layout
.Frame
.Bottom
.Whole
, layout
.Frame
.Bottom
.Frac
,
608 layout
.DocumentNumber
, layout
.PageNumber
, layout
.FrameNumber
);
610 memset(&layout
, 0, sizeof(layout
));
611 layout
.Frame
.Left
.Whole
= 1;
612 layout
.Frame
.Right
.Whole
= 2;
613 layout
.Frame
.Top
.Whole
= 1;
614 layout
.Frame
.Bottom
.Whole
= 2;
615 rc
= pDSM_Entry(appid
, source
, DG_IMAGE
, DAT_IMAGELAYOUT
, MSG_SET
, &layout
);
616 get_condition_code(appid
, source
, &status
);
617 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
618 "Error [rc %d|cc %d] doing MSG_SET for DG_IMAGE/DAT_IMAGELAYOUT\n", rc
, status
.ConditionCode
);
619 if (rc
!= TWRC_SUCCESS
)
622 rc
= pDSM_Entry(appid
, source
, DG_IMAGE
, DAT_IMAGELAYOUT
, MSG_GET
, &layout
);
623 get_condition_code(appid
, source
, &status
);
624 ok(rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
,
625 "Error [rc %d|cc %d] doing MSG_GET for DG_IMAGE/DAT_IMAGELAYOUT\n", rc
, status
.ConditionCode
);
626 if (rc
!= TWRC_SUCCESS
)
628 trace("ImageLayout after set [Left %x.%x|Top %x.%x|Right %x.%x|Bottom %x.%x|Document %d|Page %d|Frame %d]\n",
629 layout
.Frame
.Left
.Whole
, layout
.Frame
.Left
.Frac
,
630 layout
.Frame
.Top
.Whole
, layout
.Frame
.Top
.Frac
,
631 layout
.Frame
.Right
.Whole
, layout
.Frame
.Right
.Frac
,
632 layout
.Frame
.Bottom
.Whole
, layout
.Frame
.Bottom
.Frac
,
633 layout
.DocumentNumber
, layout
.PageNumber
, layout
.FrameNumber
);
637 static void test_single_source(TW_IDENTITY
*appid
, TW_IDENTITY
*source
)
642 UINT16 capabilities
[CAP_CUSTOMBASE
];
644 memset(&cap
, 0, sizeof(cap
));
645 cap
.Cap
= CAP_SUPPORTEDCAPS
;
646 cap
.ConType
= TWON_DONTCARE16
;
648 rc
= pDSM_Entry(appid
, source
, DG_CONTROL
, DAT_CAPABILITY
, MSG_GET
, &cap
);
649 get_condition_code(appid
, source
, &status
);
650 ok(rc
== TWRC_SUCCESS
|| status
.ConditionCode
== TWCC_SUCCESS
,
651 "Error obtaining CAP_SUPPORTEDCAPS\n");
653 memset(capabilities
, 0, sizeof(capabilities
));
654 if (rc
== TWRC_SUCCESS
&& cap
.ConType
== TWON_ARRAY
)
657 a
= GlobalLock(cap
.hContainer
);
660 if (a
->ItemType
== TWTY_UINT16
)
663 UINT16
*u
= (UINT16
*) a
->ItemList
;
664 trace("%d Capabilities:\n", a
->NumItems
);
665 for (i
= 0; i
< a
->NumItems
; i
++)
666 if (u
[i
] < sizeof(capabilities
) / sizeof(capabilities
[0]))
668 capabilities
[u
[i
]] = 1;
669 trace(" %d: 0x%x\n", i
, u
[i
]);
672 GlobalUnlock(cap
.hContainer
);
676 /* All sources must support: */
677 ok(capabilities
[CAP_SUPPORTEDCAPS
], "CAP_SUPPORTEDCAPS not supported\n");
678 ok(capabilities
[CAP_XFERCOUNT
], "CAP_XFERCOUNT not supported\n");
679 if (capabilities
[CAP_XFERCOUNT
])
680 test_onevalue_cap(appid
, source
, CAP_XFERCOUNT
, TWTY_INT16
,
681 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
682 ok(capabilities
[CAP_UICONTROLLABLE
], "CAP_UICONTROLLABLE not supported\n");
683 if (capabilities
[CAP_UICONTROLLABLE
])
684 test_onevalue_cap(appid
, source
, CAP_UICONTROLLABLE
, TWTY_BOOL
, TWQC_GET
);
686 if (source
->SupportedGroups
& DG_IMAGE
)
689 Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
690 MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT on:
692 ok(capabilities
[ICAP_COMPRESSION
], "ICAP_COMPRESSION not supported\n");
693 if (capabilities
[ICAP_COMPRESSION
])
694 test_onevalue_cap(appid
, source
, ICAP_COMPRESSION
, TWTY_UINT16
,
695 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
697 ok(capabilities
[ICAP_PLANARCHUNKY
], "ICAP_PLANARCHUNKY not supported\n");
698 ok(capabilities
[ICAP_PHYSICALHEIGHT
], "ICAP_PHYSICALHEIGHT not supported\n");
699 if (capabilities
[ICAP_PHYSICALHEIGHT
])
700 test_physical(appid
, source
, ICAP_PHYSICALHEIGHT
,
701 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
702 ok(capabilities
[ICAP_PHYSICALWIDTH
], "ICAP_PHYSICALWIDTH not supported\n");
703 if (capabilities
[ICAP_PHYSICALWIDTH
])
704 test_physical(appid
, source
, ICAP_PHYSICALWIDTH
,
705 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
706 ok(capabilities
[ICAP_PIXELFLAVOR
], "ICAP_PIXELFLAVOR not supported\n");
707 if (capabilities
[ICAP_PIXELFLAVOR
])
708 test_onevalue_cap(appid
, source
, ICAP_PIXELFLAVOR
, TWTY_UINT16
,
709 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
712 Sources that supply image information must support DG_CONTROL / DAT_CAPABILITY /
713 MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT, MSG_RESET and MSG_SET on:
715 ok(capabilities
[ICAP_BITDEPTH
], "ICAP_BITDEPTH not supported\n");
716 if (capabilities
[ICAP_BITDEPTH
])
717 test_onevalue_cap(appid
, source
, ICAP_BITDEPTH
, TWTY_UINT16
,
718 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
720 ok(capabilities
[ICAP_BITORDER
], "ICAP_BITORDER not supported\n");
721 ok(capabilities
[ICAP_PIXELTYPE
], "ICAP_PIXELTYPE not supported\n");
722 if (capabilities
[ICAP_PIXELTYPE
])
723 test_onevalue_cap(appid
, source
, ICAP_PIXELTYPE
, TWTY_UINT16
,
724 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
725 ok(capabilities
[ICAP_UNITS
], "ICAP_UNITS not supported\n");
726 if (capabilities
[ICAP_UNITS
])
727 test_onevalue_cap(appid
, source
, ICAP_UNITS
, TWTY_UINT16
,
728 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
729 ok(capabilities
[ICAP_XFERMECH
], "ICAP_XFERMECH not supported\n");
730 if (capabilities
[ICAP_XFERMECH
])
731 test_onevalue_cap(appid
, source
, ICAP_XFERMECH
, TWTY_UINT16
,
732 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
733 ok(capabilities
[ICAP_XRESOLUTION
], "ICAP_XRESOLUTION not supported\n");
734 if (capabilities
[ICAP_XRESOLUTION
])
735 test_resolution(appid
, source
, ICAP_XRESOLUTION
,
736 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
737 ok(capabilities
[ICAP_YRESOLUTION
], "ICAP_YRESOLUTION not supported\n");
738 if (capabilities
[ICAP_YRESOLUTION
])
739 test_resolution(appid
, source
, ICAP_YRESOLUTION
,
740 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
742 /* Optional capabilities */
743 if (capabilities
[CAP_AUTOFEED
])
744 test_onevalue_cap(appid
, source
, CAP_AUTOFEED
, TWTY_BOOL
,
745 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
746 if (capabilities
[CAP_FEEDERENABLED
])
747 test_onevalue_cap(appid
, source
, CAP_FEEDERENABLED
, TWTY_BOOL
,
748 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
749 if (capabilities
[ICAP_SUPPORTEDSIZES
])
750 test_supported_sizes(appid
, source
,
751 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
753 /* Additional tests */
754 test_imagelayout(appid
, source
);
759 static void test_sources(TW_IDENTITY
*appid
)
764 int scannercount
= 0;
766 memset(&source
, 0, sizeof(source
));
767 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETFIRST
, &source
);
768 get_condition_code(appid
, NULL
, &status
);
769 ok( (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
) ||
770 (rc
== TWRC_FAILURE
&& status
.ConditionCode
== TWCC_NODS
),
771 "Get first invalid condition code, rc %d, cc %d\n", rc
, status
.ConditionCode
);
773 while (rc
== TWRC_SUCCESS
)
776 trace("[Scanner %d|Version %d.%d(%s)|Protocol %d.%d|SupportedGroups 0x%x|Manufacturer %s|Family %s|ProductName %s]\n",
778 source
.Version
.MajorNum
, source
.Version
.MinorNum
, source
.Version
.Info
,
779 source
.ProtocolMajor
, source
.ProtocolMinor
, source
.SupportedGroups
,
780 source
.Manufacturer
, source
.ProductFamily
, source
.ProductName
);
781 memset(&source
, 0, sizeof(source
));
782 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETNEXT
, &source
);
783 get_condition_code(appid
, NULL
, &status
);
784 ok(rc
== TWRC_SUCCESS
|| rc
== TWRC_ENDOFLIST
, "Get next source failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
787 memset(&source
, 0, sizeof(source
));
788 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETDEFAULT
, &source
);
789 get_condition_code(appid
, NULL
, &status
);
790 ok( (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
) ||
791 (rc
== TWRC_FAILURE
&& status
.ConditionCode
== TWCC_NODS
),
792 "Get default invalid condition code, rc %d, cc %d\n", rc
, status
.ConditionCode
);
794 /* A DS might display a Popup during MSG_OPENDS, when the scanner is not connected */
795 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
&& winetest_interactive
)
797 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &source
);
798 get_condition_code(appid
, NULL
, &status
);
800 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
802 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &source
);
803 get_condition_code(appid
, NULL
, &status
);
804 ok(rc
== TWRC_SUCCESS
, "Close DS Failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
808 if (winetest_interactive
)
810 trace("Interactive, so trying userselect\n");
811 memset(&source
, 0, sizeof(source
));
812 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_USERSELECT
, &source
);
813 get_condition_code(appid
, NULL
, &status
);
814 ok(rc
== TWRC_SUCCESS
|| rc
== TWRC_CANCEL
, "Userselect failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
816 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
818 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &source
);
819 get_condition_code(appid
, NULL
, &status
);
820 if (rc
== TWRC_SUCCESS
&& status
.ConditionCode
== TWCC_SUCCESS
)
822 test_single_source(appid
, &source
);
823 rc
= pDSM_Entry(appid
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &source
);
824 get_condition_code(appid
, NULL
, &status
);
825 ok(rc
== TWRC_SUCCESS
, "Close DS Failed, rc %d, cc %d\n", rc
, status
.ConditionCode
);
839 if (!dsm_RegisterWindowClasses())
841 skip("Could not register the test class, skipping tests\n");
845 htwain
= LoadLibraryA("twain_32.dll");
848 win_skip("twain_32.dll not available, skipping tests\n");
851 pDSM_Entry
= (void*)GetProcAddress(htwain
, "DSM_Entry");
852 ok(pDSM_Entry
!= NULL
, "Unable to GetProcAddress DSM_Entry\n");
855 win_skip("DSM_Entry not available, skipping tests\n");
859 memset(&appid
, 0, sizeof(appid
));
860 appid
.Version
.Language
= TWLG_ENGLISH_USA
;
861 appid
.Version
.Country
= TWCY_USA
;
862 appid
.ProtocolMajor
= TWON_PROTOCOLMAJOR
;
863 appid
.ProtocolMinor
= TWON_PROTOCOLMINOR
;
864 appid
.SupportedGroups
= DG_CONTROL
| DG_IMAGE
;
866 hwnd
= CreateWindowA("TWAIN_dsm_class", "Twain Test", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
867 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandleA(NULL
), NULL
);
869 rc
= pDSM_Entry(&appid
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_OPENDSM
, (TW_MEMREF
) &hwnd
);
870 ok(rc
== TWRC_SUCCESS
, "MSG_OPENDSM returned %d\n", rc
);
872 test_sources(&appid
);
874 rc
= pDSM_Entry(&appid
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_CLOSEDSM
, (TW_MEMREF
) &hwnd
);
875 ok(rc
== TWRC_SUCCESS
, "MSG_CLOSEDSM returned %d\n", rc
);