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