1 /* 2 * Implementation of the Printer User Interface Dialogs 3 * 4 * Copyright 2006-2007 Detlef Riekenberg 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 23 #define COBJMACROS 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "wingdi.h" 28 #include "winuser.h" 29 #include "winreg.h" 30 #include "winver.h" 31 #include "winnls.h" 32 #include "shellapi.h" 33 34 #include "wine/debug.h" 35 #include "printui_private.h" 36 37 WINE_DEFAULT_DEBUG_CHANNEL(printui); 38 39 /* ################################# */ 40 41 /* Must be in order with OPT_* */ 42 static const WCHAR optionsW[OPT_MAX+1]={'a','b','c','f','h','j','l','m','n','t','r','v',0}; 43 44 /* Must be in order with FLAG_* */ 45 static const WCHAR flagsW[FLAG_MAX+1]={'q','w','y','z','Z',0}; 46 47 48 /* ################################ 49 * get_next_wstr() [Internal] 50 * 51 * Get the next WSTR, when available 52 * 53 */ 54 55 static LPWSTR get_next_wstr(context_t * cx) 56 { 57 LPWSTR ptr; 58 59 ptr = cx->pNextCharW; 60 if (ptr && ptr[0]) { 61 cx->pNextCharW = NULL; 62 return ptr; 63 } 64 65 /* Get the next Parameter, when available */ 66 if (cx->next_arg < cx->argc) { 67 ptr = cx->argv[cx->next_arg]; 68 cx->next_arg++; 69 cx->pNextCharW = NULL; 70 return ptr; 71 } 72 return NULL; 73 } 74 75 76 /* ################################ 77 * get_next_wchar() [Internal] 78 * 79 * Get the next WCHAR from the Commandline or from the File (@ Filename) 80 * 81 * ToDo: Support Parameter from a File ( "@Filename" ) 82 * 83 */ 84 85 static WCHAR get_next_wchar(context_t * cx, BOOL use_next_parameter) 86 { 87 WCHAR c; 88 89 /* Try the next WCHAR in the actual Parameter */ 90 if (cx->pNextCharW) { 91 c = *cx->pNextCharW; 92 if (c) { 93 cx->pNextCharW++; 94 return c; 95 } 96 /* We reached the end of the Parameter */ 97 cx->pNextCharW = NULL; 98 } 99 100 /* Get the next Parameter, when available and allowed */ 101 if ((cx->pNextCharW == NULL) && (cx->next_arg < cx->argc) && (use_next_parameter)) { 102 cx->pNextCharW = cx->argv[cx->next_arg]; 103 cx->next_arg++; 104 } 105 106 if (cx->pNextCharW) { 107 c = *cx->pNextCharW; 108 if (c) { 109 cx->pNextCharW++; 110 } 111 else 112 { 113 /* We reached the end of the Parameter */ 114 cx->pNextCharW = NULL; 115 } 116 return c; 117 } 118 return '\0'; 119 } 120 121 /* ################################ */ 122 static BOOL parse_rundll(context_t * cx) 123 { 124 LPWSTR ptr; 125 DWORD index; 126 WCHAR txtW[2]; 127 WCHAR c; 128 129 130 c = get_next_wchar(cx, TRUE); 131 txtW[1] = '\0'; 132 133 while (c) 134 { 135 136 while ( (c == ' ') || (c == '\t')) 137 { 138 c = get_next_wchar(cx, TRUE); 139 } 140 txtW[0] = c; 141 142 if (c == '@') { 143 /* read commands from a File */ 144 ptr = get_next_wstr(cx); 145 FIXME("redir not supported: %s\n", debugstr_w(ptr)); 146 return FALSE; 147 } 148 else if (c == '/') { 149 c = get_next_wchar(cx, FALSE); 150 while ( c ) 151 { 152 txtW[0] = c; 153 ptr = wcschr(optionsW, c); 154 if (ptr) { 155 index = ptr - optionsW; 156 cx->options[index] = get_next_wstr(cx); 157 TRACE(" opt: %s %s\n", debugstr_w(txtW), debugstr_w(cx->options[index])); 158 c = 0; 159 } 160 else 161 { 162 ptr = wcschr(flagsW, c); 163 if (ptr) { 164 index = ptr - flagsW; 165 cx->flags[index] = TRUE; 166 TRACE("flag: %s\n", debugstr_w(txtW)); 167 } 168 else 169 { 170 cx->command = c; 171 cx->subcommand = '\0'; 172 TRACE(" cmd: %s\n", debugstr_w(txtW)); 173 } 174 175 /* help has priority over all commands */ 176 if (c == '?') { 177 return TRUE; 178 } 179 180 c = get_next_wchar(cx, FALSE); 181 182 /* Some commands use two wchar */ 183 if ((cx->command == 'd') || (cx->command == 'g') || (cx->command == 'i') || 184 (cx->command == 'S') || (cx->command == 'X') ){ 185 cx->subcommand = c; 186 txtW[0] = c; 187 TRACE(" sub: %s\n", debugstr_w(txtW)); 188 c = get_next_wchar(cx, FALSE); 189 } 190 } 191 } 192 c = get_next_wchar(cx, TRUE); 193 194 } 195 else 196 { 197 /* The commands 'S' and 'X' have additional Parameter */ 198 if ((cx->command == 'S') || (cx->command == 'X')) { 199 200 /* the actual WCHAR is the start from the extra Parameter */ 201 cx->pNextCharW--; 202 TRACE("%d extra Parameter, starting with %s\n", 1 + (cx->argc - cx->next_arg), debugstr_w(cx->pNextCharW)); 203 return TRUE; 204 } 205 FIXME("0x%x: %s is unknown\n", c, debugstr_wn(&c, 1)); 206 return FALSE; 207 } 208 209 } 210 return TRUE; 211 } 212 213 /***************************************************** 214 * DllMain 215 */ 216 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 217 { 218 TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved); 219 220 switch(fdwReason) 221 { 222 case DLL_WINE_PREATTACH: 223 return FALSE; /* prefer native version */ 224 225 case DLL_PROCESS_ATTACH: 226 DisableThreadLibraryCalls( hinstDLL ); 227 break; 228 } 229 return TRUE; 230 } 231 232 233 /***************************************************** 234 * PrintUIEntryW [printui.@] 235 * Commandline-Interface for using printui.dll with rundll32.exe 236 * 237 */ 238 void WINAPI PrintUIEntryW(HWND hWnd, HINSTANCE hInst, LPCWSTR pCommand, DWORD nCmdShow) 239 { 240 context_t cx; 241 BOOL res = FALSE; 242 243 TRACE("(%p, %p, %s, 0x%x)\n", hWnd, hInst, debugstr_w(pCommand), nCmdShow); 244 245 memset(&cx, 0, sizeof(context_t)); 246 cx.hWnd = hWnd; 247 cx.nCmdShow = nCmdShow; 248 249 if ((pCommand) && (pCommand[0])) { 250 /* result is allocated with GlobalAlloc() */ 251 cx.argv = CommandLineToArgvW(pCommand, &cx.argc); 252 TRACE("got %d args at %p\n", cx.argc, cx.argv); 253 254 res = parse_rundll(&cx); 255 } 256 257 if (res && cx.command) { 258 switch (cx.command) 259 { 260 261 default: 262 { 263 WCHAR txtW[3]; 264 txtW[0] = cx.command; 265 txtW[1] = cx.subcommand; 266 txtW[2] = '\0'; 267 FIXME("command not implemented: %s\n", debugstr_w(txtW)); 268 } 269 } 270 } 271 272 if ((res == FALSE) || (cx.command == '\0')) { 273 FIXME("dialog: Printer / The operation was not successful\n"); 274 } 275 276 GlobalFree(cx.argv); 277 278 } 279