localui: Implement AddPortUI

Detlef Riekenberg wine.dev at web.de
Mon Apr 30 08:02:34 CDT 2007


localui: Implement AddPortUI


After the next Patch (ConfigurePortUI for LPT),
we are ready to add localization and
localui is ready to drop:

--- cut --
        case DLL_WINE_PREATTACH:
            return FALSE;           /* prefer native version */
--- cut --

:-)


My Patches for the tests with the CBT-Hook need some more 
polish to handle the Sub-Dialogs from AddPortUI.


-- 
 
By by ... Detlef

-------------- next part --------------
>From c1f74855a6b89919ab0189401f6dba0a33c5156f Mon Sep 17 00:00:00 2001
From: Detlef Riekenberg <wine.dev at web.de>
Date: Mon, 30 Apr 2007 14:38:24 +0200
Subject: [PATCH] localui: Implement AddPortUI
---
 dlls/localui/Makefile.in |    2 
 dlls/localui/localui.c   |  212 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/localui/localui.h   |    7 ++
 dlls/localui/localui.rc  |    1 
 dlls/localui/ui_En.rc    |   14 +++
 5 files changed, 233 insertions(+), 3 deletions(-)

diff --git a/dlls/localui/Makefile.in b/dlls/localui/Makefile.in
index 6a43906..4a99fd9 100644
--- a/dlls/localui/Makefile.in
+++ b/dlls/localui/Makefile.in
@@ -3,7 +3,7 @@ TOPOBJDIR = ../..
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = localui.dll
-IMPORTS   = winspool user32 kernel32
+IMPORTS   = winspool user32 kernel32 msvcrt
 
 C_SRCS = \
 	localui.c
diff --git a/dlls/localui/localui.c b/dlls/localui/localui.c
index 133fd60..27e1875 100644
--- a/dlls/localui/localui.c
+++ b/dlls/localui/localui.c
@@ -41,10 +41,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(localui);
 
 static HINSTANCE LOCALUI_hInstance;
 
+static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0};
 static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0};
 static const WCHAR cmd_GetDefaultCommConfigW[] = {'G','e','t',
                                     'D','e','f','a','u','l','t',
                                     'C','o','m','m','C','o','n','f','i','g',0};
+static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0};
 static const WCHAR cmd_SetDefaultCommConfigW[] = {'S','e','t',
                                     'D','e','f','a','u','l','t',
                                     'C','o','m','m','C','o','n','f','i','g',0};
@@ -55,8 +57,15 @@ static const WCHAR portname_FILE[] = {'F
 static const WCHAR portname_CUPS[] = {'C','U','P','S',':',0};
 static const WCHAR portname_LPR[]  = {'L','P','R',':',0};
 
+static const WCHAR XcvMonitorW[] = {',','X','c','v','M','o','n','i','t','o','r',' ',0};
 static const WCHAR XcvPortW[] = {',','X','c','v','P','o','r','t',' ',0};
 
+/*****************************************************/
+
+typedef struct tag_addportui_t {
+    LPWSTR  portname;
+    HANDLE  hXcv;
+} addportui_t; 
 
 /*****************************************************
  *   strdupWW [internal]
@@ -123,6 +132,58 @@ static BOOL dlg_configure_com(HANDLE hXc
 }
 
 /******************************************************************
+ *  dlg_port_already_exists [internal]
+ */
+
+static void dlg_port_already_exists(HWND hWnd, LPCWSTR portname)
+{
+    WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
+    WCHAR res_PortExistsW[IDS_PORTEXISTS_MAXLEN];
+    LPWSTR  message;
+    DWORD   len;
+
+    res_PortW[0] = '\0';
+    res_PortExistsW[0] = '\0';
+    LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN);
+    LoadStringW(LOCALUI_hInstance, IDS_PORTEXISTS, res_PortExistsW, IDS_PORTEXISTS_MAXLEN);
+
+    len = lstrlenW(portname) + IDS_PORTEXISTS_MAXLEN + 1;
+    message = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+    if (message) {
+        message[0] = '\0';
+        snprintfW(message, len, res_PortExistsW, portname);
+        MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR);
+        HeapFree(GetProcessHeap(), 0, message);
+    }
+}
+
+/******************************************************************
+ *  dlg_invalid_portname [internal]
+ */
+
+static void dlg_invalid_portname(HWND hWnd, LPCWSTR portname)
+{
+    WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
+    WCHAR res_InvalidNameW[IDS_INVALIDNAME_MAXLEN];
+    LPWSTR  message;
+    DWORD   len;
+
+    res_PortW[0] = '\0';
+    res_InvalidNameW[0] = '\0';
+    LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN);
+    LoadStringW(LOCALUI_hInstance, IDS_INVALIDNAME, res_InvalidNameW, IDS_INVALIDNAME_MAXLEN);
+
+    len = lstrlenW(portname) + IDS_INVALIDNAME_MAXLEN;
+    message = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+    if (message) {
+        message[0] = '\0';
+        snprintfW(message, len, res_InvalidNameW, portname);
+        MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR);
+        HeapFree(GetProcessHeap(), 0, message);
+    }
+}
+
+/******************************************************************
  * display the Dialog "Nothing to configure"
  *
  */
