localui/tests: Handle different results from XP.
[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         pi_buffer = HeapAlloc(GetProcessHeap(), 0, pi_needed);
75         SetLastError(0xdeadbeef);
76         res = EnumPortsW(NULL, 2, pi_buffer, pi_needed, &pi_needed, &pi_numports);
77     }
78     if (pi_buffer) {
79         pi = (PORT_INFO_2W *) pi_buffer;
80         res = 0;
81         while (pi_numports > res) {
82             if (lstrcmpiW(pi->pPortName, pPort) == 0) {
83                 return pi;
84             }
85             pi++;
86             res++;
87         }
88     }
89     return NULL;
90 }
91
92
93 /* ########################### */
94
95 static LPCSTR load_functions(void)
96 {
97     LPCSTR  ptr;
98
99     ptr = "localui.dll";
100     hdll = LoadLibraryA(ptr);
101     if (!hdll) return ptr;
102
103     ptr = "InitializePrintMonitorUI";
104     pInitializePrintMonitorUI = (VOID *) GetProcAddress(hdll, ptr);
105     if (!pInitializePrintMonitorUI) return ptr;
106
107     return NULL;
108 }
109
110 /* ###########################
111  *   strdupW [internal]
112  */
113
114 static LPWSTR strdupW(LPCWSTR strW)
115 {
116     LPWSTR  ptr;
117
118     ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(strW) + 1) * sizeof(WCHAR));
119     if (ptr) {
120         lstrcpyW(ptr, strW);
121     }
122     return ptr;
123 }
124
125 /* ########################### */
126
127 static void test_AddPortUI(void)
128 {
129     DWORD   res;
130     LPWSTR  new_portname;
131
132     /* not present before w2k */
133     if (!pAddPortUI) {
134         skip("AddPortUI not found\n");
135         return;
136     }
137
138     SetLastError(0xdeadbeef);
139     res = pAddPortUI(NULL, NULL, NULL, NULL);
140     ok( !res &&
141         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
142         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
143         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
144
145     SetLastError(0xdeadbeef);
146     res = pAddPortUI(NULL, NULL, emptyW, NULL);
147     ok( !res &&
148         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
149         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
150         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
151
152     SetLastError(0xdeadbeef);
153     res = pAddPortUI(NULL, NULL, does_not_existW, NULL);
154     ok( !res &&
155         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
156         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
157         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
158
159     if (winetest_interactive) {
160         SetLastError(0xdeadbeef);
161         new_portname = NULL;
162         /*
163          * - On MSDN, you can read, that no dialogs should be displayed, when hWnd
164          *   is NULL, but native localui does not care
165          * - when the new port already exist,
166          *   TRUE is returned, but new_portname is NULL
167          * - when the new port starts with "COM" or "LPT",
168          *   FALSE is returned with ERROR_NOT_SUPPORTED in windows
169          */
170         res = pAddPortUI(NULL, NULL, localportW, &new_portname);
171         ok( res ||
172             (GetLastError() == ERROR_CANCELLED) ||
173             (GetLastError() == ERROR_ACCESS_DENIED) ||
174             (GetLastError() == ERROR_NOT_SUPPORTED),
175             "got %d with %u and %p (expected '!= 0' or '0' with: "
176             "ERROR_CANCELLED, ERROR_ACCESS_DENIED or ERROR_NOT_SUPPORTED)\n",
177             res, GetLastError(), new_portname);
178
179         GlobalFree(new_portname);
180     }
181 }
182
183 /* ########################### */
184
185 static void test_ConfigurePortUI(void)
186 {
187     DWORD   res;
188
189     /* not present before w2k */
190     if (!pConfigurePortUI) {
191         skip("ConfigurePortUI not found\n");
192         return;
193     }
194
195     SetLastError(0xdeadbeef);
196     res = pConfigurePortUI(NULL, NULL, NULL);
197     ok( !res &&
198         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
199         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
200         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
201
202     SetLastError(0xdeadbeef);
203     res = pConfigurePortUI(NULL, NULL, emptyW);
204     ok( !res &&
205         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
206         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
207         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
208
209
210     SetLastError(0xdeadbeef);
211     res = pConfigurePortUI(NULL, NULL, does_not_existW);
212     ok( !res &&
213         ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
214         "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
215         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
216
217     if (winetest_interactive && lpt_present) {
218         SetLastError(0xdeadbeef);
219         res = pConfigurePortUI(NULL, NULL, lpt_present->pPortName);
220         ok( res ||
221             (GetLastError() == ERROR_CANCELLED) || (GetLastError() == ERROR_ACCESS_DENIED),
222             "got %d with %u (expected '!= 0' or '0' with: ERROR_CANCELLED or "
223             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
224     }
225
226     if (lpt_absent) {
227         SetLastError(0xdeadbeef);
228         res = pConfigurePortUI(NULL, NULL, lpt_absent);
229         ok( !res &&
230             ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
231             "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
232             "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
233     }
234
235     if (winetest_interactive && com_present) {
236         SetLastError(0xdeadbeef);
237         res = pConfigurePortUI(NULL, NULL, com_present->pPortName);
238         ok( res ||
239             (GetLastError() == ERROR_CANCELLED) || (GetLastError() == ERROR_ACCESS_DENIED),
240             "got %d with %u (expected '!= 0' or '0' with: ERROR_CANCELLED or "
241             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
242     }
243
244     if (com_absent) {
245         SetLastError(0xdeadbeef);
246         res = pConfigurePortUI(NULL, NULL, com_absent);
247         ok( !res &&
248             ((GetLastError() == ERROR_UNKNOWN_PORT) || (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
249             "got %d with %u (expected '0' with: ERROR_UNKNOWN_PORT or "
250             "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
251
252     }
253
254     if (winetest_interactive && file_present) {
255         SetLastError(0xdeadbeef);
256         res = pConfigurePortUI(NULL, NULL, portname_fileW);
257         ok( !res &&
258             ((GetLastError() == ERROR_CANCELLED) || (GetLastError() == ERROR_ACCESS_DENIED)),
259             "got %d with %u (expected '0' with: ERROR_CANCELLED or "
260             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
261     }
262 }
263
264 /* ########################### */
265
266 START_TEST(localui)
267 {
268     LPCSTR   ptr;
269     DWORD   numentries;
270     PORT_INFO_2W * pi2;
271     WCHAR   bufferW[16];
272     CHAR    bufferA[16];
273     DWORD   id;
274
275     /* localui.dll does not exist before w2k */
276     ptr = load_functions();
277     if (ptr) {
278         skip("%s not found\n", ptr);
279         return;
280     }
281
282     pui = pInitializePrintMonitorUI();
283     if (pui) {
284         numentries = (pui->dwMonitorUISize - sizeof(DWORD)) / sizeof(VOID *);
285         ok( numentries == 3,
286                 "dwMonitorUISize (%d) => %d Functions\n", pui->dwMonitorUISize, numentries);
287
288         if (numentries > 2) {
289             pAddPortUI = pui->pfnAddPortUI;
290             pConfigurePortUI = pui->pfnConfigurePortUI;
291             pDeletePortUI = pui->pfnDeletePortUI;
292         }
293     }
294
295     /* find installed Ports */
296
297     id = 0;
298     /* "LPT1:" - "LPT9:" */
299     while (((lpt_present == NULL) || (lpt_absent == NULL)) && id < 9) {
300         id++;
301         sprintf(bufferA, fmt_lptA, id);
302         MultiByteToWideChar( CP_ACP, 0, bufferA, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) );
303         pi2 = find_portinfo2(bufferW);
304         if (pi2 && (lpt_present == NULL)) lpt_present = pi2;
305         if (!pi2 && (lpt_absent == NULL)) lpt_absent = strdupW(bufferW);
306     }
307
308     id = 0;
309     /* "COM1:" - "COM9:" */
310     while (((com_present == NULL) || (com_absent == NULL)) && id < 9) {
311         id++;
312         sprintf(bufferA, fmt_comA, id);
313         MultiByteToWideChar( CP_ACP, 0, bufferA, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) );
314         pi2 = find_portinfo2(bufferW);
315         if (pi2 && (com_present == NULL)) com_present = pi2;
316         if (!pi2 && (com_absent == NULL)) com_absent = strdupW(bufferW);
317     }
318
319     /* "FILE:" */
320     file_present = find_portinfo2(portname_fileW);
321
322     test_AddPortUI();
323     test_ConfigurePortUI();
324
325     /* cleanup */
326     HeapFree(GetProcessHeap(), 0, lpt_absent);
327     HeapFree(GetProcessHeap(), 0, com_absent);
328     HeapFree(GetProcessHeap(), 0, pi_buffer);
329 }