Release 1.4.1.
[wine] / dlls / localui / tests / localui.c
1 /*
2  * Unit test suite for the Local Printmonitor User Interface
3  *
4  * Copyright 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
22 #include <stdarg.h>
23 #include <stdio.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "wingdi.h"
29 #include "winnls.h"
30 #include "winreg.h"
31
32 #include "winspool.h"
33 #include "ddk/winsplp.h"
34
35 #include "wine/test.h"
36
37
38 /* ##### */
39
40 static HMODULE  hdll;
41 static PMONITORUI (WINAPI *pInitializePrintMonitorUI)(VOID);
42 static PMONITORUI pui;
43 static BOOL  (WINAPI *pAddPortUI)(PCWSTR, HWND, PCWSTR, PWSTR *);
44 static BOOL  (WINAPI *pConfigurePortUI)(PCWSTR, HWND, PCWSTR);
45 static BOOL  (WINAPI *pDeletePortUI)(PCWSTR, HWND, PCWSTR);
46
47 static WCHAR does_not_existW[] = {'d','o','e','s','_','n','o','t','_','e','x','i','s','t',0};
48 static WCHAR emptyW[] = {0};
49 static CHAR  fmt_comA[] = {'C','O','M','%','u',':',0};
50 static CHAR  fmt_lptA[] = {'L','P','T','%','u',':',0};
51 static WCHAR localportW[] = {'L','o','c','a','l',' ','P','o','r','t',0};
52 static WCHAR portname_fileW[] = {'F','I','L','E',':',0};
53
54 static LPBYTE pi_buffer;
55 static DWORD pi_numports;
56 static DWORD pi_needed;
57
58 static PORT_INFO_2W * lpt_present;
59 static PORT_INFO_2W * com_present;
60 static PORT_INFO_2W * file_present;
61
62 static LPWSTR   lpt_absent;
63 static LPWSTR   com_absent;
64
65 /* ########################### */
66
67 static PORT_INFO_2W * find_portinfo2(LPWSTR pPort)
68 {
69     PORT_INFO_2W * pi;
70     DWORD   res;
71
72     if (!pi_buffer) {
73         res = EnumPortsW(NULL, 2, NULL, 0, &pi_needed, &pi_numports);
74         ok(!res, "EnumPorts failed: got %d\n", res);
75         pi_buffer = HeapAlloc(GetProcessHeap(), 0, pi_needed);
76         res = EnumPortsW(NULL, 2, pi_buffer, pi_needed, &pi_needed, &pi_numports);
77         ok(res == 1, "EnumPorts failed: got %d\n", res);
78     }
79     if (pi_buffer) {
80         pi = (PORT_INFO_2W *) pi_buffer;
81         res = 0;
82         while (pi_numports > res) {
83             if (lstrcmpiW(pi->pPortName, pPort) == 0) {
84                 return pi;
85             }
86             pi++;
87             res++;
88         }
89     }
90     return NULL;
91 }
92
93
94 /* ########################### */
95
96 static LPCSTR load_functions(void)
97 {
98     LPCSTR  ptr;
99
100     ptr = "localui.dll";
101     hdll = LoadLibraryA(ptr);
102     if (!hdll) return ptr;
103
104     ptr = "InitializePrintMonitorUI";
105     pInitializePrintMonitorUI = (VOID *) GetProcAddress(hdll, ptr);
106     if (!pInitializePrintMonitorUI) return ptr;
107
108     return NULL;
109 }
110
111 /* ###########################
112  *   strdupW [internal]
113  */
114
115 static LPWSTR strdupW(LPCWSTR strW)
116 {
117     LPWSTR  ptr;
118
119     ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(strW) + 1) * sizeof(WCHAR));
120     if (ptr) {
121         lstrcpyW(ptr, strW);
122     }
123     return ptr;
124 }
125
126 /* ########################### */
127
128 static void test_AddPortUI(void)
129 {
130     DWORD   res;
131     LPWSTR  new_portname;
132
133     /* not present before w2k */
134     if (!pAddPortUI) {
135         skip("AddPortUI not found\n");
136         return;
137     }
138
139     SetLastError(0xdeadbeef);
140     res = pAddPortUI(NULL, NULL, NULL, NULL);
141     ok( !res &&
142         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
143         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
144         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
145
146     SetLastError(0xdeadbeef);
147     res = pAddPortUI(NULL, NULL, emptyW, NULL);
148     ok( !res &&
149         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
150         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
151         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
152
153     SetLastError(0xdeadbeef);
154     res = pAddPortUI(NULL, NULL, does_not_existW, NULL);
155     ok( !res &&
156         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
157         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
158         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
159
160     if (winetest_interactive) {
161         SetLastError(0xdeadbeef);
162         new_portname = NULL;
163         /*
164          * - On MSDN, you can read, that no dialogs should be displayed, when hWnd
165          *   is NULL, but native localui does not care
166          * - when the new port already exist,
167          *   TRUE is returned, but new_portname is NULL
168          * - when the new port starts with "COM" or "LPT",
169          *   FALSE is returned with ERROR_NOT_SUPPORTED in windows
170          */
171         res = pAddPortUI(NULL, NULL, localportW, &new_portname);
172         ok( res ||
173             (GetLastError() == ERROR_CANCELLED) ||
174             (GetLastError() == ERROR_ACCESS_DENIED) ||
175             (GetLastError() == ERROR_NOT_SUPPORTED),
176             "got %d with %u and %p (expected '!= 0' or '0' with: "
177             "ERROR_CANCELLED, ERROR_ACCESS_DENIED or ERROR_NOT_SUPPORTED)\n",
178             res, GetLastError(), new_portname);
179
180         GlobalFree(new_portname);
181     }
182 }
183
184 /* ########################### */
185
186 static void test_ConfigurePortUI(void)
187 {
188     DWORD   res;
189
190     /* not present before w2k */
191     if (!pConfigurePortUI) {
192         skip("ConfigurePortUI not found\n");
193         return;
194     }
195
196     SetLastError(0xdeadbeef);
197     res = pConfigurePortUI(NULL, NULL, NULL);
198     ok( !res &&
199         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
200         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
201         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
202
203     SetLastError(0xdeadbeef);
204     res = pConfigurePortUI(NULL, NULL, emptyW);
205     ok( !res &&
206         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
207         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
208         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
209
210
211     SetLastError(0xdeadbeef);
212     res = pConfigurePortUI(NULL, NULL, does_not_existW);
213     ok( !res &&
214         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
215         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
216         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
217
218     if (winetest_interactive && lpt_present) {
219         SetLastError(0xdeadbeef);
220         res = pConfigurePortUI(NULL, NULL, lpt_present->pPortName);
221         ok( res ||
222             (GetLastError() == ERROR_CANCELLED) || (GetLastError() == ERROR_ACCESS_DENIED),
223             "got %d with %u (expected '!= 0' or '0' with: ERROR_CANCELLED or "
224             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
225     }
226
227     if (lpt_absent) {
228         SetLastError(0xdeadbeef);
229         res = pConfigurePortUI(NULL, NULL, lpt_absent);
230         ok( !res &&
231             ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
232             "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
233             "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
234     }
235
236     if (winetest_interactive && com_present) {
237         SetLastError(0xdeadbeef);
238         res = pConfigurePortUI(NULL, NULL, com_present->pPortName);
239         ok( res ||
240             (GetLastError() == ERROR_CANCELLED) || (GetLastError() == ERROR_ACCESS_DENIED),
241             "got %d with %u (expected '!= 0' or '0' with: ERROR_CANCELLED or "
242             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
243     }
244
245     if (com_absent) {
246         SetLastError(0xdeadbeef);
247         res = pConfigurePortUI(NULL, NULL, com_absent);
248         ok( !res &&
249             ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
250             "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
251             "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
252
253     }
254
255     if (winetest_interactive && file_present) {
256         SetLastError(0xdeadbeef);
257         res = pConfigurePortUI(NULL, NULL, portname_fileW);
258         ok( !res &&
259             ((GetLastError() == ERROR_CANCELLED) || (GetLastError() == ERROR_ACCESS_DENIED)),
260             "got %d with %u (expected '0' with: ERROR_CANCELLED or "
261             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
262     }
263 }
264
265 /* ########################### */
266
267 START_TEST(localui)
268 {
269     LPCSTR   ptr;
270     DWORD   numentries;
271     PORT_INFO_2W * pi2;
272     WCHAR   bufferW[16];
273     CHAR    bufferA[16];
274     DWORD   id;
275
276     /* localui.dll does not exist before w2k */
277     ptr = load_functions();
278     if (ptr) {
279         skip("%s not found\n", ptr);
280         return;
281     }
282
283     pui = pInitializePrintMonitorUI();
284     if (pui) {
285         numentries = (pui->dwMonitorUISize - sizeof(DWORD)) / sizeof(VOID *);
286         ok( numentries == 3,
287                 "dwMonitorUISize (%d) => %d Functions\n", pui->dwMonitorUISize, numentries);
288
289         if (numentries > 2) {
290             pAddPortUI = pui->pfnAddPortUI;
291             pConfigurePortUI = pui->pfnConfigurePortUI;
292             pDeletePortUI = pui->pfnDeletePortUI;
293         }
294     }
295
296     /* find installed Ports */
297
298     id = 0;
299     /* "LPT1:" - "LPT9:" */
300     while (((lpt_present == NULL) || (lpt_absent == NULL)) && id < 9) {
301         id++;
302         sprintf(bufferA, fmt_lptA, id);
303         MultiByteToWideChar( CP_ACP, 0, bufferA, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) );
304         pi2 = find_portinfo2(bufferW);
305         if (pi2 && (lpt_present == NULL)) lpt_present = pi2;
306         if (!pi2 && (lpt_absent == NULL)) lpt_absent = strdupW(bufferW);
307     }
308
309     id = 0;
310     /* "COM1:" - "COM9:" */
311     while (((com_present == NULL) || (com_absent == NULL)) && id < 9) {
312         id++;
313         sprintf(bufferA, fmt_comA, id);
314         MultiByteToWideChar( CP_ACP, 0, bufferA, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) );
315         pi2 = find_portinfo2(bufferW);
316         if (pi2 && (com_present == NULL)) com_present = pi2;
317         if (!pi2 && (com_absent == NULL)) com_absent = strdupW(bufferW);
318     }
319
320     /* "FILE:" */
321     file_present = find_portinfo2(portname_fileW);
322
323     test_AddPortUI();
324     test_ConfigurePortUI();
325
326     /* cleanup */
327     HeapFree(GetProcessHeap(), 0, lpt_absent);
328     HeapFree(GetProcessHeap(), 0, com_absent);
329     HeapFree(GetProcessHeap(), 0, pi_buffer);
330 }