rpcrt4: Fix the sending of >5800 byte messages by only adding offset
[wine.git] / dlls / twain / dsm_ctrl.c
blobf744939d2684338645d917c96d9acc8044582ae3
1 /*
2 * TWAIN32 Source Manager
4 * Copyright 2000 Corel Corporation
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdarg.h>
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"
34 WINE_DEFAULT_DEBUG_CHANNEL(twain);
36 /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
37 TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
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;
47 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n");
49 for (currentDS = activeSources; currentDS; currentDS = currentDS->next)
51 if (currentDS->identity.Id == pIdentity->Id)
52 break;
53 prevDS = currentDS;
55 if (currentDS)
57 /* Only valid to close a data source if it is in state 4 */
58 if (currentDS->currentState == 4)
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;
70 else
72 twRC = TWRC_FAILURE;
73 DSM_twCC = TWCC_SEQERROR;
76 else
78 twRC = TWRC_FAILURE;
79 DSM_twCC = TWCC_NODS;
82 return twRC;
83 #endif
86 /* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */
87 TW_UINT16 TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData)
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;
96 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n");
98 if (!device_list)
100 if ((sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
102 DSM_twCC = TWCC_NODS;
103 return TWRC_FAILURE;
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])
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;
118 twRC = TWRC_SUCCESS;
119 DSM_twCC = TWCC_SUCCESS;
121 else
123 twRC = TWRC_FAILURE;
124 DSM_twCC = TWCC_NODS;
127 return twRC;
128 #endif
131 /* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */
132 TW_UINT16 TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin, TW_MEMREF pData)
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;
142 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
144 status = sane_get_devices (&device_list, SANE_FALSE);
145 if (status == SANE_STATUS_GOOD)
147 if (device_list[0])
149 TRACE("got: %s, %s, %s\n", device_list[0]->name, device_list[0]->vendor, device_list[0]->model);
150 pSourceIdentity->Id = DSM_sourceId ++;
151 strcpy (pSourceIdentity->ProductName, device_list[0]->name);
152 strcpy (pSourceIdentity->Manufacturer, device_list[0]->vendor);
153 strcpy (pSourceIdentity->ProductFamily, device_list[0]->model);
154 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
155 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
157 DSM_currentDevice = 1;
158 twRC = TWRC_SUCCESS;
159 DSM_twCC = TWCC_SUCCESS;
161 else
163 TRACE("got empty device list\n");
164 twRC = TWRC_FAILURE;
165 DSM_twCC = TWCC_NODS;
168 else if (status == SANE_STATUS_NO_MEM)
170 twRC = TWRC_FAILURE;
171 DSM_twCC = TWCC_LOWMEMORY;
173 else
175 WARN("sane_get_devices() failed: %s\n", sane_strstatus (status));
176 twRC = TWRC_FAILURE;
177 DSM_twCC = TWCC_NODS;
180 return twRC;
181 #endif
184 /* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */
185 TW_UINT16 TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin, TW_MEMREF pData)
187 #ifndef HAVE_SANE
188 DSM_twCC = TWCC_SUCCESS;
189 return TWRC_ENDOFLIST;
190 #else
191 TW_UINT16 twRC = TWRC_SUCCESS;
192 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
194 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n");
196 if (device_list && device_list[DSM_currentDevice] &&
197 device_list[DSM_currentDevice]->name &&
198 device_list[DSM_currentDevice]->vendor &&
199 device_list[DSM_currentDevice]->model)
201 pSourceIdentity->Id = DSM_sourceId ++;
202 strcpy (pSourceIdentity->ProductName, device_list[DSM_currentDevice]->name);
203 strcpy (pSourceIdentity->Manufacturer, device_list[DSM_currentDevice]->vendor);
204 strcpy (pSourceIdentity->ProductFamily, device_list[DSM_currentDevice]->model);
205 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
206 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
207 DSM_currentDevice ++;
209 twRC = TWRC_SUCCESS;
210 DSM_twCC = TWCC_SUCCESS;
212 else
214 DSM_twCC = TWCC_SUCCESS;
215 twRC = TWRC_ENDOFLIST;
218 return twRC;
219 #endif
222 /* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */
223 TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
225 #ifndef HAVE_SANE
226 DSM_twCC = TWCC_NODS;
227 return TWRC_FAILURE;
228 #else
229 TW_UINT16 twRC = TWRC_SUCCESS, i = 0;
230 pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
231 activeDS *newSource;
232 SANE_Status status;
234 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n");
236 if (DSM_currentState != 3)
238 DSM_twCC = TWCC_SEQERROR;
239 return TWRC_FAILURE;
242 if (!device_list &&
243 (sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
245 DSM_twCC = TWCC_NODS;
246 return TWRC_FAILURE;
249 if (pIdentity->ProductName[0] != '\0')
251 /* Make sure the source to be opened exists in the device list */
252 for (i = 0; device_list[i]; i ++)
254 if (strcmp (device_list[i]->name, pIdentity->ProductName) == 0)
255 break;
259 if (device_list[i])
261 /* the source is found in the device list */
262 newSource = HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS));
263 if (newSource)
265 status = sane_open(device_list[i]->name,&newSource->deviceHandle);
266 if (status == SANE_STATUS_GOOD)
268 /* Assign name and id for the opened data source */
269 strcpy (pIdentity->ProductName, device_list[i]->name);
270 pIdentity->Id = DSM_sourceId ++;
271 /* add the data source to an internal active source list */
272 newSource->next = activeSources;
273 newSource->identity.Id = pIdentity->Id;
274 strcpy (newSource->identity.ProductName, pIdentity->ProductName);
275 newSource->currentState = 4; /*transition into state 4*/
276 newSource->twCC = TWCC_SUCCESS;
277 activeSources = newSource;
278 twRC = TWRC_SUCCESS;
279 DSM_twCC = TWCC_SUCCESS;
281 else
283 twRC = TWRC_FAILURE;
284 DSM_twCC = TWCC_OPERATIONERROR;
287 else
289 twRC = TWRC_FAILURE;
290 DSM_twCC = TWCC_LOWMEMORY;
293 else
295 twRC = TWRC_FAILURE;
296 DSM_twCC = TWCC_NODS;
299 return twRC;
300 #endif
303 /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
304 TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData)
306 #ifndef HAVE_SANE
307 return TWRC_SUCCESS;
308 #else
309 TW_UINT16 twRC = TWRC_SUCCESS;
311 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT\n");
313 /* FIXME: we should replace xscanimage with our own User Select UI */
314 system("xscanimage");
316 DSM_twCC = TWCC_SUCCESS;
317 return twRC;
318 #endif
321 /* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
322 TW_UINT16 TWAIN_CloseDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
324 #ifndef HAVE_SANE
325 return TWRC_FAILURE;
326 #else
327 TW_UINT16 twRC = TWRC_SUCCESS;
328 activeDS *currentDS = activeSources, *nextDS;
330 TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n");
332 if (DSM_currentState == 3)
334 sane_exit ();
335 DSM_initialized = FALSE;
336 DSM_parentHWND = 0;
337 DSM_currentState = 2;
339 /* If there are data sources still open, close them now. */
340 while (currentDS != NULL)
342 nextDS = currentDS->next;
343 sane_close (currentDS->deviceHandle);
344 HeapFree (GetProcessHeap(), 0, currentDS);
345 currentDS = nextDS;
347 activeSources = NULL;
348 DSM_twCC = TWCC_SUCCESS;
349 twRC = TWRC_SUCCESS;
351 else
353 DSM_twCC = TWCC_SEQERROR;
354 twRC = TWRC_FAILURE;
357 return twRC;
358 #endif
361 /* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */
362 TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
364 #ifndef HAVE_SANE
365 return TWRC_FAILURE;
366 #else
367 TW_UINT16 twRC = TWRC_SUCCESS;
368 SANE_Status status;
369 SANE_Int version_code;
371 TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
373 if (DSM_currentState == 2)
375 if (!DSM_initialized)
377 DSM_initialized = TRUE;
378 status = sane_init (&version_code, NULL);
379 device_list = NULL;
380 DSM_currentDevice = 0;
381 DSM_sourceId = 0;
383 DSM_parentHWND = *(TW_HANDLE*)pData;
384 DSM_currentState = 3; /* transition to state 3 */
385 DSM_twCC = TWCC_SUCCESS;
386 twRC = TWRC_SUCCESS;
388 else
390 /* operation invoked in invalid state */
391 DSM_twCC = TWCC_SEQERROR;
392 twRC = TWRC_FAILURE;
395 return twRC;
396 #endif
399 /* DG_CONTROL/DAT_STATUS/MSG_GET */
400 TW_UINT16 TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin, TW_MEMREF pData)
402 pTW_STATUS pSourceStatus = (pTW_STATUS) pData;
404 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
406 pSourceStatus->ConditionCode = DSM_twCC;
407 DSM_twCC = TWCC_SUCCESS; /* clear the condition code */
409 return TWRC_SUCCESS;