* Sync up to trunk head (r60691).
[reactos.git] / dll / win32 / twain_32 / dsm_ctrl.c
1 /*
2 * TWAIN32 Source Manager
3 *
4 * Copyright 2000 Corel Corporation
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 //#include "config.h"
22
23 //#include <stdlib.h>
24 //#include <stdarg.h>
25
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 //#include "windef.h"
29 //#include "winbase.h"
30 //#include "twain.h"
31 #include "twain_i.h"
32 #include <wine/debug.h>
33
34 WINE_DEFAULT_DEBUG_CHANNEL(twain);
35
36 /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
37 TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
38 {
39 #ifndef HAVE_SANE
40 DSM_twCC = TWCC_NODS;
41 return TWRC_FAILURE;
42 #else
43 TW_UINT16 twRC = TWRC_SUCCESS;
44 pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
45 activeDS *currentDS = NULL, *prevDS = NULL;
46
47 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n");
48
49 for (currentDS = activeSources; currentDS; currentDS = currentDS->next)
50 {
51 if (currentDS->identity.Id == pIdentity->Id)
52 break;
53 prevDS = currentDS;
54 }
55 if (currentDS)
56 {
57 /* Only valid to close a data source if it is in state 4 */
58 if (currentDS->currentState == 4)
59 {
60 sane_close (currentDS->deviceHandle);
61 /* remove the data source from active data source list */
62 if (prevDS)
63 prevDS->next = currentDS->next;
64 else
65 activeSources = currentDS->next;
66 HeapFree (GetProcessHeap(), 0, currentDS);
67 twRC = TWRC_SUCCESS;
68 DSM_twCC = TWCC_SUCCESS;
69 }
70 else
71 {
72 twRC = TWRC_FAILURE;
73 DSM_twCC = TWCC_SEQERROR;
74 }
75 }
76 else
77 {
78 twRC = TWRC_FAILURE;
79 DSM_twCC = TWCC_NODS;
80 }
81
82 return twRC;
83 #endif
84 }
85
86 /* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */
87 TW_UINT16 TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData)
88 {
89 #ifndef HAVE_SANE
90 DSM_twCC = TWCC_NODS;
91 return TWRC_FAILURE;
92 #else
93 TW_UINT16 twRC = TWRC_SUCCESS;
94 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
95
96 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n");
97
98 if (!device_list)
99 {
100 if ((sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
101 {
102 DSM_twCC = TWCC_NODS;
103 return TWRC_FAILURE;
104 }
105 }
106
107 /* FIXME: the default device is not necessarily the first device. *
108 * Users should be able to choose the default device */
109 if (device_list && device_list[0])
110 {
111 pSourceIdentity->Id = DSM_sourceId ++;
112 strcpy (pSourceIdentity->ProductName, device_list[0]->name);
113 strcpy (pSourceIdentity->Manufacturer, device_list[0]->vendor);
114 strcpy (pSourceIdentity->ProductFamily, device_list[0]->model);
115 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
116 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
117
118 twRC = TWRC_SUCCESS;
119 DSM_twCC = TWCC_SUCCESS;
120 }
121 else
122 {
123 twRC = TWRC_FAILURE;
124 DSM_twCC = TWCC_NODS;
125 }
126
127 return twRC;
128 #endif
129 }
130
131 /* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */
132 TW_UINT16 TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin, TW_MEMREF pData)
133 {
134 #ifndef HAVE_SANE
135 DSM_twCC = TWCC_NODS;
136 return TWRC_FAILURE;
137 #else
138 TW_UINT16 twRC = TWRC_SUCCESS;
139 pTW_IDENTITY pSourceIdentity;/* = (pTW_IDENTITY) pData;*/
140 SANE_Status status;
141
142 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
143
144 status = sane_get_devices (&device_list, SANE_FALSE);
145 if (status == SANE_STATUS_GOOD)
146 {
147 if (device_list[0])
148 {
149 pSourceIdentity->Id = DSM_sourceId ++;
150 strcpy (pSourceIdentity->ProductName, device_list[0]->name);
151 strcpy (pSourceIdentity->Manufacturer, device_list[0]->vendor);
152 strcpy (pSourceIdentity->ProductFamily, device_list[0]->model);
153 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
154 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
155 }
156 DSM_currentDevice = 1;
157 twRC = TWRC_SUCCESS;
158 DSM_twCC = TWCC_SUCCESS;
159 }
160 else if (status == SANE_STATUS_NO_MEM)
161 {
162 twRC = TWRC_FAILURE;
163 DSM_twCC = TWCC_LOWMEMORY;
164 }
165 else
166 {
167 WARN("sane_get_devices() failed: %s\n", sane_strstatus (status));
168 twRC = TWRC_FAILURE;
169 DSM_twCC = TWCC_NODS;
170 }
171
172 return twRC;
173 #endif
174 }
175
176 /* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */
177 TW_UINT16 TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin, TW_MEMREF pData)
178 {
179 #ifndef HAVE_SANE
180 DSM_twCC = TWCC_SUCCESS;
181 return TWRC_ENDOFLIST;
182 #else
183 TW_UINT16 twRC = TWRC_SUCCESS;
184 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
185
186 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n");
187
188 if (device_list && device_list[DSM_currentDevice])
189 {
190 pSourceIdentity->Id = DSM_sourceId ++;
191 strcpy (pSourceIdentity->ProductName, device_list[DSM_currentDevice]->name);
192 strcpy (pSourceIdentity->Manufacturer, device_list[DSM_currentDevice]->vendor);
193 strcpy (pSourceIdentity->ProductFamily, device_list[DSM_currentDevice]->model);
194 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
195 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
196 DSM_currentDevice ++;
197
198 twRC = TWRC_SUCCESS;
199 DSM_twCC = TWCC_SUCCESS;
200 }
201 else
202 {
203 DSM_twCC = TWCC_SUCCESS;
204 twRC = TWRC_ENDOFLIST;
205 }
206
207 return twRC;
208 #endif
209 }
210
211 /* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */
212 TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
213 {
214 #ifndef HAVE_SANE
215 DSM_twCC = TWCC_NODS;
216 return TWRC_FAILURE;
217 #else
218 TW_UINT16 twRC = TWRC_SUCCESS, i = 0;
219 pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
220 activeDS *newSource;
221 SANE_Status status;
222
223 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n");
224
225 if (DSM_currentState != 3)
226 {
227 DSM_twCC = TWCC_SEQERROR;
228 return TWRC_FAILURE;
229 }
230
231 if (!device_list &&
232 (sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
233 {
234 DSM_twCC = TWCC_NODS;
235 return TWRC_FAILURE;
236 }
237
238 if (pIdentity->ProductName[0] != '\0')
239 {
240 /* Make sure the source to be open exists in the device list */
241 for (i = 0; device_list[i]; i ++)
242 {
243 if (strcmp (device_list[i]->name, pIdentity->ProductName) == 0)
244 break;
245 }
246 }
247
248 if (device_list[i])
249 {
250 /* the source is found in the device list */
251 newSource = HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS));
252 if (newSource)
253 {
254 status = sane_open(device_list[i]->name,&newSource->deviceHandle);
255 if (status == SANE_STATUS_GOOD)
256 {
257 /* Assign name and id for the opened data source */
258 strcpy (pIdentity->ProductName, device_list[i]->name);
259 pIdentity->Id = DSM_sourceId ++;
260 /* add the data source to an internal active source list */
261 newSource->next = activeSources;
262 newSource->identity.Id = pIdentity->Id;
263 strcpy (newSource->identity.ProductName, pIdentity->ProductName);
264 newSource->currentState = 4; /*transition into state 4*/
265 newSource->twCC = TWCC_SUCCESS;
266 activeSources = newSource;
267 twRC = TWRC_SUCCESS;
268 DSM_twCC = TWCC_SUCCESS;
269 }
270 else
271 {
272 twRC = TWRC_FAILURE;
273 DSM_twCC = TWCC_OPERATIONERROR;
274 }
275 }
276 else
277 {
278 twRC = TWRC_FAILURE;
279 DSM_twCC = TWCC_LOWMEMORY;
280 }
281 }
282 else
283 {
284 twRC = TWRC_FAILURE;
285 DSM_twCC = TWCC_NODS;
286 }
287
288 return twRC;
289 #endif
290 }
291
292 /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
293 TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData)
294 {
295 #ifndef HAVE_SANE
296 return TWRC_SUCCESS;
297 #else
298 TW_UINT16 twRC = TWRC_SUCCESS;
299
300 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT\n");
301
302 /* FIXME: we should replace xscanimage with our own User Select UI */
303 system("xscanimage");
304
305 DSM_twCC = TWCC_SUCCESS;
306 return twRC;
307 #endif
308 }
309
310 /* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
311 TW_UINT16 TWAIN_CloseDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
312 {
313 #ifndef HAVE_SANE
314 return TWRC_FAILURE;
315 #else
316 TW_UINT16 twRC = TWRC_SUCCESS;
317 activeDS *currentDS = activeSources, *nextDS;
318
319 TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n");
320
321 if (DSM_currentState == 3)
322 {
323 sane_exit ();
324 DSM_initialized = FALSE;
325 DSM_parentHWND = 0;
326 DSM_currentState = 2;
327
328 /* If there are data sources still open, close them now. */
329 while (currentDS != NULL)
330 {
331 nextDS = currentDS->next;
332 sane_close (currentDS->deviceHandle);
333 HeapFree (GetProcessHeap(), 0, currentDS);
334 currentDS = nextDS;
335 }
336 activeSources = NULL;
337 DSM_twCC = TWCC_SUCCESS;
338 twRC = TWRC_SUCCESS;
339 }
340 else
341 {
342 DSM_twCC = TWCC_SEQERROR;
343 twRC = TWRC_FAILURE;
344 }
345
346 return twRC;
347 #endif
348 }
349
350 /* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */
351 TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
352 {
353 #ifndef HAVE_SANE
354 return TWRC_FAILURE;
355 #else
356 TW_UINT16 twRC = TWRC_SUCCESS;
357 SANE_Status status;
358 SANE_Int version_code;
359
360 TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
361
362 if (DSM_currentState == 2)
363 {
364 if (!DSM_initialized)
365 {
366 DSM_initialized = TRUE;
367 status = sane_init (&version_code, NULL);
368 device_list = NULL;
369 DSM_currentDevice = 0;
370 DSM_sourceId = 0;
371 }
372 DSM_parentHWND = *(TW_HANDLE*)pData;
373 DSM_currentState = 3; /* transition to state 3 */
374 DSM_twCC = TWCC_SUCCESS;
375 twRC = TWRC_SUCCESS;
376 }
377 else
378 {
379 /* operation invoked in invalid state */
380 DSM_twCC = TWCC_SEQERROR;
381 twRC = TWRC_FAILURE;
382 }
383
384 return twRC;
385 #endif
386 }
387
388 /* DG_CONTROL/DAT_STATUS/MSG_GET */
389 TW_UINT16 TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin, TW_MEMREF pData)
390 {
391 pTW_STATUS pSourceStatus = (pTW_STATUS) pData;
392
393 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
394
395 pSourceStatus->ConditionCode = DSM_twCC;
396 DSM_twCC = TWCC_SUCCESS; /* clear the condition code */
397
398 return TWRC_SUCCESS;
399 }