Vincent Povirk : twain_32: Add support for DAT_NULL commands.

Alexandre Julliard julliard at winehq.org
Tue Oct 24 02:40:04 CDT 2017


Module: wine
Branch: master
Commit: 24a10e301a3056fbdb6d348fc7c96db68c6c1fad
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=24a10e301a3056fbdb6d348fc7c96db68c6c1fad

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Fri Oct 20 14:16:26 2017 -0500

twain_32: Add support for DAT_NULL commands.

Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/twain_32/Makefile.in    |  1 +
 dlls/twain_32/dsm_ctrl.c     | 89 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/twain_32/twain32_main.c | 28 ++++++++++++++
 dlls/twain_32/twain_i.h      | 14 +++++++
 4 files changed, 132 insertions(+)

diff --git a/dlls/twain_32/Makefile.in b/dlls/twain_32/Makefile.in
index 451c489..cadaf80 100644
--- a/dlls/twain_32/Makefile.in
+++ b/dlls/twain_32/Makefile.in
@@ -1,4 +1,5 @@
 MODULE    = twain_32.dll
+IMPORTS   = user32
 
 C_SRCS = \
 	dsm_ctrl.c \
diff --git a/dlls/twain_32/dsm_ctrl.c b/dlls/twain_32/dsm_ctrl.c
index b20d55c..9b87867 100644
--- a/dlls/twain_32/dsm_ctrl.c
+++ b/dlls/twain_32/dsm_ctrl.c
@@ -27,6 +27,7 @@
 
 #include "windef.h"
 #include "winbase.h"
+#include "winuser.h"
 #include "twain.h"
 #include "twain_i.h"
 #include "wine/debug.h"
@@ -36,6 +37,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(twain);
 static TW_UINT16 DSM_initialized;	/* whether Source Manager is initialized */
 static TW_UINT32 DSM_sourceId;		/* source id generator */
 static TW_UINT16 DSM_currentDevice;	/* keep track of device during enumeration */
+static HWND DSM_parent;
+static UINT event_message;
 
 struct all_devices {
 	char 		*modname;
@@ -114,6 +117,86 @@ twain_autodetect(void) {
 #endif
 }
 
+/* DG_CONTROL/DAT_NULL/MSG_CLOSEDSREQ|MSG_DEVICEEVENT|MSG_XFERREADY */
+TW_UINT16 TWAIN_ControlNull (pTW_IDENTITY pOrigin, pTW_IDENTITY pDest, activeDS *pSource, TW_UINT16 MSG, TW_MEMREF pData)
+{
+    struct pending_message *message;
+
+    TRACE ("DG_CONTROL/DAT_NULL MSG=%i\n", MSG);
+
+    if (MSG != MSG_CLOSEDSREQ &&
+        MSG != MSG_DEVICEEVENT &&
+        MSG != MSG_XFERREADY)
+    {
+        DSM_twCC = TWCC_BADPROTOCOL;
+        return TWRC_FAILURE;
+    }
+
+    message = HeapAlloc(GetProcessHeap(), 0, sizeof(*message));
+    if (!message)
+    {
+        DSM_twCC = TWCC_LOWMEMORY;
+        return TWRC_FAILURE;
+    }
+
+    message->msg = MSG;
+    list_add_tail(&pSource->pending_messages, &message->entry);
+
+    /* Delphi twain only sends us messages from one window, and it
+       doesn't even give us the real handle to that window. Other
+       applications might decide to forward messages sent to DSM_parent
+       or to the one supplied to ENABLEDS. So let's try very hard to
+       find a window that will work. */
+    if (DSM_parent)
+        PostMessageW(DSM_parent, event_message, 0, 0);
+    if (pSource->ui_window && pSource->ui_window != DSM_parent)
+        PostMessageW(pSource->ui_window, event_message, 0, 0);
+    if (pSource->event_window && pSource->event_window != pSource->ui_window &&
+        pSource->event_window != DSM_parent)
+        PostMessageW(pSource->event_window, event_message, 0, 0);
+    PostMessageW(0, event_message, 0, 0);
+
+    return TWRC_SUCCESS;
+}
+
+/* Filters MSG_PROCESSEVENT messages before reaching the data source */
+TW_UINT16 TWAIN_ProcessEvent (pTW_IDENTITY pOrigin, activeDS *pSource, TW_MEMREF pData)
+{
+    TW_EVENT *event = (TW_EVENT*)pData;
+    MSG *msg = (MSG*)event->pEvent;
+    TW_UINT16 result = TWRC_NOTDSEVENT;
+
+    TRACE("%x,%x\n", msg->message, event_message);
+
+    if (msg->message == event_message)
+    {
+        if (!list_empty (&pSource->pending_messages))
+        {
+            struct list *entry = list_head (&pSource->pending_messages);
+            struct pending_message *message = LIST_ENTRY(entry, struct pending_message, entry);
+            event->TWMessage = message->msg;
+            list_remove (entry);
+            TRACE("<-- %x\n", event->TWMessage);
+        }
+        else
+            event->TWMessage = MSG_NULL;
+        result = TWRC_DSEVENT;
+    }
+
+    if (msg->hwnd)
+    {
+        MSG dummy;
+        pSource->event_window = msg->hwnd;
+        if (!list_empty (&pSource->pending_messages) &&
+            !PeekMessageW(&dummy, msg->hwnd, event_message, event_message, PM_NOREMOVE))
+        {
+            PostMessageW(msg->hwnd, event_message, 0, 0);
+        }
+    }
+
+    return result;
+}
+
 /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
 TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
 {
@@ -254,6 +337,9 @@ TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
 	newSource->next = activeSources;
 	newSource->identity.Id = pIdentity->Id;
 	strcpy (newSource->identity.ProductName, pIdentity->ProductName);
+        list_init(&newSource->pending_messages);
+        newSource->ui_window = NULL;
+        newSource->event_window = NULL;
 	activeSources = newSource;
 	DSM_twCC = TWCC_SUCCESS;
 	return TWRC_SUCCESS;
@@ -299,6 +385,7 @@ TW_UINT16 TWAIN_CloseDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
             currentDS = nextDS;
         }
         activeSources = NULL;
+        DSM_parent = NULL;
         DSM_twCC = TWCC_SUCCESS;
         return TWRC_SUCCESS;
     } else {
@@ -314,6 +401,7 @@ TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
 
 	TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
         if (!DSM_initialized) {
+                event_message = RegisterWindowMessageA("WINE TWAIN_32 EVENT");
 		DSM_currentDevice = 0;
 		DSM_initialized = TRUE;
 		DSM_twCC = TWCC_SUCCESS;
@@ -323,6 +411,7 @@ TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
 		DSM_twCC = TWCC_SEQERROR;
 		twRC = TWRC_FAILURE;
 	}
+        DSM_parent = (HWND)pData;
 	return twRC;
 }
 
