| /* |
| * Implementation of the Printer User Interface Dialogs |
| * |
| * 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 |
| * 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 <stdarg.h> |
| |
| #define COBJMACROS |
| #define NONAMELESSUNION |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "wingdi.h" |
| #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); |
| |
| /* ################################# */ |
| |
| /* Must be in order with OPT_* */ |
| static const WCHAR optionsW[OPT_MAX+1]={'a','b','c','f','h','j','l','m','n','t','r','v',0}; |
| |
| /* Must be in order with FLAG_* */ |
| static const WCHAR flagsW[FLAG_MAX+1]={'q','w','y','z','Z',0}; |
| |
| |
| /* ################################ |
| * 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; |
| DWORD index; |
| WCHAR txtW[2]; |
| WCHAR c; |
| |
| |
| c = get_next_wchar(cx, TRUE); |
| txtW[1] = '\0'; |
| |
| while (c) |
| { |
| |
| while ( (c == ' ') || (c == '\t')) |
| { |
| c = get_next_wchar(cx, TRUE); |
| } |
| txtW[0] = c; |
| |
| 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 ) |
| { |
| txtW[0] = c; |
| ptr = strchrW(optionsW, c); |
| if (ptr) { |
| index = ptr - optionsW; |
| cx->options[index] = get_next_wstr(cx); |
| TRACE(" opt: %s %s\n", debugstr_w(txtW), debugstr_w(cx->options[index])); |
| c = 0; |
| } |
| else |
| { |
| ptr = strchrW(flagsW, c); |
| if (ptr) { |
| index = ptr - flagsW; |
| cx->flags[index] = TRUE; |
| TRACE("flag: %s\n", debugstr_w(txtW)); |
| } |
| else |
| { |
| cx->command = c; |
| cx->subcommand = '\0'; |
| TRACE(" cmd: %s\n", debugstr_w(txtW)); |
| } |
| |
| /* help has priority over all commands */ |
| if (c == '?') { |
| return TRUE; |
| } |
| |
| c = get_next_wchar(cx, FALSE); |
| |
| /* Some commands use two wchar */ |
| if ((cx->command == 'd') || (cx->command == 'g') || (cx->command == 'i') || |
| (cx->command == 'S') || (cx->command == 'X') ){ |
| cx->subcommand = c; |
| txtW[0] = c; |
| TRACE(" sub: %s\n", debugstr_w(txtW)); |
| 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')) { |
| |
| /* the actual WCHAR is the start from the extra Parameter */ |
| cx->pNextCharW--; |
| TRACE("%d extra Parameter, starting with %s\n", 1 + (cx->argc - cx->next_arg), debugstr_w(cx->pNextCharW)); |
| return TRUE; |
| } |
| FIXME("0x%x: %s is unknown\n", c, debugstr_wn(&c, 1)); |
| return FALSE; |
| } |
| |
| } |
| return TRUE; |
| } |
| |
| /***************************************************** |
| * DllMain |
| */ |
| BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) |
| { |
| TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved); |
| |
| switch(fdwReason) |
| { |
| case DLL_WINE_PREATTACH: |
| return FALSE; /* prefer native version */ |
| |
| case DLL_PROCESS_ATTACH: |
| DisableThreadLibraryCalls( hinstDLL ); |
| break; |
| } |
| return TRUE; |
| } |
| |
| |
| /***************************************************** |
| * PrintUIEntryW [printui.@] |
| * Commandline-Interface for using printui.dll with rundll32.exe |
| * |
| */ |
| void WINAPI PrintUIEntryW(HWND hWnd, HINSTANCE hInst, LPCWSTR pCommand, DWORD 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])) { |
| /* result is allocated with GlobalAlloc() */ |
| 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[3]; |
| txtW[0] = cx.command; |
| txtW[1] = cx.subcommand; |
| txtW[2] = '\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); |
| |
| } |