@@ -140,6 +201,96 @@ static void dlg_nothingtoconfig(HWND hWn
     MessageBoxW(hWnd, res_nothingW, res_PortW, MB_OK | MB_ICONINFORMATION);
 }
 
+/******************************************************************
+ *  dlg_win32error [internal]
+ */
+
+static void dlg_win32error(HWND hWnd, DWORD lasterror)
+{
+    WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
+    LPWSTR  message = NULL;
+    DWORD   res;
+
+    res_PortW[0] = '\0';
+    LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN);
+
+
+    res = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                        NULL, lasterror, 0, (LPWSTR) &message, 0, NULL);
+
+    if (res > 0) {
+        MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR);
+        LocalFree(message);
+    }
+}
+
+/*****************************************************************************
+ *
+ */
+
+INT_PTR CALLBACK dlgproc_addport(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+    addportui_t * data;
+    DWORD   status;
+    DWORD   dummy;
+    DWORD   len;
+    DWORD   res;
+
+    switch(msg)
+    {
+    case WM_INITDIALOG:
+        SetWindowLongPtrW(hwnd, DWLP_USER, lparam);
+        return TRUE;
+
+    case WM_COMMAND:
+        if (wparam == MAKEWPARAM(IDOK, BN_CLICKED))
+        {
+            data = (addportui_t *) GetWindowLongPtrW(hwnd, DWLP_USER);
+            /* length in WCHAR, without the '\0' */
+            len = SendDlgItemMessageW(hwnd, ADDPORT_EDIT, WM_GETTEXTLENGTH, 0, 0);
+            data->portname = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
+
+            if (!data->portname) {
+                EndDialog(hwnd, FALSE);
+                return TRUE;
+            }
+            /* length is in WCHAR, including the '\0' */
+            GetDlgItemTextW(hwnd, ADDPORT_EDIT, data->portname, len + 1);
+            status = ERROR_SUCCESS;
+            res = XcvDataW( data->hXcv, cmd_PortIsValidW, (PBYTE) data->portname,
+                            (lstrlenW(data->portname) + 1) * sizeof(WCHAR),
+                            (PBYTE) &dummy, 0, &len, &status);
+
+            TRACE("got %u with status %u\n", res, status);
+            if (res && (status == ERROR_SUCCESS)) {
+                /* The caller must free data->portname */
+                EndDialog(hwnd, TRUE);
+                return TRUE;
+            }
+
+            if (res && (status == ERROR_INVALID_NAME)) {
+                dlg_invalid_portname(hwnd, data->portname);
+                HeapFree(GetProcessHeap(), 0, data->portname);
+                data->portname = NULL;
+                return TRUE;
+            }
+
+            dlg_win32error(hwnd, status);
+            HeapFree(GetProcessHeap(), 0, data->portname);
+            data->portname = NULL;
+            return TRUE;
+        }
+
+        if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED))
+        {
+            EndDialog(hwnd, FALSE);
+            return TRUE;
+        }
+        return FALSE;
+    }
+    return FALSE;
+}
+
 /*****************************************************
  * get_type_from_name (internal)
  *
@@ -224,11 +375,68 @@ static BOOL open_monitor_by_name(LPCWSTR
  *  Success: TRUE
  *  Failure: FALSE
  *
+ * NOTES
+ * The caller must free the buffer (returned in ppPortName) with GlobalFree().
+ * Native localui.dll failed with ERROR_INVALID_PARAMETER, when the user tried
+ * to add a Port, that start with "COM" or "LPT".
+ *
  */
 static BOOL WINAPI localui_AddPortUI(PCWSTR pName, HWND hWnd, PCWSTR pMonitorName, PWSTR *ppPortName)
 {
-    FIXME("(%s, %p, %s, %p) stub\n", debugstr_w(pName), hWnd, debugstr_w(pMonitorName), ppPortName);
-    return TRUE;
+    addportui_t data;
+    HANDLE  hXcv;
+    LPWSTR  ptr = NULL;
+    DWORD   needed;
+    DWORD   dummy;
+    DWORD   status;
+    DWORD   res = FALSE;
+
+    TRACE(  "(%s, %p, %s, %p) (*ppPortName: %p)\n", debugstr_w(pName), hWnd, 
+            debugstr_w(pMonitorName), ppPortName, ppPortName ? *ppPortName : NULL);
+
+    if (open_monitor_by_name(XcvMonitorW, pMonitorName, &hXcv)) {
+
+        ZeroMemory(&data, sizeof(addportui_t));
+        data.hXcv = hXcv;
+        res = DialogBoxParamW(LOCALUI_hInstance, MAKEINTRESOURCEW(ADDPORT_DIALOG), hWnd,
+                               dlgproc_addport, (LPARAM) &data);
+
+        TRACE("got %u with %u for %s\n", res, GetLastError(), debugstr_w(data.portname));
+
+        if (ppPortName) *ppPortName = NULL;
+
+        if (res) {
+            res = XcvDataW(hXcv, cmd_AddPortW, (PBYTE) data.portname,
+                            (lstrlenW(data.portname)+1) * sizeof(WCHAR),
+                            (PBYTE) &dummy, 0, &needed, &status);
+
+            TRACE("got %u with status %u\n", res, status);
+            if (res && (status == ERROR_SUCCESS)) {
+                /* Native localui uses GlobalAlloc also. 
+                   The caller must GlobalFree the buffer */
+                ptr = GlobalAlloc(GPTR, (lstrlenW(data.portname)+1) * sizeof(WCHAR));
+                if (ptr) {
+                    lstrcpyW(ptr, data.portname);
+                    if (ppPortName) *ppPortName = ptr;
+                }
+            }
+
+            if (res && (status == ERROR_ALREADY_EXISTS)) {
+                dlg_port_already_exists(hWnd, data.portname);
+                /* Native localui also return "TRUE" from AddPortUI in this case */
+            }
+
+            HeapFree(GetProcessHeap(), 0, data.portname);
+        }
+        else
+        {
+            SetLastError(ERROR_CANCELLED);
+        }
+        ClosePrinter(hXcv);
+    }
+
+    TRACE("=> %u with %u\n", res, GetLastError());
+    return res;
 }
 
 