diff --git a/dlls/twain_32/twain32_main.c b/dlls/twain_32/twain32_main.c
index f7b8f58..d1977b4 100644
--- a/dlls/twain_32/twain32_main.c
+++ b/dlls/twain_32/twain32_main.c
@@ -142,6 +142,19 @@ DSM_Entry (pTW_IDENTITY pOrigin,
 
     TRACE("(DG=%d DAT=%d MSG=%d)\n", DG, DAT, MSG);
 
+    if (DG == DG_CONTROL && DAT == DAT_NULL)
+    {
+        activeDS *pSource = TWAIN_LookupSource (pOrigin);
+        if (!pSource)
+        {
+            ERR("No source associated with pSource %p\n", pDest);
+            DSM_twCC = TWCC_BADPROTOCOL;
+            return TWRC_FAILURE;
+        }
+
+        return TWAIN_ControlNull (pOrigin, pDest, pSource, MSG, pData);
+    }
+
     if (pDest)
     {
         activeDS *pSource = TWAIN_LookupSource (pDest);
@@ -152,6 +165,21 @@ DSM_Entry (pTW_IDENTITY pOrigin,
 	    DSM_twCC = TWCC_BADDEST;
 	    return TWRC_FAILURE;
 	}
+
+        if (DG == DG_CONTROL && DAT == DAT_EVENT && MSG == MSG_PROCESSEVENT)
+        {
+            twRC = TWAIN_ProcessEvent(pOrigin, pSource, pData);
+            if (twRC == TWRC_DSEVENT)
+                return twRC;
+        }
+
+        if (DG == DG_CONTROL && DAT == DAT_USERINTERFACE &&
+            (MSG == MSG_ENABLEDS || MSG == MSG_ENABLEDSUIONLY) &&
+            pData != NULL)
+        {
+            pSource->ui_window = ((TW_USERINTERFACE*)pData)->hParent;
+        }
+
 	DSM_twCC = TWCC_SUCCESS;
         TRACE("Forwarding %d/%d/%d/%p to DS.\n", DG, DAT, MSG, pData);
 	twRC = pSource->dsEntry(pOrigin, DG, DAT, MSG, pData);
diff --git a/dlls/twain_32/twain_i.h b/dlls/twain_32/twain_i.h
index a8fa2fb..f46999c 100644
--- a/dlls/twain_32/twain_i.h
+++ b/dlls/twain_32/twain_i.h
@@ -29,6 +29,13 @@
 #include "windef.h"
 #include "winbase.h"
 #include "twain.h"
+#include "wine/list.h"
+
+struct pending_message
+{
+    struct list entry;
+    TW_UINT16 msg;
+};
 
 /* internal information about an active data source */
 typedef struct tagActiveDS
@@ -37,6 +44,9 @@ typedef struct tagActiveDS
     TW_IDENTITY		identity;		/* identity */
     HMODULE		hmod;
     DSENTRYPROC		dsEntry;
+    struct list         pending_messages;
+    HWND                ui_window;
+    HWND                event_window;
 } activeDS;
 
 TW_UINT16 DSM_twCC DECLSPEC_HIDDEN;             /* current condition code of Source Manager */
@@ -62,5 +72,9 @@ extern TW_UINT16 TWAIN_OpenDSM
            (pTW_IDENTITY pOrigin, TW_MEMREF pData) DECLSPEC_HIDDEN;
 extern TW_UINT16 TWAIN_GetDSMStatus
            (pTW_IDENTITY pOrigin, TW_MEMREF pData) DECLSPEC_HIDDEN;
+extern TW_UINT16 TWAIN_ControlNull
+           (pTW_IDENTITY pOrigin, pTW_IDENTITY pDest, activeDS *pSource, TW_UINT16 MSG, TW_MEMREF pData) DECLSPEC_HIDDEN;
+extern TW_UINT16 TWAIN_ProcessEvent
+           (pTW_IDENTITY pOrigin, activeDS *pSource, TW_MEMREF pData) DECLSPEC_HIDDEN;
 
 #endif




More information about the wine-cvs mailing list