| /* | |
| * TWAIN32 Source Manager | |
| * | |
| * Copyright 2000 Corel Corporation | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| #include "config.h" | |
| #include <stdlib.h> | |
| #include "winbase.h" | |
| #include "twain.h" | |
| #include "twain_i.h" | |
| #include "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(twain); | |
| /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */ | |
| TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData) | |
| { | |
| #ifndef HAVE_SANE | |
| DSM_twCC = TWCC_NODS; | |
| return TWRC_FAILURE; | |
| #else | |
| TW_UINT16 twRC = TWRC_SUCCESS; | |
| pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData; | |
| activeDS *currentDS = NULL, *prevDS = NULL; | |
| TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n"); | |
| for (currentDS = activeSources; currentDS; currentDS = currentDS->next) | |
| { | |
| if (currentDS->identity.Id == pIdentity->Id) | |
| break; | |
| prevDS = currentDS; | |
| } | |
| if (currentDS) | |
| { | |
| /* Only valid to close a data source if it is in state 4 */ | |
| if (currentDS->currentState == 4) | |
| { | |
| sane_close (currentDS->deviceHandle); | |
| /* remove the data source from active data source list */ | |
| if (prevDS) | |
| prevDS->next = currentDS->next; | |
| else | |
| activeSources = currentDS->next; | |
| HeapFree (GetProcessHeap(), 0, currentDS); | |
| twRC = TWRC_SUCCESS; | |
| DSM_twCC = TWCC_SUCCESS; | |
| } | |
| else | |
| { | |
| twRC = TWRC_FAILURE; | |
| DSM_twCC = TWCC_SEQERROR; | |
| } | |
| } | |
| else | |
| { | |
| twRC = TWRC_FAILURE; | |
| DSM_twCC = TWCC_NODS; | |
| } | |
| return twRC; | |
| #endif | |
| } | |
| /* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */ | |
| TW_UINT16 TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData) | |
| { | |
| #ifndef HAVE_SANE | |
| DSM_twCC = TWCC_NODS; | |
| return TWRC_FAILURE; | |
| #else | |
| TW_UINT16 twRC = TWRC_SUCCESS; | |
| pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData; | |
| TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n"); | |
| if (!device_list) | |
| { | |
| if ((sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD)) | |
| { | |
| DSM_twCC = TWCC_NODS; | |
| return TWRC_FAILURE; | |
| } | |
| } | |
| /* FIXME: the default device is not necessarily the first device. * | |
| * Users should be able to choose the default device */ | |
| if (device_list && device_list[0]) | |
| { | |
| pSourceIdentity->Id = DSM_sourceId ++; | |
| strcpy (pSourceIdentity->ProductName, device_list[0]->name); | |
| strcpy (pSourceIdentity->Manufacturer, device_list[0]->vendor); | |
| strcpy (pSourceIdentity->ProductFamily, device_list[0]->model); | |
| pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR; | |
| pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR; | |
| twRC = TWRC_SUCCESS; | |
| DSM_twCC = TWCC_SUCCESS; | |
| } | |
| else | |
| { | |
| twRC = TWRC_FAILURE; | |
| DSM_twCC = TWCC_NODS; | |
| } | |
| return twRC; | |
| #endif | |
| } | |
| /* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */ | |
| TW_UINT16 TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin, TW_MEMREF pData) | |
| { | |
| #ifndef HAVE_SANE | |
| DSM_twCC = TWCC_NODS; | |
| return TWRC_FAILURE; | |
| #else | |
| TW_UINT16 twRC = TWRC_SUCCESS; | |
| pTW_IDENTITY pSourceIdentity;/* = (pTW_IDENTITY) pData;*/ | |
| SANE_Status status; | |
| TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n"); | |
| status = sane_get_devices (&device_list, SANE_FALSE); | |
| if (status == SANE_STATUS_GOOD) | |
| { | |
| if (device_list[0]) | |
| { | |
| pSourceIdentity->Id = DSM_sourceId ++; | |
| strcpy (pSourceIdentity->ProductName, device_list[0]->name); | |
| strcpy (pSourceIdentity->Manufacturer, device_list[0]->vendor); | |
| strcpy (pSourceIdentity->ProductFamily, device_list[0]->model); | |
| pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR; | |
| pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR; | |
| } | |
| DSM_currentDevice = 1; | |
| twRC = TWRC_SUCCESS; | |
| DSM_twCC = TWCC_SUCCESS; | |
| } | |
| else if (status == SANE_STATUS_NO_MEM) | |
| { | |
| twRC = TWRC_FAILURE; | |
| DSM_twCC = TWCC_LOWMEMORY; | |
| } | |
| else | |
| { | |
| WARN("sane_get_devices() failed: %s\n", sane_strstatus (status)); | |
| twRC = TWRC_FAILURE; | |
| DSM_twCC = TWCC_NODS; | |
| } | |
| return twRC; | |
| #endif | |
| } | |
| /* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */ | |
| TW_UINT16 TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin, TW_MEMREF pData) | |
| { | |
| #ifndef HAVE_SANE | |
| DSM_twCC = TWCC_SUCCESS; | |
| return TWRC_ENDOFLIST; | |
| #else | |
| TW_UINT16 twRC = TWRC_SUCCESS; | |
| pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData; | |
| TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n"); | |
| if (device_list && device_list[DSM_currentDevice]) | |
| { | |
| pSourceIdentity->Id = DSM_sourceId ++; | |
| strcpy (pSourceIdentity->ProductName, device_list[DSM_currentDevice]->name); | |
| strcpy (pSourceIdentity->Manufacturer, device_list[DSM_currentDevice]->vendor); | |
| strcpy (pSourceIdentity->ProductFamily, device_list[DSM_currentDevice]->model); | |
| pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR; | |
| pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR; | |
| DSM_currentDevice ++; | |
| twRC = TWRC_SUCCESS; | |
| DSM_twCC = TWCC_SUCCESS; | |
| } | |
| else | |
| { | |
| DSM_twCC = TWCC_SUCCESS; | |
| twRC = TWRC_ENDOFLIST; | |
| } | |
| return twRC; | |
| #endif | |
| } | |
| /* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */ | |
| TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData) | |
| { | |
| #ifndef HAVE_SANE | |
| DSM_twCC = TWCC_NODS; | |
| return TWRC_FAILURE; | |
| #else | |
| TW_UINT16 twRC = TWRC_SUCCESS, i = 0; | |
| pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData; | |
| activeDS *newSource; | |
| SANE_Status status; | |
| TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n"); | |
| if (DSM_currentState != 3) | |
| { | |
| DSM_twCC = TWCC_SEQERROR; | |
| return TWRC_FAILURE; | |
| } | |
| if (!device_list && | |
| (sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD)) | |
| { | |
| DSM_twCC = TWCC_NODS; | |
| return TWRC_FAILURE; | |
| } | |
| if (pIdentity->ProductName[0] != '\0') | |
| { | |
| /* Make sure the source to be open exists in the device list */ | |
| for (i = 0; device_list[i]; i ++) | |
| { | |
| if (strcmp (device_list[i]->name, pIdentity->ProductName) == 0) | |
| break; | |
| } | |
| } | |
| if (device_list[i]) | |
| { | |
| /* the source is found in the device list */ | |
| newSource = HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS)); | |
| if (newSource) | |
| { | |
| status = sane_open(device_list[i]->name,&newSource->deviceHandle); | |
| if (status == SANE_STATUS_GOOD) | |
| { | |
| /* Assign name and id for the opened data source */ | |
| strcpy (pIdentity->ProductName, device_list[i]->name); | |
| pIdentity->Id = DSM_sourceId ++; | |
| /* add the data source to an internal active source list */ | |
| newSource->next = activeSources; | |
| newSource->identity.Id = pIdentity->Id; | |
| strcpy (newSource->identity.ProductName, pIdentity->ProductName); | |
| newSource->currentState = 4; /*transition into state 4*/ | |
| newSource->twCC = TWCC_SUCCESS; | |
| activeSources = newSource; | |
| twRC = TWRC_SUCCESS; | |
| DSM_twCC = TWCC_SUCCESS; | |
| } | |
| else | |
| { | |
| twRC = TWRC_FAILURE; | |
| DSM_twCC = TWCC_OPERATIONERROR; | |
| } | |
| } | |
| else | |
| { | |
| twRC = TWRC_FAILURE; | |
| DSM_twCC = TWCC_LOWMEMORY; | |
| } | |
| } | |
| else | |
| { | |
| twRC = TWRC_FAILURE; | |
| DSM_twCC = TWCC_NODS; | |
| } | |
| return twRC; | |
| #endif | |
| } | |
| /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */ | |
| TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData) | |
| { | |
| #ifndef HAVE_SANE | |
| return TWRC_SUCCESS; | |
| #else | |
| TW_UINT16 twRC = TWRC_SUCCESS; | |
| TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT\n"); | |
| /* FIXME: we should replace xscanimage with our own User Select UI */ | |
| system("xscanimage"); | |
| DSM_twCC = TWCC_SUCCESS; | |
| return twRC; | |
| #endif | |
| } | |
| /* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */ | |
| TW_UINT16 TWAIN_CloseDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData) | |
| { | |
| #ifndef HAVE_SANE | |
| return TWRC_FAILURE; | |
| #else | |
| TW_UINT16 twRC = TWRC_SUCCESS; | |
| activeDS *currentDS = activeSources, *nextDS; | |
| TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n"); | |
| if (DSM_currentState == 3) | |
| { | |
| sane_exit (); | |
| DSM_initialized = FALSE; | |
| DSM_parentHWND = 0; | |
| DSM_currentState = 2; | |
| /* If there are data sources still open, close them now. */ | |
| while (currentDS != NULL) | |
| { | |
| nextDS = currentDS->next; | |
| sane_close (currentDS->deviceHandle); | |
| HeapFree (GetProcessHeap(), 0, currentDS); | |
| currentDS = nextDS; | |
| } | |
| activeSources = NULL; | |
| DSM_twCC = TWCC_SUCCESS; | |
| twRC = TWRC_SUCCESS; | |
| } | |
| else | |
| { | |
| DSM_twCC = TWCC_SEQERROR; | |
| twRC = TWRC_FAILURE; | |
| } | |
| return twRC; | |
| #endif | |
| } | |
| /* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */ | |
| TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData) | |
| { | |
| #ifndef HAVE_SANE | |
| return TWRC_FAILURE; | |
| #else | |
| TW_UINT16 twRC = TWRC_SUCCESS; | |
| SANE_Status status; | |
| SANE_Int version_code; | |
| TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n"); | |
| if (DSM_currentState == 2) | |
| { | |
| if (!DSM_initialized) | |
| { | |
| DSM_initialized = TRUE; | |
| status = sane_init (&version_code, NULL); | |
| device_list = NULL; | |
| DSM_currentDevice = 0; | |
| DSM_sourceId = 0; | |
| } | |
| DSM_parentHWND = *(TW_HANDLE*)pData; | |
| DSM_currentState = 3; /* transition to state 3 */ | |
| DSM_twCC = TWCC_SUCCESS; | |
| twRC = TWRC_SUCCESS; | |
| } | |
| else | |
| { | |
| /* operation invoked in invalid state */ | |
| DSM_twCC = TWCC_SEQERROR; | |
| twRC = TWRC_FAILURE; | |
| } | |
| return twRC; | |
| #endif | |
| } | |
| /* DG_CONTROL/DAT_STATUS/MSG_GET */ | |
| TW_UINT16 TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin, TW_MEMREF pData) | |
| { | |
| pTW_STATUS pSourceStatus = (pTW_STATUS) pData; | |
| TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n"); | |
| pSourceStatus->ConditionCode = DSM_twCC; | |
| DSM_twCC = TWCC_SUCCESS; /* clear the condition code */ | |
| return TWRC_SUCCESS; | |
| } |