gdi32: Avoid redundant computation of the gradient bounding rectangle.
[wine/multimedia.git] / dlls / twain_32 / dsm_ctrl.c
blobb50dbc5628540f16748859a14bc2598fad3562ca
1 /*
2 * TWAIN32 Source Manager
4 * Copyright 2000 Corel Corporation
5 * Copyright 2006 Marcus Meissner
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30 #include "windef.h"
31 #include "winbase.h"
32 #include "twain.h"
33 #include "twain_i.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(twain);
38 static TW_UINT16 DSM_initialized; /* whether Source Manager is initialized */
39 static TW_UINT32 DSM_sourceId; /* source id generator */
40 static TW_UINT16 DSM_currentDevice; /* keep track of device during enumeration */
42 struct all_devices {
43 char *modname;
44 TW_IDENTITY identity;
47 static int nrdevices = 0;
48 static struct all_devices *devices = NULL;
50 static void
51 twain_add_onedriver(const char *dsname) {
52 HMODULE hmod;
53 DSENTRYPROC dsEntry;
54 TW_IDENTITY fakeOrigin;
55 TW_IDENTITY sourceId;
56 TW_UINT16 ret;
58 hmod = LoadLibraryA(dsname);
59 if (!hmod) {
60 ERR("Failed to load TWAIN Source %s\n", dsname);
61 return;
63 dsEntry = (DSENTRYPROC)GetProcAddress(hmod, "DS_Entry");
64 if (!dsEntry) {
65 ERR("Failed to find DS_Entry() in TWAIN DS %s\n", dsname);
66 return;
68 /* Loop to do multiple detects, mostly for sane.ds and gphoto2.ds */
69 do {
70 int i;
72 sourceId.Id = DSM_sourceId;
73 sourceId.ProtocolMajor = TWON_PROTOCOLMAJOR;
74 sourceId.ProtocolMinor = TWON_PROTOCOLMINOR;
75 ret = dsEntry (&fakeOrigin, DG_CONTROL, DAT_IDENTITY, MSG_GET, &sourceId);
76 if (ret != TWRC_SUCCESS) {
77 ERR("Source->(DG_CONTROL,DAT_IDENTITY,MSG_GET) failed!\n");
78 return;
80 TRACE("Manufacturer: %s\n", debugstr_a(sourceId.Manufacturer));
81 TRACE("ProductFamily: %s\n", debugstr_a(sourceId.ProductFamily));
82 TRACE("ProductName: %s\n", debugstr_a(sourceId.ProductName));
84 for (i=0;i<nrdevices;i++) {
85 if (!strcmp(sourceId.ProductName,devices[i].identity.ProductName))
86 break;
88 if (i < nrdevices)
89 break;
90 if (nrdevices)
91 devices = HeapReAlloc(GetProcessHeap(), 0, devices, sizeof(devices[0])*(nrdevices+1));
92 else
93 devices = HeapAlloc(GetProcessHeap(), 0, sizeof(devices[0]));
94 if ((devices[nrdevices].modname = HeapAlloc(GetProcessHeap(), 0, strlen(dsname) + 1)))
95 lstrcpyA(devices[nrdevices].modname, dsname);
96 devices[nrdevices].identity = sourceId;
97 nrdevices++;
98 DSM_sourceId++;
99 } while (1);
100 FreeLibrary (hmod);
103 static int detectionrun = 0;
105 static void
106 twain_autodetect(void) {
107 if (detectionrun) return;
108 detectionrun = 1;
110 twain_add_onedriver("sane.ds");
111 twain_add_onedriver("gphoto2.ds");
112 #if 0
113 twain_add_onedriver("c:\\windows\\Twain_32\\Largan\\sp503a.ds");
114 twain_add_onedriver("c:\\windows\\Twain_32\\vivicam10\\vivicam10.ds");
115 twain_add_onedriver("c:\\windows\\Twain_32\\ws30slim\\sp500a.ds");
116 #endif
119 /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
120 TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
122 TW_UINT16 twRC = TWRC_SUCCESS;
123 pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
124 activeDS *currentDS = NULL, *prevDS = NULL;
126 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n");
128 for (currentDS = activeSources; currentDS; currentDS = currentDS->next) {
129 if (currentDS->identity.Id == pIdentity->Id)
130 break;
131 prevDS = currentDS;
133 if (!currentDS) {
134 DSM_twCC = TWCC_NODS;
135 return TWRC_FAILURE;
137 twRC = currentDS->dsEntry (pOrigin, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, pData);
138 /* This causes crashes due to still open Windows, so leave out for now.
139 * FreeLibrary (currentDS->hmod);
141 if (prevDS)
142 prevDS->next = currentDS->next;
143 else
144 activeSources = currentDS->next;
145 HeapFree (GetProcessHeap(), 0, currentDS);
146 if (twRC == TWRC_SUCCESS)
147 DSM_twCC = TWCC_SUCCESS;
148 else /* FIXME: unclear how to get TWCC */
149 DSM_twCC = TWCC_SEQERROR;
150 return twRC;
153 /* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */
154 TW_UINT16 TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData)
156 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
158 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n");
159 DSM_twCC = TWCC_NODS;
160 twain_autodetect();
161 if (!nrdevices)
162 return TWRC_FAILURE;
163 *pSourceIdentity = devices[0].identity;
164 DSM_twCC = TWCC_SUCCESS;
165 return TWRC_SUCCESS;
168 /* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */
169 TW_UINT16 TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin, TW_MEMREF pData)
171 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
173 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
174 twain_autodetect();
175 if (!nrdevices) {
176 TRACE ("no entries found.\n");
177 DSM_twCC = TWCC_NODS;
178 return TWRC_FAILURE;
180 DSM_currentDevice = 0;
181 *pSourceIdentity = devices[DSM_currentDevice++].identity;
182 return TWRC_SUCCESS;
185 /* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */
186 TW_UINT16 TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin, TW_MEMREF pData)
188 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
190 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n");
191 if (!nrdevices || (DSM_currentDevice == nrdevices)) {
192 DSM_twCC = TWCC_SUCCESS;
193 return TWRC_ENDOFLIST;
195 *pSourceIdentity = devices[DSM_currentDevice++].identity;
196 return TWRC_SUCCESS;
199 /* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */
200 TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
202 TW_UINT16 i = 0;
203 pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
204 activeDS *newSource;
205 const char *modname = NULL;
206 HMODULE hmod;
208 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n");
209 TRACE("pIdentity is %s\n", pIdentity->ProductName);
210 if (DSM_currentState != 3) {
211 FIXME("seq error\n");
212 DSM_twCC = TWCC_SEQERROR;
213 return TWRC_FAILURE;
215 twain_autodetect();
216 if (!nrdevices) {
217 FIXME("no devs.\n");
218 DSM_twCC = TWCC_NODS;
219 return TWRC_FAILURE;
222 if (pIdentity->ProductName[0] != '\0') {
223 /* Make sure the source to be opened exists in the device list */
224 for (i = 0; i<nrdevices; i++)
225 if (!strcmp (devices[i].identity.ProductName, pIdentity->ProductName))
226 break;
227 if (i == nrdevices)
228 i = 0;
229 } /* else use the first device */
231 /* the source is found in the device list */
232 newSource = HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS));
233 if (!newSource) {
234 DSM_twCC = TWCC_LOWMEMORY;
235 FIXME("Out of memory.\n");
236 return TWRC_FAILURE;
238 hmod = LoadLibraryA(devices[i].modname);
239 if (!hmod) {
240 ERR("Failed to load TWAIN Source %s\n", modname);
241 DSM_twCC = TWCC_OPERATIONERROR;
242 HeapFree(GetProcessHeap(), 0, newSource);
243 return TWRC_FAILURE;
245 newSource->hmod = hmod;
246 newSource->dsEntry = (DSENTRYPROC)GetProcAddress(hmod, "DS_Entry");
247 if (TWRC_SUCCESS != newSource->dsEntry (pOrigin, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, pIdentity)) {
248 DSM_twCC = TWCC_OPERATIONERROR;
249 HeapFree(GetProcessHeap(), 0, newSource);
250 return TWRC_FAILURE;
252 /* Assign name and id for the opened data source */
253 pIdentity->Id = DSM_sourceId ++;
254 /* add the data source to an internal active source list */
255 newSource->next = activeSources;
256 newSource->identity.Id = pIdentity->Id;
257 strcpy (newSource->identity.ProductName, pIdentity->ProductName);
258 activeSources = newSource;
259 DSM_twCC = TWCC_SUCCESS;
260 return TWRC_SUCCESS;
263 /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
264 TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData)
266 pTW_IDENTITY selected = (pTW_IDENTITY)pData;
268 if (!nrdevices) {
269 DSM_twCC = TWCC_OPERATIONERROR;
270 return TWRC_FAILURE;
272 *selected = devices[0].identity;
273 DSM_twCC = TWCC_SUCCESS;
274 return TWRC_SUCCESS;
277 /* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
278 TW_UINT16 TWAIN_CloseDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
280 activeDS *currentDS = activeSources, *nextDS;
282 TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n");
284 if (DSM_currentState == 3)
286 DSM_initialized = FALSE;
287 DSM_currentState = 2;
289 /* If there are data sources still open, close them now. */
290 while (currentDS != NULL)
292 nextDS = currentDS->next;
293 currentDS->dsEntry (pOrigin, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, pData);
294 HeapFree (GetProcessHeap(), 0, currentDS);
295 currentDS = nextDS;
297 activeSources = NULL;
298 DSM_twCC = TWCC_SUCCESS;
299 return TWRC_SUCCESS;
300 } else {
301 DSM_twCC = TWCC_SEQERROR;
302 return TWRC_FAILURE;
306 /* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */
307 TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
309 TW_UINT16 twRC = TWRC_SUCCESS;
311 TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
312 if (DSM_currentState == 2) {
313 if (!DSM_initialized) {
314 DSM_currentDevice = 0;
315 DSM_initialized = TRUE;
317 DSM_currentState = 3;
318 DSM_twCC = TWCC_SUCCESS;
319 twRC = TWRC_SUCCESS;
320 } else {
321 /* operation invoked in invalid state */
322 DSM_twCC = TWCC_SEQERROR;
323 twRC = TWRC_FAILURE;
325 return twRC;
328 /* DG_CONTROL/DAT_STATUS/MSG_GET */
329 TW_UINT16 TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin, TW_MEMREF pData)
331 pTW_STATUS pSourceStatus = (pTW_STATUS) pData;
333 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
335 pSourceStatus->ConditionCode = DSM_twCC;
336 DSM_twCC = TWCC_SUCCESS; /* clear the condition code */
337 return TWRC_SUCCESS;