printui: Parse args in PrintUIEntryW

Detlef Riekenberg wine.dev at web.de
Wed Jul 4 15:47:48 CDT 2007


I did a lot of tests with rundll32 and used the results to build
a Parser on top of CommandLineToArgvW


printui: Parse args in PrintUIEntryW



-- 
 
By by ... Detlef

-------------- next part --------------
>From 87657e3dc83768b71ba292f319c9c5603d70b8bd Mon Sep 17 00:00:00 2001
From: Detlef Riekenberg <wine.dev at web.de>
Date: Wed, 4 Jul 2007 22:45:26 +0200
Subject: [PATCH] printui: Parse args in PrintUIEntryW
---
 dlls/printui/Makefile.in       |    2 
 dlls/printui/printui.c         |  260 ++++++++++++++++++++++++++++++++++++++++
 dlls/printui/printui_private.h |   54 ++++++++
 3 files changed, 312 insertions(+), 4 deletions(-)

diff --git a/dlls/printui/Makefile.in b/dlls/printui/Makefile.in
index 2cb44b9..65aa7f6 100644
--- a/dlls/printui/Makefile.in
+++ b/dlls/printui/Makefile.in
@@ -3,7 +3,7 @@ TOPOBJDIR = ../..
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = printui.dll
-IMPORTS   = kernel32
+IMPORTS   = kernel32 shell32
 
 C_SRCS = \
 	printui.c
