From: Bernd Herd codeberg@herdsoft.com
Since TWAIN version 2.0, applications are encouraged to use callbacks instead of window messages for communication. This commit implements the TRIPLET to set the callbacks and the call to those callbacks.
If an application does not use callbacks, the old PostMessage method is being used as before. --- dlls/twaindsm/dsm_ctrl.c | 54 ++++++++++++++++++++++++++++++++++-- dlls/twaindsm/twain32_main.c | 19 ++++++++++++- dlls/twaindsm/twain_i.h | 2 ++ include/twain.h | 23 +++++++++++++++ 4 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/dlls/twaindsm/dsm_ctrl.c b/dlls/twaindsm/dsm_ctrl.c index 8addc688188..d0a6a13c9a6 100644 --- a/dlls/twaindsm/dsm_ctrl.c +++ b/dlls/twaindsm/dsm_ctrl.c @@ -77,6 +77,7 @@ twain_add_onedriver(const WCHAR *dsname) { do { int i;
+ memset(&sourceId, 0, sizeof(sourceId)); sourceId.Id = DSM_sourceId; sourceId.ProtocolMajor = TWON_PROTOCOLMAJOR; sourceId.ProtocolMinor = TWON_PROTOCOLMINOR; @@ -188,12 +189,43 @@ TW_UINT16 TWAIN_ControlNull (pTW_IDENTITY pOrigin, pTW_IDENTITY pDest, activeDS
if (MSG != MSG_CLOSEDSREQ && MSG != MSG_DEVICEEVENT && - MSG != MSG_XFERREADY) + MSG != MSG_XFERREADY && + MSG != MSG_DEVICEEVENT) { DSM_twCC = TWCC_BADPROTOCOL; return TWRC_FAILURE; }
+ if (pSource && + pSource->registered_callback.CallBackProc) + { + static BOOL bProcessingCallback = FALSE; + TRACE("DG_CONTROL/DAT_NULL using callback\n"); + if (!bProcessingCallback) + { + TW_UINT16 twRC; + bProcessingCallback=TRUE; + twRC = ((DSMENTRYPROC) pSource->registered_callback.CallBackProc) + (pOrigin, + pDest, + DG_CONTROL, DAT_NULL, MSG, + (TW_MEMREF) pSource->registered_callback.RefCon); + bProcessingCallback=FALSE; + if (twRC != TWCC_SUCCESS) + { + DSM_twCC = TWCC_BADPROTOCOL; + } + return twRC; + } + else + { + ERR("Nested callback\n"); + DSM_twCC = TWCC_BADPROTOCOL; + return TWRC_FAILURE; + } + + } + message = HeapAlloc(GetProcessHeap(), 0, sizeof(*message)); if (!message) { @@ -377,7 +409,7 @@ TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData) } /* else use the first device */
/* the source is found in the device list */ - newSource = HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS)); + newSource = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (activeDS)); if (!newSource) { DSM_twCC = TWCC_LOWMEMORY; FIXME("Out of memory.\n"); @@ -640,3 +672,21 @@ TW_UINT16 TWAIN_GetEntrypoint(TW_ENTRYPOINT *pEntrypoint)
return twRC; } + + + +/** @brief DG_CONTROL/DAT_CALLBACK/MSG_REGISTER_CALLBACK and DG_CONTROL/DAT_CALLBACK2/MSG_REGISTER_CALLBACK + * @param pSource The data source to associate the callback to + * @param CallBackProc Address of a callback procedure defined by the application program + * @param RefCon Reference Constant as defined by the application program + * @return Twain result code, TWRC_SUCCESS on success + */ +TW_UINT16 TWAIN_RegisterCallback(activeDS *pSource, TW_MEMREF *CallBackProc, UINT_PTR RefCon) +{ + TRACE("DG_CONTROL/DAT_CALLBACKx/MSG_REGISTER_CALLBACK\n"); + pSource->registered_callback.CallBackProc=CallBackProc; + pSource->registered_callback.RefCon=RefCon; + + DSM_twCC = TWCC_SUCCESS; + return TWRC_SUCCESS; +} diff --git a/dlls/twaindsm/twain32_main.c b/dlls/twaindsm/twain32_main.c index 8edbad40327..6f727c04747 100644 --- a/dlls/twaindsm/twain32_main.c +++ b/dlls/twaindsm/twain32_main.c @@ -187,7 +187,6 @@ DSM_Entry (pTW_IDENTITY pOrigin,
return TWAIN_ControlNull (pOrigin, pDest, pSource, MSG, pData); } - if (pDest) { activeDS *pSource = TWAIN_LookupSource (pDest); @@ -213,6 +212,24 @@ DSM_Entry (pTW_IDENTITY pOrigin, pSource->ui_window = ((TW_USERINTERFACE*)pData)->hParent; }
+ if (DG == DG_CONTROL && + MSG == MSG_REGISTER_CALLBACK && + (DAT == DAT_CALLBACK || DAT != DAT_CALLBACK2) && + pData != NULL) + { + if (DAT == DAT_CALLBACK) + { + TW_CALLBACK *pCallback = (TW_CALLBACK *) pData; + twRC = TWAIN_RegisterCallback(pSource, pCallback->CallBackProc, pCallback->RefCon); + } + else + { + TW_CALLBACK2 *pCallback = (TW_CALLBACK2 *) pData; + twRC = TWAIN_RegisterCallback(pSource, pCallback->CallBackProc, pCallback->RefCon); + } + return twRC; + } + DSM_twCC = TWCC_SUCCESS; TRACE("Forwarding %ld/%d/%d/%p to DS.\n", DG, DAT, MSG, pData); twRC = pSource->dsEntry(pOrigin, DG, DAT, MSG, pData); diff --git a/dlls/twaindsm/twain_i.h b/dlls/twaindsm/twain_i.h index a4aa37a5dbd..6858aac0908 100644 --- a/dlls/twaindsm/twain_i.h +++ b/dlls/twaindsm/twain_i.h @@ -43,6 +43,7 @@ typedef struct tagActiveDS struct list pending_messages; HWND ui_window; HWND event_window; + TW_CALLBACK2 registered_callback; } activeDS;
extern TW_UINT16 DSM_twCC; /* current condition code of Source Manager */ @@ -64,5 +65,6 @@ extern TW_UINT16 TWAIN_GetDSMStatus(pTW_IDENTITY pOrigin, TW_MEMREF pData); extern TW_UINT16 TWAIN_ControlNull(pTW_IDENTITY pOrigin, pTW_IDENTITY pDest, activeDS *pSource, TW_UINT16 MSG, TW_MEMREF pData); extern TW_UINT16 TWAIN_ProcessEvent(pTW_IDENTITY pOrigin, activeDS *pSource, TW_MEMREF pData); extern TW_UINT16 TWAIN_GetEntrypoint(TW_ENTRYPOINT *pEntrypoint); +extern TW_UINT16 TWAIN_RegisterCallback(activeDS *pSource, TW_MEMREF *CallBackProc, UINT_PTR RefCon);
#endif diff --git a/include/twain.h b/include/twain.h index 0dc65fcd8d0..bac51357012 100644 --- a/include/twain.h +++ b/include/twain.h @@ -81,6 +81,7 @@ #ifdef _MSWIN_ typedef HANDLE TW_HANDLE; typedef LPVOID TW_MEMREF; + typedef UINT_PTR TW_UINTPTR; typedef BYTE * HPBYTE; typedef void * HPVOID; #endif /* _MSWIN_ */ @@ -496,6 +497,22 @@ typedef struct { TW_INT16 VRefNum; } TW_SETUPAUDIOFILEXFER, FAR * pTW_SETUPAUDIOFILEXFER;
+ +/* Used with DG_CONTROL / DAT_CALLBACK / MSG_REGISTER_CALLBACK */ +typedef struct { + TW_MEMREF CallBackProc; + TW_UINT32 RefCon; + TW_INT16 Message; +} TW_CALLBACK, * pTW_CALLBACK; + +/* Used with DG_CONTROL / DAT_CALLBACK2 / MSG_REGISTER_CALLBACK */ +typedef struct { + TW_MEMREF CallBackProc; + TW_UINTPTR RefCon; + TW_INT16 Message; +} TW_CALLBACK2, * pTW_CALLBACK2; + + /**************************************************************************** * Generic Constants * ****************************************************************************/ @@ -1351,6 +1368,8 @@ typedef struct { #define DAT_DEVICEEVENT 0x000d /* TW_DEVICEEVENT */ #define DAT_FILESYSTEM 0x000e /* TW_FILESYSTEM */ #define DAT_PASSTHRU 0x000f /* TW_PASSTHRU */ +#define DAT_CALLBACK 0x0010 /* TW_CALLBACK */ +#define DAT_CALLBACK2 0x0012 /* TW_CALLBACK2 */
/* Data Argument Types for the DG_IMAGE Data Group. */ #define DAT_IMAGEINFO 0x0101 /* TW_IMAGEINFO */ @@ -1436,6 +1455,10 @@ typedef struct { /* Messages used with a pointer to a DAT_PASSTHRU structure */ #define MSG_PASSTHRU 0x0901
+/* Added 2.x */ +#define MSG_REGISTER_CALLBACK 0x0902 /* Used with DAT_CALLBACK/DAT_CALLBACK2*/ + + /**************************************************************************** * Capabilities * ****************************************************************************/