diff --git a/dlls/localui/localui.h b/dlls/localui/localui.h
index 581922a..599ef58 100644
--- a/dlls/localui/localui.h
+++ b/dlls/localui/localui.h
@@ -23,11 +23,18 @@ #define __WINE_LOCALUI__
 
 
 /* ## Resource-ID ## */
+#define ADDPORT_DIALOG  100
+#define ADDPORT_EDIT    201
+
 #define IDS_LOCALPORT       300
+#define IDS_INVALIDNAME     301
+#define IDS_PORTEXISTS      302
 #define IDS_NOTHINGTOCONFIG 303
 
 /* ## Reserved memorysize for the strings (in WCHAR) ## */
 #define IDS_LOCALPORT_MAXLEN 32
+#define IDS_INVALIDNAME_MAXLEN 48
+#define IDS_PORTEXISTS_MAXLEN  48
 #define IDS_NOTHINGTOCONFIG_MAXLEN 80
 
 /* ## Type of Ports ## */
diff --git a/dlls/localui/localui.rc b/dlls/localui/localui.rc
index 23a6b95..ff24209 100644
--- a/dlls/localui/localui.rc
+++ b/dlls/localui/localui.rc
@@ -21,6 +21,7 @@
 
 #include "windef.h"
 #include "winbase.h"
+#include "winuser.h"
 #include "winver.h"
 #include "localui.h"
 
diff --git a/dlls/localui/ui_En.rc b/dlls/localui/ui_En.rc
index 7b687f1..8a1e5b9 100644
--- a/dlls/localui/ui_En.rc
+++ b/dlls/localui/ui_En.rc
@@ -20,8 +20,22 @@
 
 LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
 
+ADDPORT_DIALOG DIALOG LOADONCALL MOVEABLE DISCARDABLE 6, 18, 245, 47
+STYLE DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFONT | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION
+CAPTION "Add a Local Port"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    LTEXT "&Enter the port name to add:", -1, 7, 13, 194, 13, WS_VISIBLE
+    EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL
+    DEFPUSHBUTTON "OK", IDOK, 199, 10, 40, 14, WS_VISIBLE
+    PUSHBUTTON "Cancel", IDCANCEL, 199, 27, 40, 14, WS_VISIBLE
+END
+
+
 STRINGTABLE DISCARDABLE
 {
     IDS_LOCALPORT "Local Port"
+    IDS_INVALIDNAME "'%s' is not a valid port name"
+    IDS_PORTEXISTS "Port %s already exists"
     IDS_NOTHINGTOCONFIG "This port has no options to configure"
 }
-- 
1.4.1



More information about the wine-patches mailing list