diff --git a/dlls/printui/printui.c b/dlls/printui/printui.c
index 06cbaa2..f54f17d 100644
--- a/dlls/printui/printui.c
+++ b/dlls/printui/printui.c
@@ -1,7 +1,7 @@
 /*
  * Implementation of the Printer User Interface Dialogs
  *
- * Copyright 2006 Detlef Riekenberg
+ * Copyright 2006-2007 Detlef Riekenberg
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,14 +30,236 @@ #include "winuser.h"
 #include "winreg.h"
 #include "winver.h"
 #include "winnls.h"
+#include "shellapi.h"
 
 #include "wine/unicode.h"
 #include "wine/debug.h"
+#include "printui_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(printui);
 
 HINSTANCE PRINTUI_hInstance = NULL;
 
+/* ################################
+ * get_next_wstr() [Internal]
+ *
+ * Get the next WSTR, when available
+ *
+ */
+
+static LPWSTR get_next_wstr(context_t * cx)
+{
+    LPWSTR  ptr;
+
+    ptr = cx->pNextCharW;
+    if (ptr && ptr[0]) {
+        cx->pNextCharW = NULL;
+        return ptr;
+    }
+
+    /* Get the next Parameter, when available */
+    if (cx->next_arg < cx->argc) {
+        ptr = cx->argv[cx->next_arg];
+        cx->next_arg++;
+        cx->pNextCharW = NULL;
+        return ptr;
+    }
+    return NULL;
+}
+
+
+/* ################################
+ * get_next_wchar() [Internal]
+ *
+ * Get the next WCHAR from the Commandline or from the File (@ Filename)
+ *
+ * ToDo: Support Parameter from a File ( "@Filename" )
+ *
+ */
+
+static WCHAR get_next_wchar(context_t * cx, BOOL use_next_parameter)
+{
+    WCHAR   c;
+
+    /* Try the next WCHAR in the actual Parameter */
+    if (cx->pNextCharW) {
+        c = *cx->pNextCharW;
+        if (c) {
+            cx->pNextCharW++;
+            return c;
+        }
+        /* We reached the end of the Parameter */
+        cx->pNextCharW = NULL;
+    }
+
+    /* Get the next Parameter, when available and allowed */
+    if ((cx->pNextCharW == NULL) && (cx->next_arg < cx->argc) && (use_next_parameter)) {
+        cx->pNextCharW = cx->argv[cx->next_arg];
+        cx->next_arg++;
+    }
+
+    if (cx->pNextCharW) {
+        c = *cx->pNextCharW;
+        if (c) {
+            cx->pNextCharW++;
+        }
+        else
+        {
+            /* We reached the end of the Parameter */
+            cx->pNextCharW = NULL;
+        }
+        return c;
+    }
+    return '\0';
+}
+
+/* ################################ */
+static BOOL parse_rundll(context_t * cx)
+{
+
+    LPWSTR  ptr;
+    WCHAR   c;
+
+
+    c = get_next_wchar(cx, TRUE);
+
+    while (c)
+    {
+        while ( (c == ' ') || (c == '\t'))
+        {
+            c = get_next_wchar(cx, TRUE);
+        }
+
+        if (c == '@') {
+            /* read commands from a File */
+            ptr = get_next_wstr(cx);
+            FIXME("redir not supported: %s\n", debugstr_w(ptr));
+            return FALSE;
+        }
+        else if (c == '/') {
+            c = get_next_wchar(cx, FALSE);
+            while ( c )
+            {
+                switch (c)
+                {
+                case 'a':
+                    cx->opt_a = get_next_wstr(cx);
+                    TRACE("opt_a: %s\n", debugstr_w(cx->opt_a));
+                    c = '\0';
+                    break;
+
+                case 'b':
+                    cx->opt_b = get_next_wstr(cx);
+                    TRACE("opt_b: %s\n", debugstr_w(cx->opt_b));
+                    c = '\0';
+                    break;
+
+                case 'c':
+                    cx->opt_c = get_next_wstr(cx);
+                    TRACE("opt_c: %s\n", debugstr_w(cx->opt_c));
+                    c = '\0';
+                    break;
+
+                case 'f':
+                    cx->opt_f = get_next_wstr(cx);
+                    TRACE("opt_f: %s\n", debugstr_w(cx->opt_f));
+                    c = '\0';
+                    break;
+
+                case 'h':
+                    cx->opt_h = get_next_wstr(cx);
+                    TRACE("opt_h: %s\n", debugstr_w(cx->opt_h));
+                    c = '\0';
+                    break;
+
+                case 'j':
+                    cx->opt_j = get_next_wstr(cx);
+                    TRACE("opt_j: %s\n", debugstr_w(cx->opt_j));
+                    c = '\0';
+                    break;
+
+                case 'l':
+                    cx->opt_l = get_next_wstr(cx);
+                    TRACE("opt_l: %s\n", debugstr_w(cx->opt_l));
+                    c = '\0';
+                    break;
+
+                case 'm':
+                    cx->opt_m = get_next_wstr(cx);
+                    TRACE("opt_m: %s\n", debugstr_w(cx->opt_m));
+                    c = '\0';
+                    break;
+
+                case 'n':
+                    cx->opt_n = get_next_wstr(cx);
+                    TRACE("opt_n: %s\n", debugstr_w(cx->opt_n));
+                    c = '\0';
+                    break;
+
+                case 'r':
+                    cx->opt_r = get_next_wstr(cx);
+                    TRACE("opt_r: %s\n", debugstr_w(cx->opt_r));
+                    c = '\0';
+                    break;
+
+                case 't':
+                    cx->opt_t = get_next_wstr(cx);
+                    TRACE("opt_t: %s\n", debugstr_w(cx->opt_t));
+                    c = '\0';
+                    break;
+
+                case 'v':
+                    cx->opt_v = get_next_wstr(cx);
+                    TRACE("opt_v: %s\n", debugstr_w(cx->opt_v));
+                    c = '\0';
+                    break;
+
+
+                default:
+                    if (c == 'q') {
+                        cx->quiet = TRUE;
+                    }
+                    else
+                    {
+                        cx->command = c;
+                        cx->subcommand = '\0';
+                    }
+                    TRACE("cmd__: %c\n", (CHAR) c);
+
+                    /* help has priority over all commands */
+                    if (c == '?') {
+                        return TRUE;
+                    }
+
+
+                    c = get_next_wchar(cx, FALSE);
+                    if ((cx->command == 'd') || (cx->command == 'g') || (cx->command == 'i') ||
+                        (cx->command == 'S') || (cx->command == 'X') ){
+                        cx->subcommand = c;
+                        c = get_next_wchar(cx, FALSE);
+                    }
+                }
+            }
+            c = get_next_wchar(cx, TRUE);
+
+        }
+        else
+        {
+            /* The commands 'S' and 'X' have additional Parameter */
+            if ((cx->command == 'S') || (cx->command == 'X')) {
+                /* unget the WCHAR */
+                cx->pNextCharW--;
+                TRACE("%d extra Parameter, starting with %s\n", 1 + (cx->argc - cx->next_arg), debugstr_w(cx->pNextCharW));
+                return TRUE;
+            }
+            TRACE("bad code 0x%x: %c\n", c, (CHAR) c);
+            return FALSE;
+        }
+
+    }
+    return TRUE;
+}
+
 /*****************************************************
  *      DllMain
  */
