sane.ds: Send events to applications through the DSM.

Signed-off-by: Vincent Povirk <vincent@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Vincent Povirk 2017-11-14 15:14:11 -06:00 committed by Alexandre Julliard
parent 21ade8538d
commit 870c4f3e99
5 changed files with 81 additions and 22 deletions

View File

@ -184,13 +184,7 @@ TW_UINT16 SANE_ProcessEvent (pTW_IDENTITY pOrigin,
TRACE("DG_CONTROL/DAT_EVENT/MSG_PROCESSEVENT msg 0x%x, wParam 0x%lx\n", pMsg->message, pMsg->wParam);
activeDS.twCC = TWCC_SUCCESS;
if (pMsg->message == activeDS.windowMessage && activeDS.windowMessage)
{
twRC = TWRC_DSEVENT;
pEvent->TWMessage = pMsg->wParam;
}
else
pEvent->TWMessage = MSG_NULL; /* no message to the application */
pEvent->TWMessage = MSG_NULL; /* no message to the application */
if (activeDS.currentState < 5 || activeDS.currentState > 7)
{
@ -232,8 +226,7 @@ TW_UINT16 SANE_PendingXfersEndXfer (pTW_IDENTITY pOrigin,
pPendingXfers->Count = 0;
activeDS.currentState = 5;
/* Notify the application that it can close the data source */
if (activeDS.windowMessage)
PostMessageA(activeDS.hwndOwner, activeDS.windowMessage, MSG_CLOSEDSREQ, 0);
SANE_Notify(MSG_CLOSEDSREQ);
}
else
activeDS.sane_started = TRUE;
@ -403,8 +396,6 @@ TW_UINT16 SANE_EnableDSUserInterface (pTW_IDENTITY pOrigin,
else
{
activeDS.hwndOwner = pUserInterface->hParent;
if (! activeDS.windowMessage)
activeDS.windowMessage = RegisterWindowMessageA("SANE.DS ACTIVITY MESSAGE");
if (pUserInterface->ShowUI)
{
BOOL rc;
@ -413,8 +404,7 @@ TW_UINT16 SANE_EnableDSUserInterface (pTW_IDENTITY pOrigin,
pUserInterface->ModalUI = TRUE;
if (!rc)
{
if (activeDS.windowMessage)
PostMessageA(activeDS.hwndOwner, activeDS.windowMessage, MSG_CLOSEDSREQ, 0);
SANE_Notify(MSG_CLOSEDSREQ);
}
#ifdef SONAME_LIBSANE
else
@ -428,8 +418,7 @@ TW_UINT16 SANE_EnableDSUserInterface (pTW_IDENTITY pOrigin,
{
/* no UI will be displayed, so source is ready to transfer data */
activeDS.currentState = 6; /* Transitions to state 6 directly */
if (activeDS.windowMessage)
PostMessageA(activeDS.hwndOwner, activeDS.windowMessage, MSG_XFERREADY, 0);
SANE_Notify(MSG_XFERREADY);
}
twRC = TWRC_SUCCESS;

View File

@ -62,10 +62,10 @@ extern HINSTANCE SANE_instance DECLSPEC_HIDDEN;
struct tagActiveDS
{
struct tagActiveDS *next; /* next active DS */
TW_IDENTITY identity; /* identity */
TW_IDENTITY identity; /* identity of the DS */
TW_UINT16 currentState; /* current state */
UINT windowMessage; /* message to use to send status */
TW_UINT16 twCC; /* condition code */
TW_IDENTITY appIdentity; /* identity of the app */
HWND hwndOwner; /* window handle of the app */
HWND progressWnd; /* window handle of the scanning window */
#ifdef SONAME_LIBSANE
@ -89,6 +89,7 @@ struct tagActiveDS
/* Helper functions */
extern TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action) DECLSPEC_HIDDEN;
extern TW_UINT16 SANE_SaneSetDefaults (void) DECLSPEC_HIDDEN;
extern void SANE_Notify (TW_UINT16 message) DECLSPEC_HIDDEN;
/* Implementation of operation triplets
* From Application to Source (Control Information) */

View File

@ -30,6 +30,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(twain);
DSMENTRYPROC SANE_dsmentry;
#ifdef SONAME_LIBSANE
HINSTANCE SANE_instance;
@ -113,6 +115,8 @@ static TW_UINT16 SANE_OpenDS( pTW_IDENTITY, pTW_IDENTITY);
#endif /* SONAME_LIBSANE */
static TW_UINT16 SANE_SetEntryPoint (pTW_IDENTITY pOrigin, TW_MEMREF pData);
static TW_UINT16 SANE_SourceControlHandler (
pTW_IDENTITY pOrigin,
TW_UINT16 DAT,
@ -181,6 +185,17 @@ static TW_UINT16 SANE_SourceControlHandler (
}
break;
case DAT_ENTRYPOINT:
if (MSG == MSG_SET)
twRC = SANE_SetEntryPoint (pOrigin, pData);
else
{
twRC = TWRC_FAILURE;
activeDS.twCC = TWCC_CAPBADOPERATION;
FIXME("unrecognized operation triplet\n");
}
break;
case DAT_EVENT:
if (MSG == MSG_PROCESSEVENT)
twRC = SANE_ProcessEvent (pOrigin, pData);
@ -380,6 +395,21 @@ DS_Entry ( pTW_IDENTITY pOrigin,
return twRC;
}
void SANE_Notify (TW_UINT16 message)
{
SANE_dsmentry (&activeDS.identity, &activeDS.appIdentity, DG_CONTROL, DAT_NULL, message, NULL);
}
/* DG_CONTROL/DAT_ENTRYPOINT/MSG_SET */
TW_UINT16 SANE_SetEntryPoint (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
TW_ENTRYPOINT *entry = (TW_ENTRYPOINT*)pData;
SANE_dsmentry = entry->DSM_Entry;
return TWRC_SUCCESS;
}
#ifdef SONAME_LIBSANE
/* Sane returns device names that are longer than the 32 bytes allowed
by TWAIN. However, it colon separates them, and the last bit is
@ -432,7 +462,7 @@ SANE_GetIdentity( pTW_IDENTITY pOrigin, pTW_IDENTITY self) {
return TWRC_FAILURE;
self->ProtocolMajor = TWON_PROTOCOLMAJOR;
self->ProtocolMinor = TWON_PROTOCOLMINOR;
self->SupportedGroups = DG_CONTROL | DG_IMAGE;
self->SupportedGroups = DG_CONTROL | DG_IMAGE | DF_DS2;
copy_sane_short_name(sane_devlist[cursanedev]->name, self->ProductName, sizeof(self->ProductName) - 1);
lstrcpynA (self->Manufacturer, sane_devlist[cursanedev]->vendor, sizeof(self->Manufacturer) - 1);
lstrcpynA (self->ProductFamily, sane_devlist[cursanedev]->model, sizeof(self->ProductFamily) - 1);
@ -451,6 +481,21 @@ static TW_UINT16 SANE_OpenDS( pTW_IDENTITY pOrigin, pTW_IDENTITY self) {
SANE_Status status;
int i;
if (SANE_dsmentry == NULL)
{
static const WCHAR twain32W[] = {'t','w','a','i','n','_','3','2',0};
HMODULE moddsm = GetModuleHandleW(twain32W);
if (moddsm)
SANE_dsmentry = (void*)GetProcAddress(moddsm, "DSM_Entry");
if (!SANE_dsmentry)
{
ERR("can't find DSM entry point\n");
return TWRC_FAILURE;
}
}
detect_sane_devices();
if (!sane_devlist[0]) {
ERR("No scanners? We should not get to OpenDS?\n");
@ -481,6 +526,8 @@ static TW_UINT16 SANE_OpenDS( pTW_IDENTITY pOrigin, pTW_IDENTITY self) {
activeDS.twCC = SANE_SaneSetDefaults();
if (activeDS.twCC == TWCC_SUCCESS) {
activeDS.currentState = 4;
activeDS.identity.Id = self->Id;
activeDS.appIdentity = *pOrigin;
return TWRC_SUCCESS;
}
else

View File

@ -1034,13 +1034,11 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM
if (psn->lParam)
{
activeDS.currentState = 6;
if (activeDS.windowMessage)
PostMessageA(activeDS.hwndOwner, activeDS.windowMessage, MSG_XFERREADY, 0);
SANE_Notify(MSG_XFERREADY);
}
break;
case PSN_QUERYCANCEL:
if (activeDS.windowMessage)
PostMessageA(activeDS.hwndOwner, activeDS.windowMessage, MSG_CLOSEDSREQ, 0);
SANE_Notify(MSG_CLOSEDSREQ);
break;
case PSN_SETACTIVE:
InitializeDialog(hwndDlg);

View File

@ -1843,6 +1843,30 @@ typedef TW_UINT16 (*DSENTRYPROC)(pTW_IDENTITY,
}
#endif /* cplusplus */
/* Definitions from TWAIN 2.x used by our builtin data sources */
#define DAT_ENTRYPOINT 0x0403
#define DF_DS2 0x40000000
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef TW_HANDLE (PASCAL *DSM_MEMALLOCATE)(TW_UINT32 _size);
typedef void (PASCAL *DSM_MEMFREE)(TW_HANDLE _handle);
typedef TW_MEMREF (PASCAL *DSM_MEMLOCK)(TW_HANDLE _handle);
typedef void (PASCAL *DSM_MEMUNLOCK)(TW_HANDLE _handle);
#ifdef __cplusplus
}
#endif /* cplusplus */
typedef struct {
TW_UINT32 Size;
DSMENTRYPROC DSM_Entry;
DSM_MEMALLOCATE DSM_MemAllocate;
DSM_MEMFREE DSM_MemFree;
DSM_MEMLOCK DSM_MemLock;
DSM_MEMUNLOCK DSM_MemUnlock;
} TW_ENTRYPOINT;
/* The Twain structures must be packed on 2 byte alignment */
#include "poppack.h"