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