Signed-off-by: Vincent Povirk <vincent(a)codeweavers.com>
---
dlls/twain_32/Makefile.in | 2 +
dlls/twain_32/dsm_ctrl.c | 114 ++++++++++++++++++++++++++++++++++++++-----
dlls/twain_32/resource.h | 25 ++++++++++
dlls/twain_32/twain.rc | 34 +++++++++++++
dlls/twain_32/twain32_main.c | 18 +++++++
dlls/twain_32/twain_i.h | 2 +
6 files changed, 182 insertions(+), 13 deletions(-)
create mode 100644 dlls/twain_32/resource.h
create mode 100644 dlls/twain_32/twain.rc
diff --git a/dlls/twain_32/Makefile.in b/dlls/twain_32/Makefile.in
index cadaf8081d8..c82b5a74453 100644
--- a/dlls/twain_32/Makefile.in
+++ b/dlls/twain_32/Makefile.in
@@ -4,3 +4,5 @@ IMPORTS = user32
C_SRCS = \
dsm_ctrl.c \
twain32_main.c
+
+RC_SRCS = twain.rc
diff --git a/dlls/twain_32/dsm_ctrl.c b/dlls/twain_32/dsm_ctrl.c
index 9b878676656..bfd0651cb46 100644
--- a/dlls/twain_32/dsm_ctrl.c
+++ b/dlls/twain_32/dsm_ctrl.c
@@ -30,6 +30,7 @@
#include "winuser.h"
#include "twain.h"
#include "twain_i.h"
+#include "resource.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(twain);
@@ -345,24 +346,111 @@ TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
return TWRC_SUCCESS;
}
+typedef struct {
+ pTW_IDENTITY origin;
+ pTW_IDENTITY result;
+} userselect_data;
+
+INT_PTR CALLBACK userselect_dlgproc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ userselect_data *data = (userselect_data*)lparam;
+ int i;
+ HWND sourcelist;
+ BOOL any_devices = FALSE;
+
+ SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)data);
+
+ sourcelist = GetDlgItem(hwnd, IDC_LISTSOURCE);
+
+ for (i=0; i<nrdevices; i++)
+ {
+ TW_IDENTITY *id = &devices[i].identity;
+ LRESULT index;
+
+ if ((id->SupportedGroups & data->origin->SupportedGroups) == 0)
+ continue;
+
+ index = SendMessageA(sourcelist, LB_ADDSTRING, 0, (LPARAM)id->ProductName);
+ SendMessageW(sourcelist, LB_SETITEMDATA, (WPARAM)index, (LPARAM)i);
+ any_devices = TRUE;
+ }
+
+ if (any_devices)
+ {
+ EnableWindow(GetDlgItem(hwnd, IDOK), TRUE);
+
+ /* FIXME: Select the supplied product name or default source. */
+ SendMessageW(sourcelist, LB_SETCURSEL, 0, 0);
+ }
+
+ return TRUE;
+ }
+ case WM_CLOSE:
+ EndDialog(hwnd, 0);
+ return TRUE;
+ case WM_COMMAND:
+ if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED))
+ {
+ EndDialog(hwnd, 0);
+ return TRUE;
+ }
+ else if (wparam == MAKEWPARAM(IDOK, BN_CLICKED) ||
+ wparam == MAKEWPARAM(IDC_LISTSOURCE, LBN_DBLCLK))
+ {
+ userselect_data *data = (userselect_data*)GetWindowLongPtrW(hwnd, DWLP_USER);
+ HWND sourcelist;
+ LRESULT index;
+
+ sourcelist = GetDlgItem(hwnd, IDC_LISTSOURCE);
+
+ index = SendMessageW(sourcelist, LB_GETCURSEL, 0, 0);
+
+ if (index == LB_ERR)
+ return TRUE;
+
+ index = SendMessageW(sourcelist, LB_GETITEMDATA, (WPARAM)index, 0);
+
+ *data->result = devices[index].identity;
+
+ /* FIXME: Save this as the default source */
+
+ EndDialog(hwnd, 1);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
/* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData)
{
- pTW_IDENTITY selected = (pTW_IDENTITY)pData;
+ userselect_data param = {pOrigin, pData};
+ HWND parent = DSM_parent;
- TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT SupportedGroups=0x%x ProductName=%s\n",
- selected->SupportedGroups, wine_dbgstr_a(selected->ProductName));
+ TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT SupportedGroups=0x%x ProductName=%s\n",
+ pOrigin->SupportedGroups, wine_dbgstr_a(param.result->ProductName));
- twain_autodetect();
- if (!nrdevices) {
- TRACE("<-- TWRC_FAILURE\n");
- DSM_twCC = TWCC_OPERATIONERROR;
- return TWRC_FAILURE;
- }
- *selected = devices[0].identity;
- TRACE("<-- %s\n", wine_dbgstr_a(selected->ProductName));
- DSM_twCC = TWCC_SUCCESS;
- return TWRC_SUCCESS;
+ twain_autodetect();
+
+ if (!IsWindow(parent))
+ parent = NULL;
+
+ if (DialogBoxParamW(DSM_hinstance, MAKEINTRESOURCEW(DLG_USERSELECT),
+ parent, userselect_dlgproc, (LPARAM)¶m) == 0)
+ {
+ TRACE("canceled\n");
+ DSM_twCC = TWCC_SUCCESS;
+ return TWRC_CANCEL;
+ }
+
+ TRACE("<-- %s\n", wine_dbgstr_a(param.result->ProductName));
+ DSM_twCC = TWCC_SUCCESS;
+ return TWRC_SUCCESS;
}
/* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
diff --git a/dlls/twain_32/resource.h b/dlls/twain_32/resource.h
new file mode 100644
index 00000000000..366f52f181c
--- /dev/null
+++ b/dlls/twain_32/resource.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017 Vincent Povirk for CodeWeavers
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <windef.h>
+#include <winuser.h>
+
+#define DLG_USERSELECT 1
+
+#define IDC_LISTSOURCE 1001
+
diff --git a/dlls/twain_32/twain.rc b/dlls/twain_32/twain.rc
new file mode 100644
index 00000000000..2c5939308d5
--- /dev/null
+++ b/dlls/twain_32/twain.rc
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017 Vincent Povirk for CodeWeavers
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "resource.h"
+
+#pragma makedep po
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+DLG_USERSELECT DIALOG 0, 0, 140, 140
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_NOIDLEMSG
+FONT 8, "MS Shell Dlg"
+CAPTION "Select Source"
+{
+ LISTBOX IDC_LISTSOURCE, 7, 7, 126, 104
+ DEFPUSHBUTTON "OK", IDOK, 29, 118, 50, 15, BS_DEFPUSHBUTTON|WS_TABSTOP|WS_DISABLED
+ PUSHBUTTON "Cancel", IDCANCEL, 83, 118, 50, 15
+}
+
diff --git a/dlls/twain_32/twain32_main.c b/dlls/twain_32/twain32_main.c
index d1977b4d75f..016680b96eb 100644
--- a/dlls/twain_32/twain32_main.c
+++ b/dlls/twain_32/twain32_main.c
@@ -31,6 +31,24 @@
WINE_DEFAULT_DEBUG_CHANNEL(twain);
+extern HINSTANCE DSM_hinstance;
+
+BOOL WINAPI DllMain (HINSTANCE hinstance, DWORD reason, LPVOID reserved)
+{
+ TRACE("%p,%x,%p\n", hinstance, reason, reserved);
+
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hinstance);
+ DSM_hinstance = hinstance;
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
/* A helper function that looks up a destination identity in the active
source list */
static activeDS *TWAIN_LookupSource (const TW_IDENTITY *pDest)
diff --git a/dlls/twain_32/twain_i.h b/dlls/twain_32/twain_i.h
index f46999c6fa1..4d33135344e 100644
--- a/dlls/twain_32/twain_i.h
+++ b/dlls/twain_32/twain_i.h
@@ -53,6 +53,8 @@ TW_UINT16 DSM_twCC DECLSPEC_HIDDEN; /* current condition code of Sou
activeDS *activeSources DECLSPEC_HIDDEN; /* list of active data sources */
+HINSTANCE DSM_hinstance DECLSPEC_HIDDEN;
+
/* Implementation of operation triplets (From Application to Source Manager) */
extern TW_UINT16 TWAIN_CloseDS
(pTW_IDENTITY pOrigin, TW_MEMREF pData) DECLSPEC_HIDDEN;
--
2.11.0