1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <stdlib.h>
5 #include <string.h>
6 
7 #include <windows.h>
8 #include <wia.h>
9 #include <Sti.h>
10 
11 #include <Python.h>
12 
13 #include "properties.h"
14 #include "trace.h"
15 #include "util.h"
16 
17 static const struct wia_prop_int g_possible_connect_status[] = {
18     { WIA_DEVICE_NOT_CONNECTED, "not_connected" },
19     { WIA_DEVICE_CONNECTED, "connected" },
20     { -1, NULL, },
21 };
22 
23 static const struct wia_prop_int g_possible_access_rights[] = {
24     { WIA_ITEM_READ, "read" },
25     { WIA_ITEM_WRITE, "write" },
26     { WIA_ITEM_CAN_BE_DELETED, "can_be_deleted" },
27     { WIA_ITEM_RD, "read_can_be_deleted" },
28     { WIA_ITEM_RWD, "read_write_can_be_deleted" },
29     { -1, NULL, }
30 };
31 
32 static const struct wia_prop_int g_possible_compression[] = {
33     { WIA_COMPRESSION_NONE, "none", },
34     { 100 /* WIA_COMPRESSION_AUTO ; Visual C++ 2010 doesn't know this value */, "auto", },
35     { WIA_COMPRESSION_BI_RLE4, "bi_rle4", },
36     { WIA_COMPRESSION_BI_RLE8, "bi_rle8", },
37     { WIA_COMPRESSION_G3, "g3", },
38     { WIA_COMPRESSION_G4, "g4", },
39     { WIA_COMPRESSION_JPEG, "jpeg", },
40     { WIA_COMPRESSION_JBIG, "jbig", },
41     { WIA_COMPRESSION_JPEG2K, "jpeg2k", },
42     { WIA_COMPRESSION_PNG, "png", },
43     { -1, NULL, },
44 };
45 
46 static const struct wia_prop_int g_possible_datatype[] = {
47     { 100 /* WIA_DATA_AUTO ; Visual C++ 2010 doesn't know this value */, "auto", },
48     { WIA_DATA_COLOR, "color", },
49     { WIA_DATA_COLOR_DITHER, "color_dither", },
50     { WIA_DATA_COLOR_THRESHOLD, "color_threshold", },
51     { WIA_DATA_DITHER, "dither", },
52     { WIA_DATA_GRAYSCALE, "grayscale", },
53     { WIA_DATA_THRESHOLD, "threshold", },
54     { WIA_DATA_RAW_BGR, "raw_bgr", },
55     { WIA_DATA_RAW_CMY, "raw_cmy", },
56     { WIA_DATA_RAW_CMYK, "raw_cmyk", },
57     { WIA_DATA_RAW_RGB, "raw_rgb", },
58     { WIA_DATA_RAW_YUV, "raw_yuv", },
59     { WIA_DATA_RAW_YUVK, "raw_yuvk", },
60     { -1, NULL, },
61 };
62 
63 static const struct wia_prop_clsid g_possible_format[] = {
64     { WiaImgFmt_BMP, "bmp", },
65     { WiaImgFmt_CIFF, "ciff", },
66     { WiaImgFmt_EXIF, "exif", },
67     { WiaImgFmt_FLASHPIX, "flashpix", },
68     { WiaImgFmt_GIF, "gif", },
69     { WiaImgFmt_ICO, "ico", },
70     { WiaImgFmt_JBIG, "jbig", },
71     { WiaImgFmt_JPEG, "jpeg", },
72     { WiaImgFmt_JPEG2K, "jpeg2k", },
73     { WiaImgFmt_JPEG2KX, "jpeg2kx", },
74     { WiaImgFmt_MEMORYBMP, "memorybmp", },
75     { WiaImgFmt_PDFA, "pdfa", },
76     { WiaImgFmt_PHOTOCD, "photocd", },
77     { WiaImgFmt_PICT, "pict", },
78     { WiaImgFmt_PNG, "png", },
79     { WiaImgFmt_RAW, "raw", },
80     { WiaImgFmt_RAWRGB, "rawrgb", },
81     { WiaImgFmt_TIFF, "tiff", },
82     { NULL, NULL, },
83 };
84 
85 static const struct wia_prop_clsid g_possible_item_category[] = {
86     { WIA_CATEGORY_ROOT, "root", },
87     { WIA_CATEGORY_FLATBED, "flatbed", },
88     { WIA_CATEGORY_FEEDER, "feeder", },
89     { WIA_CATEGORY_FEEDER_FRONT, "feeder_front", },
90     { WIA_CATEGORY_FEEDER_BACK, "feeder_back", },
91     { WIA_CATEGORY_FILM, "film", },
92     { WIA_CATEGORY_FOLDER, "folder", },
93     { WIA_CATEGORY_FINISHED_FILE, "finished_file", },
94     { NULL, NULL, },
95 };
96 
97 static const struct wia_prop_int g_possible_item_flags[] = {
98     { WiaItemTypeAnalyze, "analyze", },
99     { WiaItemTypeAudio, "audio", },
100     { WiaItemTypeBurst, "burst", },
101     { WiaItemTypeDeleted, "deleted", },
102     { WiaItemTypeDocument, "document", },
103     { WiaItemTypeDevice, "device", },
104     { WiaItemTypeDisconnected, "disconnected", },
105     { WiaItemTypeFile, "file", },
106     { WiaItemTypeFolder, "folder", },
107     { WiaItemTypeFree, "free", },
108     { WiaItemTypeGenerated, "generated", },
109     { WiaItemTypeHasAttachments, "has_attachments", },
110     { WiaItemTypeHPanorama, "hpanorama", },
111     { WiaItemTypeImage, "image", },
112     { WiaItemTypeProgrammableDataSource, "programmable_data_source", },
113     { WiaItemTypeRoot, "root", },
114     { WiaItemTypeStorage, "storage", },
115     { WiaItemTypeTransfer, "transfer", },
116     // WiaItemTypeTwainCapabilityPassThrough, // Jflesch> Doesn't exist ?
117     { WiaItemTypeVideo, "video", },
118     { WiaItemTypeVPanorama, "vpanorama", },
119     { -1, NULL },
120 };
121 
122 static const struct wia_prop_int g_possible_planar[] = {
123     { WIA_PACKED_PIXEL, "pixel" },
124     { WIA_PLANAR, "planar" },
125     { -1, NULL, },
126 };
127 
128 static const struct wia_prop_int g_possible_suppress_property_page[] = {
129     { WIA_PROPPAGE_CAMERA_ITEM_GENERAL, "camera_item_general", },
130     { WIA_PROPPAGE_SCANNER_ITEM_GENERAL, "scanner_item_general", },
131     { -1, NULL, },
132 };
133 
134 static const struct wia_prop_int g_possible_tymed[] = {
135     { TYMED_CALLBACK, "callback", },
136     { TYMED_MULTIPAGE_CALLBACK, "multipage_callback", },
137     { TYMED_FILE, "file", },
138     { TYMED_MULTIPAGE_FILE, "multipage_file", },
139     { -1, NULL, },
140 };
141 
142 static const struct wia_prop_int g_possible_dev_type[] = {
143     { StiDeviceTypeDefault, "default", },
144     { StiDeviceTypeScanner, "scanner", },
145     { StiDeviceTypeDigitalCamera, "digital_camera", },
146     { StiDeviceTypeStreamingVideo, "streaming_video", },
147     { -1, NULL, },
148 };
149 
150 static const struct wia_prop_int g_possible_hw_config[] = {
151     { 1, "generic", }, // Generic WDM device
152     { 2, "scsi", }, // SCSI device
153     { 4, "usb", }, // USB device
154     { 8, "serial", }, // Serial device
155     { 16, "parallel", }, // Parallel device
156     { -1, NULL, },
157 };
158 
159 static const struct wia_prop_int g_possible_document_handling_capabilities[] = {
160     { AUTO_SOURCE, "auto_source", },
161     { ADVANCED_DUP, "dup", },
162     { DETECT_FILM_TPA, "detect_film_tpa", },
163     { DETECT_STOR, "detect_stor", },
164     { FILM_TPA, "film_tpa", },
165     { STOR, "stor", },
166     { DETECT_FEED, "detect_feed", },
167     { DETECT_FLAT, "detect_flat", },
168     { DETECT_SCAN, "detect_scan", },
169     { DUP, "dup", },
170     { FEED, "feed", },
171     { FLAT, "flat", },
172     { DETECT_DUP, "detect_dup", },
173     { DETECT_DUP_AVAIL, "detect_dup_avail", },
174     { DETECT_FEED_AVAIL, "detect_feed_avail", },
175     { -1, NULL, },
176 };
177 
178 static const struct wia_prop_int g_possible_document_handling_select[] = {
179     { FEEDER, "feeder", },
180     { FLATBED, "flatbed", },
181     { DUPLEX, "duplex", },
182     { AUTO_ADVANCE, "auto_advance", },
183     { FRONT_FIRST, "front_first", },
184     { BACK_FIRST, "back_first", },
185     { FRONT_ONLY, "front_only", },
186     { BACK_ONLY, "back_only", },
187     { NEXT_PAGE, "next_page", },
188     { PREFEED, "prefeed", },
189     { -1, NULL, },
190 };
191 
192 static const struct wia_prop_int g_possible_document_handling_status[] = {
193     { FEED_READY, "feed_ready", },
194     { FLAT_READY, "flat_ready", },
195     { DUP_READY, "dup_ready", },
196     { FLAT_COVER_UP, "flat_cover_up", },
197     { PATH_COVER_UP, "path_cover_up", },
198     { PAPER_JAM, "paper_jam", },
199     { FILM_TPA_READY, "film_tpa_ready", },
200     { STORAGE_READY, "storage_ready", },
201     { STORAGE_FULL, "storage_full", },
202     { MULTIPLE_FEED, "multiple_feed", },
203     { DEVICE_ATTENTION, "device_attention", },
204     { LAMP_ERR, "lamp_err", },
205     { -1, NULL, },
206 };
207 
208 static const struct wia_prop_int g_possible_horizontal_bed_registration[] = {
209     { LEFT_JUSTIFIED, "left_justified", },
210     { CENTERED, "centered", },
211     { RIGHT_JUSTIFIED, "right_justified", },
212     { -1, NULL, },
213 };
214 
215 static const struct wia_prop_int g_possible_orientation[] = {
216     { LANDSCAPE, "landscape", },
217     { PORTRAIT, "portrait", },
218     { ROT180, "rot180", },
219     { ROT270, "rot270", },
220     { -1, NULL },
221 };
222 
223 static const struct wia_prop_int g_possible_page_size[] = {
224     { WIA_PAGE_A4, "a4", },
225     { WIA_PAGE_CUSTOM, "custom", }, // see WIA_DPS_PAGE_HEIGHT and WIA_DPS_PAGE_WIDTH
226     { WIA_PAGE_LETTER, "letter", },
227     { WIA_PAGE_USLEGAL, "uslegal", },
228     { WIA_PAGE_USLETTER, "usletter", },
229     { WIA_PAGE_USLEDGER, "usledger", },
230     { WIA_PAGE_USSTATEMENT, "usstatement", },
231     { WIA_PAGE_BUSINESSCARD, "businesscard", },
232     { WIA_PAGE_ISO_A0, "iso_a0", },
233     { WIA_PAGE_ISO_A1, "iso_a1", },
234     { WIA_PAGE_ISO_A2, "iso_a2", },
235     { WIA_PAGE_ISO_A3, "iso_a3", },
236     { WIA_PAGE_ISO_A4, "iso_a4", },
237     { WIA_PAGE_ISO_A5, "iso_a5", },
238     { WIA_PAGE_ISO_A6, "iso_a6", },
239     { WIA_PAGE_ISO_A7, "iso_a7", },
240     { WIA_PAGE_ISO_A8, "iso_a8", },
241     { WIA_PAGE_ISO_A9, "iso_a9", },
242     { WIA_PAGE_ISO_A10, "iso_a10", },
243     { WIA_PAGE_ISO_B0, "iso_b0", },
244     { WIA_PAGE_ISO_B1, "iso_b1", },
245     { WIA_PAGE_ISO_B2, "iso_b2", },
246     { WIA_PAGE_ISO_B3, "iso_b3", },
247     { WIA_PAGE_ISO_B4, "iso_b4", },
248     { WIA_PAGE_ISO_B5, "iso_b5", },
249     { WIA_PAGE_ISO_B6, "iso_b6", },
250     { WIA_PAGE_ISO_B7, "iso_b7", },
251     { WIA_PAGE_ISO_B8, "iso_b8", },
252     { WIA_PAGE_ISO_B9, "iso_b9", },
253     { WIA_PAGE_ISO_B10, "iso_b10", },
254     { WIA_PAGE_ISO_C0, "iso_c0", },
255     { WIA_PAGE_ISO_C1, "iso_c1", },
256     { WIA_PAGE_ISO_C2, "iso_c2", },
257     { WIA_PAGE_ISO_C3, "iso_c3", },
258     { WIA_PAGE_ISO_C4, "iso_c4", },
259     { WIA_PAGE_ISO_C5, "iso_c5", },
260     { WIA_PAGE_ISO_C6, "iso_c6", },
261     { WIA_PAGE_ISO_C7, "iso_c7", },
262     { WIA_PAGE_ISO_C8, "iso_c8", },
263     { WIA_PAGE_ISO_C9, "iso_c9", },
264     { WIA_PAGE_ISO_C10, "iso_c10", },
265     { WIA_PAGE_JIS_B0, "jis_b0", },
266     { WIA_PAGE_JIS_B1, "jis_b1", },
267     { WIA_PAGE_JIS_B2, "jis_b2", },
268     { WIA_PAGE_JIS_B3, "jis_b3", },
269     { WIA_PAGE_JIS_B4, "jis_b4", },
270     { WIA_PAGE_JIS_B5, "jis_b5", },
271     { WIA_PAGE_JIS_B6, "jis_b6", },
272     { WIA_PAGE_JIS_B7, "jis_b7", },
273     { WIA_PAGE_JIS_B8, "jis_b8", },
274     { WIA_PAGE_JIS_B9, "jis_b9", },
275     { WIA_PAGE_JIS_B10, "jis_b10", },
276     { WIA_PAGE_JIS_2A, "jis_2a", },
277     { WIA_PAGE_JIS_4A, "jis_4a", },
278     { WIA_PAGE_DIN_2B, "din_2b", },
279     { WIA_PAGE_DIN_4B, "din_4b", },
280     { WIA_PAGE_AUTO, "auto", },
281     { WIA_PAGE_CUSTOM_BASE, "custom_base", },
282     { -1, NULL, },
283 };
284 
285 static const struct wia_prop_int g_possible_preview[] = {
286     { WIA_FINAL_SCAN, "final_scan", },
287     { WIA_PREVIEW_SCAN, "preview_scan", },
288     { -1, NULL, },
289 };
290 
291 static const struct wia_prop_int g_possible_sheet_feeder_registration[] = {
292     { LEFT_JUSTIFIED, "left_justified", },
293     { CENTERED, "centered", },
294     { RIGHT_JUSTIFIED, "right_justified", },
295     { -1, NULL },
296 };
297 
298 static const struct wia_prop_int g_possible_show_preview_control[] = {
299     { WIA_SHOW_PREVIEW_CONTROL, "show_preview_control", },
300     { WIA_DONT_SHOW_PREVIEW_CONTROL, "dont_show_preview_control", },
301     { -1, NULL, },
302 };
303 
304 static const struct wia_prop_int g_possible_vertical_bed_registration[] = {
305     { TOP_JUSTIFIED, "top_justified", },
306     { CENTERED, "centered", },
307     { BOTTOM_JUSTIFIED, "bottom_justified", },
308     { -1, NULL, },
309 };
310 
311 static const struct wia_prop_int g_possible_auto_deskew[] = {
312     { WIA_AUTO_DESKEW_ON, "deskew_on", },
313     { WIA_AUTO_DESKEW_OFF, "deskew_off", },
314     { -1, NULL, },
315 };
316 
317 static const struct wia_prop_int g_possible_intent[] = {
318     { WIA_INTENT_NONE, "none", },
319     { WIA_INTENT_IMAGE_TYPE_COLOR, "image_type_color", },
320     { WIA_INTENT_IMAGE_TYPE_GRAYSCALE, "image_type_grayscale", },
321     { WIA_INTENT_IMAGE_TYPE_TEXT, "image_type_text", },
322     { WIA_INTENT_IMAGE_TYPE_MASK, "image_type_mask", },
323     { WIA_INTENT_MINIMIZE_SIZE, "minimize_size", },
324     { WIA_INTENT_MAXIMIZE_QUALITY, "maximize_quality", },
325     { WIA_INTENT_SIZE_MASK, "size_mask", },
326     { WIA_INTENT_BEST_PREVIEW, "best_preview", },
327     { -1, NULL, },
328 };
329 
330 static const struct wia_prop_int g_possible_film_scan_mode[] = {
331     { WIA_FILM_COLOR_SLIDE, "color_slide", },
332     { WIA_FILM_COLOR_NEGATIVE, "color_negative", },
333     { WIA_FILM_BW_NEGATIVE, "bw_negative", },
334     { -1, NULL, },
335 };
336 
337 static const struct wia_prop_int g_possible_lamp[] = {
338     { WIA_LAMP_ON, "on", },
339     { WIA_LAMP_OFF, "off", },
340     { -1, NULL, },
341 };
342 
343 static const struct wia_prop_int g_possible_photometric_interp[] = {
344     { WIA_PHOTO_WHITE_0, "white_0", }, // WHITE is 0, and BLACK is 1
345     { WIA_PHOTO_WHITE_1, "white_1", }, // WHITE is 1, and BLACK is 0
346     { -1, NULL, },
347 };
348 
349 static const struct wia_prop_int g_possible_preview_type[] = {
350     { WIA_ADVANCED_PREVIEW, "advanced", },
351     { WIA_BASIC_PREVIEW, "basic", },
352     { -1, NULL, },
353 };
354 
355 static const struct wia_prop_int g_possible_rotation[] = {
356     { PORTRAIT, "portrait", },
357     { LANDSCAPE, "landscape", },
358     { ROT180, "rot180", },
359     { ROT270, "rot270", },
360     { -1, NULL, },
361 };
362 
363 static const struct wia_prop_int g_possible_segmentation[] = {
364     { WIA_USE_SEGMENTATION_FILTER, "true", },
365     { WIA_DONT_USE_SEGMENTATION_FILTER, "false", },
366     { -1, NULL, },
367 };
368 
369 static PyObject *get_possible_values_int(const struct wia_property*);
370 static PyObject *get_possible_values_clsid(const struct wia_property*);
371 static PyObject *get_possible_values_none(const struct wia_property*);
372 
373 static const struct wia_property _g_wia_all_properties[] =
374 {
375     {
376         WIA_DPA_CONNECT_STATUS, VT_I4, "connect_status", 0, g_possible_connect_status, get_possible_values_int,
377     },
378     {
379         WIA_DPA_DEVICE_TIME, VT_VECTOR | VT_UI2, "device_time", 0, NULL, get_possible_values_none,
380     },
381     {
382         WIA_DPA_FIRMWARE_VERSION, VT_BSTR, "firmware_version", 0, NULL, get_possible_values_none,
383     },
384     {
385         WIA_IPA_ACCESS_RIGHTS, VT_I4, "access_rights", 1, g_possible_access_rights, get_possible_values_int,
386     },
387     {
388         WIA_IPA_BITS_PER_CHANNEL, VT_I4, "bits_per_channel", 0, NULL, get_possible_values_none,
389     },
390     {
391         WIA_IPA_BUFFER_SIZE, VT_I4, "buffer_size", 0, NULL, get_possible_values_none,
392     },
393     {
394         WIA_IPA_BYTES_PER_LINE, VT_I4, "bytes_per_line", 0, NULL, get_possible_values_none,
395     },
396     {
397         WIA_IPA_CHANNELS_PER_PIXEL, VT_I4, "channels_per_pixel", 0, NULL, get_possible_values_none,
398     },
399     {
400         WIA_IPA_COLOR_PROFILE, VT_I4, "color_profile", 0, NULL, get_possible_values_none,
401     },
402     {
403         WIA_IPA_COMPRESSION, VT_I4, "compression", 1, g_possible_compression, get_possible_values_int,
404     },
405     {
406         WIA_IPA_DATATYPE, VT_I4, "datatype", 1, g_possible_datatype, get_possible_values_int,
407     },
408     {
409         WIA_IPA_DEPTH, VT_I4, "depth", 1, NULL, get_possible_values_none,
410     },
411     {
412         WIA_IPA_FILENAME_EXTENSION, VT_BSTR, "filename_extension", 0, NULL, get_possible_values_none,
413     },
414     {
415         WIA_IPA_FORMAT, VT_CLSID, "format", 1, g_possible_format, get_possible_values_clsid,
416     },
417     {
418         WIA_IPA_FULL_ITEM_NAME, VT_BSTR, "full_item_name", 0, NULL, get_possible_values_none,
419     },
420     {
421         WIA_IPA_GAMMA_CURVES, VT_I4, "gamma_curves", 0, NULL, get_possible_values_none,
422     },
423     {
424         WIA_IPA_ICM_PROFILE_NAME, VT_BSTR, "icm_profile_name", 0, NULL, get_possible_values_none,
425     },
426     {
427         WIA_IPA_ITEM_CATEGORY, VT_CLSID, "item_category", 0, g_possible_item_category, get_possible_values_clsid,
428     },
429     {
430         WIA_IPA_ITEM_FLAGS, VT_I4, "item_flags", 0, g_possible_item_flags, get_possible_values_int,
431     },
432     {
433         WIA_IPA_ITEM_NAME, VT_BSTR, "item_name", 0, NULL, get_possible_values_none,
434     },
435     {
436         WIA_IPA_ITEM_SIZE, VT_I4, "item_size", 0, NULL, get_possible_values_none,
437     },
438     {
439         WIA_IPA_ITEM_TIME, VT_UI2 | VT_VECTOR, "item_time", 1, NULL, get_possible_values_none,
440     },
441     {
442         WIA_IPA_ITEMS_STORED, VT_I4, "items_stored", 1, NULL, get_possible_values_none,
443     },
444     {
445         WIA_IPA_MIN_BUFFER_SIZE, VT_I4, "buffer_size", 0, NULL, get_possible_values_none,
446     },
447     {
448         WIA_IPA_NUMBER_OF_LINES, VT_I4, "number_of_lines", 0, NULL, get_possible_values_none,
449     },
450     {
451         WIA_IPA_PIXELS_PER_LINE, VT_I4, "pixels_per_line", 0, NULL, get_possible_values_none,
452     },
453     {
454         WIA_IPA_PLANAR, VT_I4, "planar", 1, g_possible_planar, get_possible_values_int,
455     },
456     {
457         WIA_IPA_PREFERRED_FORMAT, VT_CLSID, "preferred_format", 0, g_possible_format, get_possible_values_clsid,
458     },
459     {
460         WIA_IPA_PROP_STREAM_COMPAT_ID, VT_CLSID, "prop_stream_compat_id", 0, NULL, get_possible_values_clsid,
461     },
462     {
463         WIA_IPA_RAW_BITS_PER_CHANNEL, VT_UI1 | VT_VECTOR, "raw_bits_per_channel", 0, NULL, get_possible_values_none,
464     },
465     {
466         WIA_IPA_REGION_TYPE, VT_I4, "region_type", 0, NULL, get_possible_values_none,
467     },
468     {
469         WIA_IPA_SUPPRESS_PROPERTY_PAGE, VT_I4, "suppress_property_page", 0, g_possible_suppress_property_page,
470          get_possible_values_int,
471     },
472     {
473         WIA_IPA_TYMED, VT_I4, "tymed", 1, g_possible_tymed, get_possible_values_int,
474     },
475     {
476         WIA_IPA_UPLOAD_ITEM_SIZE, VT_I4, "upload_item_size", 1, NULL, get_possible_values_none,
477     },
478     {
479         WIA_DIP_DEV_ID, VT_BSTR, "dev_id", 0, NULL, get_possible_values_none,
480     },
481     {
482         WIA_DIP_VEND_DESC, VT_BSTR, "vend_desc", 0, NULL, get_possible_values_none,
483     },
484     {
485         WIA_DIP_DEV_DESC, VT_BSTR, "dev_desc", 0, NULL, get_possible_values_none,
486     },
487     {
488         WIA_DIP_DEV_TYPE, VT_I4, "dev_type", 0, g_possible_dev_type, get_possible_values_int,
489     },
490     {
491         WIA_DIP_PORT_NAME, VT_BSTR, "port_name", 0, NULL, get_possible_values_none,
492     },
493     {
494         WIA_DIP_DEV_NAME, VT_BSTR, "dev_name", 0, NULL, get_possible_values_none,
495     },
496     {
497         WIA_DIP_SERVER_NAME, VT_BSTR, "server_name", 0, NULL, get_possible_values_none,
498     },
499     {
500         WIA_DIP_REMOTE_DEV_ID, VT_BSTR, "remote_dev_id", 0, NULL, get_possible_values_none,
501     },
502     {
503         WIA_DIP_UI_CLSID, VT_BSTR, "ui_clsid", 0, NULL, get_possible_values_none,
504     },
505     {
506         WIA_DIP_HW_CONFIG, VT_I4, "hw_config", 0, g_possible_hw_config, get_possible_values_int,
507     },
508     {
509         WIA_DIP_BAUDRATE, VT_BSTR, "baudrate", 0, NULL, get_possible_values_none,
510     },
511     {
512         WIA_DIP_STI_GEN_CAPABILITIES, VT_I4, "sti_gen_capabilities", 0, NULL, get_possible_values_none,
513     },
514     {
515         WIA_DIP_WIA_VERSION, VT_BSTR, "wia_version", 0, NULL, get_possible_values_none,
516     },
517     {
518         WIA_DIP_DRIVER_VERSION, VT_BSTR, "driver_version", 0, NULL, get_possible_values_none,
519     },
520     {
521         WIA_DIP_PNP_ID, VT_BSTR, "pnp_id", 0, NULL, get_possible_values_none,
522     },
523     {
524         WIA_DIP_STI_DRIVER_VERSION, VT_BSTR, "sti_driver_version", 0, NULL, get_possible_values_none,
525     },
526     {
527         WIA_DPS_DEVICE_ID, VT_BSTR, "device_id", 0, NULL, get_possible_values_none,
528     },
529     {
530         WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES, VT_I4,
531         "document_handling_capabilities", 0, g_possible_document_handling_capabilities,
532         get_possible_values_int,
533     },
534     {
535         WIA_DPS_DOCUMENT_HANDLING_SELECT, VT_I4, "document_handling_select", 1, g_possible_document_handling_select,
536         get_possible_values_int,
537     },
538     {
539         WIA_DPS_DOCUMENT_HANDLING_STATUS, VT_I4, "document_handling_status", 0, g_possible_document_handling_status,
540         get_possible_values_int,
541     },
542     {
543         WIA_DPS_ENDORSER_CHARACTERS, VT_BSTR, "endorser_characters", 0, NULL, get_possible_values_none,
544     },
545     {
546         WIA_DPS_ENDORSER_STRING, VT_BSTR, "endorser_string", 1, NULL, get_possible_values_none,
547     },
548     {
549         WIA_DPS_GLOBAL_IDENTITY, VT_BSTR, "global_identity", 0, NULL, get_possible_values_none,
550     },
551     {
552         WIA_DPS_HORIZONTAL_BED_REGISTRATION, VT_I4,
553         "horizontal_bed_registration", 0, g_possible_horizontal_bed_registration,
554         get_possible_values_int,
555     },
556     {
557         WIA_DPS_HORIZONTAL_BED_SIZE, VT_I4, "horizontal_bed_size", 0, NULL, get_possible_values_none,
558     },
559     {
560         WIA_DPS_HORIZONTAL_SHEET_FEED_SIZE, VT_I4, "horizontal_sheet_feed_size", 0, NULL, get_possible_values_none,
561     },
562     {
563         WIA_DPS_MAX_SCAN_TIME, VT_I4, "max_scan_time", 0, NULL, get_possible_values_none,
564     },
565     {
566         WIA_DPS_MIN_HORIZONTAL_SHEET_FEED_SIZE, VT_I4, "min_horizontal_sheet_feed_size", 0, NULL,
567         get_possible_values_none,
568     },
569     {
570         WIA_DPS_MIN_VERTICAL_SHEET_FEED_SIZE, VT_I4, "min_vertical_sheet_feed_size", 0, NULL, get_possible_values_none,
571     },
572     {
573         WIA_DPS_OPTICAL_XRES, VT_I4, "optical_xres", 0, NULL, get_possible_values_none,
574     },
575     {
576         WIA_DPS_OPTICAL_YRES, VT_I4, "optical_yres", 0, NULL, get_possible_values_none,
577     },
578     // TODO(JFlesch): Visual C++ says WIA_DPS_ORIENTATION doesn't exist ?!
579     //{
580     //    WIA_DPS_ORIENTATION, VT_I4, "orientation", 1, g_possible_orientation, get_possible_values_int,
581     //},
582     {
583         WIA_DPS_PAD_COLOR, VT_UI1 | VT_VECTOR, "pad_color", 0, NULL, get_possible_values_none,
584     },
585     {
586         WIA_DPS_PAGE_HEIGHT, VT_I4, "page_height", 0, NULL, get_possible_values_none,
587     },
588     {
589         WIA_DPS_PAGE_SIZE, VT_I4, "page_size", 1, g_possible_page_size, get_possible_values_int,
590     },
591     {
592         WIA_DPS_PAGE_WIDTH, VT_I4, "page_width", 0, NULL, get_possible_values_none,
593     },
594     {
595         WIA_DPS_PAGES, VT_I4, "pages", 1, NULL, get_possible_values_none,
596     },
597     {
598         WIA_DPS_PLATEN_COLOR, VT_UI1 | VT_VECTOR, "platen_color", 0, NULL, get_possible_values_none,
599     },
600     {
601         WIA_DPS_PREVIEW, VT_I4, "preview", 1, g_possible_preview, get_possible_values_int,
602     },
603     {
604         WIA_DPS_SCAN_AHEAD_PAGES, VT_I4, "scan_ahead_pages", 1, NULL, get_possible_values_none,
605     },
606     {
607         WIA_DPS_SCAN_AVAILABLE_ITEM, VT_I4, "scan_available_item", 1, NULL, get_possible_values_none,
608     },
609     {
610         WIA_DPS_SERVICE_ID, VT_BSTR, "service_id", 0, NULL, get_possible_values_none,
611     },
612     {
613         WIA_DPS_SHEET_FEEDER_REGISTRATION, VT_I4,
614         "sheet_feeder_registration", 0, g_possible_sheet_feeder_registration,
615         get_possible_values_int,
616     },
617     {
618         WIA_DPS_SHOW_PREVIEW_CONTROL, VT_I4, "show_preview_control", 0, g_possible_show_preview_control,
619         get_possible_values_int,
620     },
621     {
622         WIA_DPS_USER_NAME, VT_BSTR, "user_name", 0, NULL, get_possible_values_none,
623     },
624     {
625         WIA_DPS_VERTICAL_BED_REGISTRATION, VT_I4, "vertical_bed_registration", 0, g_possible_vertical_bed_registration,
626         get_possible_values_int,
627     },
628     {
629         WIA_DPS_VERTICAL_BED_SIZE, VT_I4, "vertical_bed_size", 0, NULL, get_possible_values_none,
630     },
631     {
632         WIA_DPS_VERTICAL_SHEET_FEED_SIZE, VT_I4, "vertical_sheet_feed_size", 0, NULL, get_possible_values_none,
633     },
634     {
635         WIA_IPS_AUTO_DESKEW, VT_I4, "auto_deskew", 1, g_possible_auto_deskew, get_possible_values_int,
636     },
637     {
638         WIA_IPS_BRIGHTNESS, VT_I4, "brightness", 1, NULL, get_possible_values_none,
639     },
640     {
641         WIA_IPS_CONTRAST, VT_I4, "contrast", 1, NULL, get_possible_values_none,
642     },
643     {
644         WIA_IPS_CUR_INTENT, VT_I4, "current_intent", 1, g_possible_intent, get_possible_values_int,
645     },
646     {
647         WIA_IPS_DESKEW_X, VT_I4, "deskew_x", 1, NULL, get_possible_values_none,
648     },
649     {
650         WIA_IPS_DESKEW_Y, VT_I4, "deskew_y", 1, NULL, get_possible_values_none,
651     },
652     {
653         WIA_IPS_DOCUMENT_HANDLING_SELECT, VT_I4, "document_handling_select", 1, g_possible_document_handling_select,
654         get_possible_values_int,
655     },
656     {
657         WIA_IPS_FILM_NODE_NAME, VT_BSTR, "film_node_name", 0, NULL, get_possible_values_none,
658     },
659     {
660         WIA_IPS_FILM_SCAN_MODE, VT_I4, "file_scan_mode", 1, g_possible_film_scan_mode, get_possible_values_int,
661     },
662     {
663         WIA_IPS_INVERT, VT_I4, "invert", 0, NULL, get_possible_values_none,
664     },
665     {
666         WIA_IPA_ITEMS_STORED, VT_I4, "items_stored", 0, NULL, get_possible_values_none,
667     },
668     {
669         WIA_IPS_LAMP, VT_I4, "lamp", 1, g_possible_lamp, get_possible_values_int,
670     },
671     {
672         WIA_IPS_LAMP_AUTO_OFF, VT_UI4, "lamp_auto_off", 1, NULL, get_possible_values_none,
673     },
674     {
675         WIA_IPS_MAX_HORIZONTAL_SIZE, VT_I4, "max_horizontal_size", 0, NULL, get_possible_values_none,
676     },
677     {
678         WIA_IPS_MAX_VERTICAL_SIZE, VT_I4, "max_vertical_size", 0, NULL, get_possible_values_none,
679     },
680     {
681         WIA_IPS_MIN_HORIZONTAL_SIZE, VT_I4, "min_horizontal_size", 0, NULL, get_possible_values_none,
682     },
683     {
684         WIA_IPS_MIN_VERTICAL_SIZE, VT_I4, "min_vertical_size", 0, NULL, get_possible_values_none,
685     },
686     {
687         WIA_IPS_MIRROR, VT_I4, "mirror", 0, NULL, get_possible_values_none,
688     },
689     {
690         WIA_IPS_OPTICAL_XRES, VT_I4, "optical_xres", 0, NULL, get_possible_values_none,
691     },
692     {
693         WIA_IPS_OPTICAL_YRES, VT_I4, "optical_yres", 0, NULL, get_possible_values_none,
694     },
695     {
696         WIA_IPS_ORIENTATION, VT_I4, "orientation", 1, g_possible_orientation, get_possible_values_int,
697     },
698     {
699         WIA_IPS_PAGE_SIZE, VT_I4, "page_size", 1, g_possible_page_size, get_possible_values_int,
700     },
701     {
702         WIA_IPS_PAGE_HEIGHT, VT_I4, "page_height", 0, NULL, get_possible_values_none,
703     },
704     {
705         WIA_IPS_PAGE_WIDTH, VT_I4, "page_width", 0, NULL, get_possible_values_none,
706     },
707     {
708         WIA_IPS_PAGES, VT_I4, "pages", 1, NULL, get_possible_values_none,
709     },
710     {
711         WIA_IPS_PHOTOMETRIC_INTERP, VT_I4, "photometric_interp", 1, g_possible_photometric_interp,
712         get_possible_values_int,
713     },
714     {
715         WIA_IPS_PREVIEW, VT_I4, "preview", 1, g_possible_preview, get_possible_values_int,
716     },
717     {
718         WIA_IPS_PREVIEW_TYPE, VT_I4, "preview_type", 0, g_possible_preview_type, get_possible_values_int,
719     },
720     {
721         WIA_IPS_ROTATION, VT_I4, "rotation", 1, g_possible_rotation, get_possible_values_int,
722     },
723     {
724         WIA_IPS_SEGMENTATION, VT_I4, "segmentation", 0, g_possible_segmentation, get_possible_values_int,
725     },
726     {
727         WIA_IPS_SHEET_FEEDER_REGISTRATION, VT_I4, "sheet_feeder_registration",
728         0, g_possible_sheet_feeder_registration, get_possible_values_int,
729     },
730     {
731         WIA_IPS_SHOW_PREVIEW_CONTROL, VT_I4, "show_preview_control",
732         0, g_possible_show_preview_control, get_possible_values_int,
733     },
734     {
735         WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION, VT_I4, "supportes_child_item_creation", 0, NULL,
736         get_possible_values_none,
737     },
738     {
739         WIA_IPS_THRESHOLD, VT_I4, "threshold", 1, NULL, get_possible_values_none,
740     },
741     {
742         WIA_IPS_TRANSFER_CAPABILITIES, VT_I4, "transfer_capabilities", 0, NULL, get_possible_values_none,
743     },
744     {
745         WIA_IPA_UPLOAD_ITEM_SIZE, VT_I4, "upload_item_size", 1, NULL, get_possible_values_none,
746     },
747     {
748         WIA_IPS_WARM_UP_TIME, VT_I4, "warm_up_time", 0, NULL, get_possible_values_none,
749     },
750     {
751         WIA_IPS_XEXTENT, VT_I4, "xextent", 1, NULL, get_possible_values_none,
752     },
753     {
754         WIA_IPS_XPOS, VT_I4, "xpos", 1, NULL, get_possible_values_none,
755     },
756     {
757         WIA_IPS_XRES, VT_I4, "xres", 1, NULL, get_possible_values_none,
758     },
759     {
760         WIA_IPS_XSCALING, VT_I4, "xscaling", 1, NULL, get_possible_values_none,
761     },
762     {
763         WIA_IPS_YEXTENT, VT_I4, "yextent", 1, NULL, get_possible_values_none,
764     },
765     {
766         WIA_IPS_YPOS, VT_I4, "ypos", 1, NULL, get_possible_values_none,
767     },
768     {
769         WIA_IPS_YRES, VT_I4, "yres", 1, NULL, get_possible_values_none,
770     },
771     {
772         WIA_IPS_YSCALING, VT_I4, "yscaling", 1, NULL, get_possible_values_none,
773     },
774     { 0 },
775 };
776 
777 const struct wia_property *g_wia_all_properties = _g_wia_all_properties;
778 
get_possible_values_int(const struct wia_property * propspec)779 static PyObject *get_possible_values_int(const struct wia_property *propspec)
780 {
781     struct wia_prop_int *values = (struct wia_prop_int *)propspec->possible_values;
782     PyObject *list;
783     PyObject *value;
784 
785     list = PyList_New(0);
786 
787     while(values->name != NULL) {
788         value = PyUnicode_FromString(values->name);
789         PyList_Append(list, value);
790         values++;
791     }
792 
793     return list;
794 }
795 
get_possible_values_clsid(const struct wia_property * propspec)796 static PyObject *get_possible_values_clsid(const struct wia_property *propspec)
797 {
798     struct wia_prop_clsid *values = (struct wia_prop_clsid *)propspec->possible_values;
799     PyObject *list;
800     PyObject *value;
801 
802     list = PyList_New(0);
803 
804     while(values->name != NULL) {
805         value = PyUnicode_FromString(values->name);
806         PyList_Append(list, value);
807         values++;
808     }
809 
810     return list;
811 }
812 
get_possible_values_none(const struct wia_property *)813 static PyObject *get_possible_values_none(const struct wia_property*)
814 {
815     Py_RETURN_NONE;
816 }
817 
int_to_pyobject(const struct wia_property * property,long value)818 PyObject *int_to_pyobject(const struct wia_property *property, long value)
819 {
820     const struct wia_prop_int *values;
821     int i;
822     PyObject *out;
823 
824     if (property->possible_values == NULL)
825         return PyLong_FromLong(value);
826     values = (const struct wia_prop_int *)property->possible_values;
827     for (i = 0 ; values[i].name != NULL ; i++) {
828         if (values[i].value == value)
829             return PyUnicode_FromString(values[i].name);
830     }
831 
832     char str[256];
833     str[0] = '\0';
834     str[sizeof(str)-1] = '\0';
835 
836     for (i = 0 ; values[i].name != NULL ; i++) {
837         if (value & values[i].value) {
838             if (str[0] == '\0')
839                 strncpy_s(str, values[i].name, sizeof(str) - 1);
840             else {
841                 strncat_s(str, ",", sizeof(str) - 1);
842                 strncat_s(str, values[i].name, sizeof(str) - 1);
843             }
844         }
845     }
846     if (str[0] != '\0') {
847         out = PyUnicode_FromString(str);
848         return out;
849     }
850 
851     return PyLong_FromLong(value);
852 }
853 
854 
clsid_to_pyobject(const struct wia_property * property,CLSID value)855 PyObject *clsid_to_pyobject(const struct wia_property *property, CLSID value)
856 {
857     const struct wia_prop_clsid *values;
858     int i;
859 
860     assert(property->possible_values != NULL);
861     values = (const struct wia_prop_clsid *)property->possible_values;
862     for (i = 0 ; NULL != values[i].name ; i++) {
863         if (values[i].value == value)
864             return PyUnicode_FromString(values[i].name);
865     }
866     wia_log(WIA_WARNING, "Got unknown clsid from driver (property=%s)", property->name);
867     return NULL;
868 }
869 
int_vector_to_pyobject_list(const CAL * values)870 PyObject *int_vector_to_pyobject_list(const CAL *values)
871 {
872     PyObject *out = PyList_New(values->cElems);
873     PyObject *val;
874     ULONG i;
875 
876     for (i = 0 ; i < values->cElems ; i++) {
877         val = PyLong_FromLong(values->pElems[i]);
878         PyList_SetItem(out, i, val);
879     }
880 
881     return out;
882 }
883 
int_vector_to_pyobject_tuple(const CAL * values)884 PyObject *int_vector_to_pyobject_tuple(const CAL *values)
885 {
886     PyObject *out;
887     PyObject *val;
888     int i;
889 
890     if (values->cElems < 2) {
891         wia_log(WIA_WARNING, "Got a range with not enough elements ! (%d)", values->cElems);
892         return NULL;
893     }
894 
895     out = PyTuple_New(values->cElems);
896     for (i = 0 ; i < values->cElems ; i++) {
897         val = PyLong_FromLong(values->pElems[i]);
898         PyTuple_SetItem(out, i, val);
899     }
900     return out;
901 }
902 
str_vector_to_pyobject(const CABSTR * values)903 PyObject *str_vector_to_pyobject(const CABSTR *values)
904 {
905     PyObject *out = PyList_New(values->cElems);
906     PyObject *val;
907     ULONG i;
908 
909     for (i = 0 ; i < values->cElems ; i++) {
910         //val = PyLong_FromLong(values->pElems[i]);
911         val = PyUnicode_FromWideChar(SysAllocString(values->pElems[i]), SysStringLen(values->pElems[i]));
912         PyList_SetItem(out, i, val);
913     }
914 
915     return out;
916 }
917 
pyobject_to_int(const struct wia_property * property_spec,PyObject * pyvalue,int fail_value)918 int pyobject_to_int(const struct wia_property *property_spec, PyObject *pyvalue, int fail_value)
919 {
920     char str[256];
921     char *pstr, *nstr;
922     int has_match;
923     int val;
924     int i;
925     const struct wia_prop_int *str2int;
926 
927     if (PyLong_Check(pyvalue))
928         return PyLong_AsLong(pyvalue);
929 
930     str2int = (const struct wia_prop_int *)property_spec->possible_values;
931     if (PyUnicode_Check(pyvalue) && str2int != NULL) {
932         // parse string
933         strncpy_s(str, PyUnicode_AsUTF8(pyvalue), sizeof(str));
934         val = 0;
935         has_match = 0;
936         pstr = str;
937         while(pstr) {
938             nstr = strchr(pstr, ',');
939             if (nstr) {
940                 nstr[0] = '\0';
941                 nstr++;
942             }
943             for (i = 0 ; str2int[i].name != NULL ; i++) {
944                 if (strcmp(pstr, str2int[i].name) == 0) {
945                     val |= str2int[i].value;
946                     has_match = 1;
947                     break;
948                 }
949             }
950             pstr = nstr;
951         }
952 
953         if (has_match) {
954             return val;
955         }
956     }
957 
958     wia_log(WIA_WARNING, "set_property(%s): Failed to parse value", property_spec->name);
959     return fail_value;
960 }
961 
pyobject_to_clsid(const struct wia_property * property_spec,PyObject * pyvalue,CLSID ** out)962 int pyobject_to_clsid(const struct wia_property *property_spec, PyObject *pyvalue, CLSID **out)
963 {
964     const struct wia_prop_clsid *str2clsid;
965     int i;
966     const char *value;
967 
968     if (!PyUnicode_Check(pyvalue)) {
969         wia_log(WIA_WARNING, "set_property(%s): Invalid type for clsid property", property_spec->name);
970         return 0;
971     }
972 
973     str2clsid = (const struct wia_prop_clsid *)property_spec->possible_values;
974     assert(str2clsid != NULL);
975 
976     value = PyUnicode_AsUTF8(pyvalue);
977 
978     for (i = 0 ; str2clsid[i].name != NULL ; i++) {
979         if (strcmp(value, str2clsid[i].name) == 0) {
980             *out = (CLSID *)&str2clsid[i].value;
981             return 1;
982         }
983     }
984 
985     wia_log(WIA_WARNING, "set_property(%s): Invalid value for clsid property", property_spec->name);
986     return 0;
987 }
988