@@ -58,7 +280,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, 
     return TRUE;
 }
 
-
 /*****************************************************
  *  PrintUIEntryW                [printui.@]
  *  Commandline-Interface for using printui.dll with rundll32.exe
@@ -66,5 +287,38 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, 
  */
 void WINAPI PrintUIEntryW(HWND hWnd, HINSTANCE hInst, LPCWSTR pCommand, DWORD nCmdShow)
 {
-    FIXME("(%p, %p, %s, 0x%x) stub\n", hWnd, hInst, debugstr_w(pCommand), nCmdShow);
+    context_t cx;
+    BOOL  res = FALSE;
+
+    TRACE("(%p, %p, %s, 0x%x)\n", hWnd, hInst, debugstr_w(pCommand), nCmdShow);
+
+    memset(&cx, 0, sizeof(context_t));
+    cx.hWnd = hWnd;
+    cx.nCmdShow = nCmdShow;
+
+    if ((pCommand) && (pCommand[0])) {
+        cx.argv = CommandLineToArgvW(pCommand, &cx.argc);
+        TRACE("got %d args at %p\n", cx.argc, cx.argv);
+
+        res = parse_rundll(&cx);
+    }
+
+    if (res && cx.command) {
+        switch (cx.command)
+        {
+
+            default:
+            {
+                WCHAR txtW[] = {cx.command, cx.subcommand, 0};
+                FIXME("command not implemented: %s\n", debugstr_w(txtW));
+            }
+        }
+    }
+
+    if ((res == FALSE) || (cx.command == '\0')) {
+        FIXME("dialog: Printer / The operation was not successful\n");
+    }
+
+    GlobalFree(cx.argv);
+
 }
diff --git a/dlls/printui/printui_private.h b/dlls/printui/printui_private.h
new file mode 100644
index 0000000..e049255
--- /dev/null
+++ b/dlls/printui/printui_private.h
@@ -0,0 +1,54 @@
+/*
+ * Implementation of the Printer User Interface Dialogs: private Header
+ *
+ * Copyright 2007 Detlef Riekenberg
+ *
+ * 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
+ */
+
+#ifndef __WINE_PRINTUI_PRIVATE__
+#define __WINE_PRINTUI_PRIVATE__
+
+
+typedef struct tag_context {
+    HWND    hWnd;
+    DWORD   nCmdShow;
+    LPWSTR  * argv;
+    LPWSTR  pNextCharW;
+    int     argc;
+    int     next_arg;
+    LPWSTR  opt_a;
+    LPWSTR  opt_b;
+    LPWSTR  opt_c;
+    LPWSTR  opt_f;
+    LPWSTR  opt_h;
+    LPWSTR  opt_j;
+    LPWSTR  opt_l;
+    LPWSTR  opt_m;
+    LPWSTR  opt_n;
+    LPWSTR  opt_r;
+    LPWSTR  opt_t;
+    LPWSTR  opt_v;
+    WCHAR   command;
+    WCHAR   subcommand;
+    BOOL    quiet;
+} context_t;
+
+
+/* ## DLL-wide Globals ## */
+extern HINSTANCE PRINTUI_hInstance;
+
+
+#endif
-- 
1.4.1



More information about the wine-patches mailing list