[LOCALSPL_WINETEST] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / modules / rostests / winetests / localspl / localmon.c
1 /*
2 * Unit test suite for localspl API functions: local print monitor
3 *
4 * Copyright 2006-2007 Detlef Riekenberg
5 * Copyright 2019 Dmitry Timoshkov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 *
21 */
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "wingdi.h"
29 #include "winreg.h"
30
31 #include "winspool.h"
32 #include "ddk/winsplp.h"
33
34 #include "wine/test.h"
35
36
37 /* ##### */
38
39 static HMODULE hdll;
40 static HMODULE hlocalmon;
41 static HANDLE hmon;
42 static LPMONITOREX (WINAPI *pInitializePrintMonitor)(LPWSTR);
43 static LPMONITOR2 (WINAPI *pInitializePrintMonitor2)(PMONITORINIT, LPHANDLE);
44
45 static LPMONITOREX pm;
46 static LPMONITOR2 pm2;
47 static BOOL (WINAPI *pEnumPorts)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
48 static BOOL (WINAPI *pEnumPorts2)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
49 static BOOL (WINAPI *pOpenPort)(LPWSTR, PHANDLE);
50 static BOOL (WINAPI *pOpenPort2)(HANDLE, LPWSTR, PHANDLE);
51 static BOOL (WINAPI *pOpenPortEx)(LPWSTR, LPWSTR, PHANDLE, struct _MONITOR *);
52 static BOOL (WINAPI *pOpenPortEx2)(HANDLE, HANDLE, LPWSTR, LPWSTR, PHANDLE, struct _MONITOR2 *);
53 static BOOL (WINAPI *pStartDocPort)(HANDLE, LPWSTR, DWORD, DWORD, LPBYTE);
54 static BOOL (WINAPI *pWritePort)(HANDLE hPort, LPBYTE, DWORD, LPDWORD);
55 static BOOL (WINAPI *pReadPort)(HANDLE hPort, LPBYTE, DWORD, LPDWORD);
56 static BOOL (WINAPI *pEndDocPort)(HANDLE);
57 static BOOL (WINAPI *pClosePort)(HANDLE);
58 static BOOL (WINAPI *pAddPort)(LPWSTR, HWND, LPWSTR);
59 static BOOL (WINAPI *pAddPort2)(HANDLE, LPWSTR, HWND, LPWSTR);
60 static BOOL (WINAPI *pAddPortEx)(LPWSTR, DWORD, LPBYTE, LPWSTR);
61 static BOOL (WINAPI *pAddPortEx2)(HANDLE, LPWSTR, DWORD, LPBYTE, LPWSTR);
62 static BOOL (WINAPI *pConfigurePort)(LPWSTR, HWND, LPWSTR);
63 static BOOL (WINAPI *pConfigurePort2)(HANDLE, LPWSTR, HWND, LPWSTR);
64 static BOOL (WINAPI *pDeletePort)(LPWSTR, HWND, LPWSTR);
65 static BOOL (WINAPI *pDeletePort2)(HANDLE, LPWSTR, HWND, LPWSTR);
66 static BOOL (WINAPI *pGetPrinterDataFromPort)(HANDLE, DWORD, LPWSTR, LPWSTR, DWORD, LPWSTR, DWORD, LPDWORD);
67 static BOOL (WINAPI *pSetPortTimeOuts)(HANDLE, LPCOMMTIMEOUTS, DWORD);
68 static BOOL (WINAPI *pXcvOpenPort)(LPCWSTR, ACCESS_MASK, PHANDLE);
69 static BOOL (WINAPI *pXcvOpenPort2)(HANDLE, LPCWSTR, ACCESS_MASK, PHANDLE);
70 static DWORD (WINAPI *pXcvDataPort)(HANDLE, LPCWSTR, PBYTE, DWORD, PBYTE, DWORD, PDWORD);
71 static BOOL (WINAPI *pXcvClosePort)(HANDLE);
72
73 static HANDLE hXcv;
74 static HANDLE hXcv_noaccess;
75
76 /* ########################### */
77
78 static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0};
79 static const WCHAR cmd_ConfigureLPTPortCommandOKW[] = {'C','o','n','f','i','g','u','r','e',
80 'L','P','T','P','o','r','t',
81 'C','o','m','m','a','n','d','O','K',0};
82 static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0};
83 static const WCHAR cmd_GetTransmissionRetryTimeoutW[] = {'G','e','t',
84 'T','r','a','n','s','m','i','s','s','i','o','n',
85 'R','e','t','r','y','T','i','m','e','o','u','t',0};
86
87 static const WCHAR cmd_MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
88 static const WCHAR cmd_MonitorUI_lcaseW[] = {'m','o','n','i','t','o','r','u','i',0};
89 static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0};
90 static WCHAR does_not_existW[] = {'d','o','e','s','_','n','o','t','_','e','x','i','s','t',0};
91 static const CHAR emptyA[] = "";
92 static WCHAR emptyW[] = {0};
93 static WCHAR LocalPortW[] = {'L','o','c','a','l',' ','P','o','r','t',0};
94 static WCHAR Monitors_LocalPortW[] = {
95 'S','y','s','t','e','m','\\',
96 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
97 'C','o','n','t','r','o','l','\\',
98 'P','r','i','n','t','\\',
99 'M','o','n','i','t','o','r','s','\\',
100 'L','o','c','a','l',' ','P','o','r','t',0};
101
102 static const CHAR num_0A[] = "0";
103 static WCHAR num_0W[] = {'0',0};
104 static const CHAR num_1A[] = "1";
105 static WCHAR num_1W[] = {'1',0};
106 static const CHAR num_999999A[] = "999999";
107 static WCHAR num_999999W[] = {'9','9','9','9','9','9',0};
108 static const CHAR num_1000000A[] = "1000000";
109 static WCHAR num_1000000W[] = {'1','0','0','0','0','0','0',0};
110
111 static const WCHAR portname_comW[] = {'C','O','M',0};
112 static WCHAR portname_com1W[] = {'C','O','M','1',':',0};
113 static WCHAR portname_com2W[] = {'C','O','M','2',':',0};
114 static WCHAR portname_fileW[] = {'F','I','L','E',':',0};
115 static const WCHAR portname_lptW[] = {'L','P','T',0};
116 static WCHAR portname_lpt1W[] = {'L','P','T','1',':',0};
117 static WCHAR portname_lpt2W[] = {'L','P','T','2',':',0};
118 static WCHAR server_does_not_existW[] = {'\\','\\','d','o','e','s','_','n','o','t','_','e','x','i','s','t',0};
119
120 static const CHAR TransmissionRetryTimeoutA[] = {'T','r','a','n','s','m','i','s','s','i','o','n',
121 'R','e','t','r','y','T','i','m','e','o','u','t',0};
122
123 static const CHAR WinNT_CV_WindowsA[] = {'S','o','f','t','w','a','r','e','\\',
124 'M','i','c','r','o','s','o','f','t','\\',
125 'W','i','n','d','o','w','s',' ','N','T','\\',
126 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
127 'W','i','n','d','o','w','s',0};
128 static WCHAR wineW[] = {'W','i','n','e',0};
129
130 static WCHAR tempdirW[MAX_PATH];
131 static WCHAR tempfileW[MAX_PATH];
132
133 #define PORTNAME_PREFIX 3
134 #define PORTNAME_MINSIZE 5
135 #define PORTNAME_MAXSIZE 10
136 static WCHAR have_com[PORTNAME_MAXSIZE];
137 static WCHAR have_lpt[PORTNAME_MAXSIZE];
138 static WCHAR have_file[PORTNAME_MAXSIZE];
139
140 /* ########################### */
141
142 static LONG WINAPI CreateKey(HANDLE hcKey, LPCWSTR pszSubKey, DWORD dwOptions,
143 REGSAM samDesired, PSECURITY_ATTRIBUTES pSecurityAttributes,
144 PHANDLE phckResult, PDWORD pdwDisposition, HANDLE hSpooler)
145 {
146 ok(0, "should not be called\n");
147 return ERROR_CALL_NOT_IMPLEMENTED;
148 }
149
150 static LONG WINAPI OpenKey(HANDLE hcKey, LPCWSTR pszSubKey, REGSAM samDesired,
151 PHANDLE phkResult, HANDLE hSpooler)
152 {
153 ok(0, "should not be called\n");
154 return ERROR_CALL_NOT_IMPLEMENTED;
155 }
156
157 static LONG WINAPI CloseKey(HANDLE hcKey, HANDLE hSpooler)
158 {
159 ok(0, "should not be called\n");
160 return ERROR_CALL_NOT_IMPLEMENTED;
161 }
162
163 static LONG WINAPI DeleteKey(HANDLE hcKey, LPCWSTR pszSubKey, HANDLE hSpooler)
164 {
165 ok(0, "should not be called\n");
166 return ERROR_CALL_NOT_IMPLEMENTED;
167 }
168
169 static LONG WINAPI EnumKey(HANDLE hcKey, DWORD dwIndex, LPWSTR pszName,
170 PDWORD pcchName, PFILETIME pftLastWriteTime, HANDLE hSpooler)
171 {
172 ok(0, "should not be called\n");
173 return ERROR_CALL_NOT_IMPLEMENTED;
174 }
175
176 static LONG WINAPI QueryInfoKey(HANDLE hcKey, PDWORD pcSubKeys, PDWORD pcbKey,
177 PDWORD pcValues, PDWORD pcbValue, PDWORD pcbData,
178 PDWORD pcbSecurityDescriptor, PFILETIME pftLastWriteTime,
179 HANDLE hSpooler)
180 {
181 ok(0, "should not be called\n");
182 return ERROR_CALL_NOT_IMPLEMENTED;
183 }
184
185 static LONG WINAPI SetValue(HANDLE hcKey, LPCWSTR pszValue, DWORD dwType,
186 const BYTE* pData, DWORD cbData, HANDLE hSpooler)
187 {
188 ok(0, "should not be called\n");
189 return ERROR_CALL_NOT_IMPLEMENTED;
190 }
191
192 static LONG WINAPI DeleteValue(HANDLE hcKey, LPCWSTR pszValue, HANDLE hSpooler)
193 {
194 ok(0, "should not be called\n");
195 return ERROR_CALL_NOT_IMPLEMENTED;
196 }
197
198 static LONG WINAPI EnumValue(HANDLE hcKey, DWORD dwIndex, LPWSTR pszValue,
199 PDWORD pcbValue, PDWORD pType, PBYTE pData, PDWORD pcbData,
200 HANDLE hSpooler)
201 {
202 ok(0, "should not be called\n");
203 return ERROR_CALL_NOT_IMPLEMENTED;
204 }
205
206 static LONG WINAPI QueryValue(HANDLE hcKey, LPCWSTR pszValue, PDWORD pType,
207 PBYTE pData, PDWORD pcbData, HANDLE hSpooler)
208 {
209 return ERROR_CALL_NOT_IMPLEMENTED;
210 }
211
212 static MONITORREG monreg =
213 {
214 sizeof(MONITORREG),
215 CreateKey,
216 OpenKey,
217 CloseKey,
218 DeleteKey,
219 EnumKey,
220 QueryInfoKey,
221 SetValue,
222 DeleteValue,
223 EnumValue,
224 QueryValue
225 };
226
227 static DWORD delete_port(LPWSTR portname)
228 {
229 DWORD res;
230
231 if (pDeletePort) {
232 res = pDeletePort(NULL, 0, portname);
233 }
234 else
235 {
236 res = pXcvDataPort(hXcv, cmd_DeletePortW, (PBYTE) portname, (lstrlenW(portname) + 1) * sizeof(WCHAR), NULL, 0, NULL);
237 }
238 return res;
239 }
240
241 /* ########################### */
242
243 static void find_installed_ports(void)
244 {
245 PORT_INFO_1W * pi = NULL;
246 WCHAR nameW[PORTNAME_MAXSIZE];
247 DWORD needed;
248 DWORD returned;
249 DWORD res;
250 DWORD id;
251
252 have_com[0] = '\0';
253 have_lpt[0] = '\0';
254 have_file[0] = '\0';
255
256 if (!pEnumPorts) return;
257
258 res = pEnumPorts(NULL, 1, NULL, 0, &needed, &returned);
259 if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
260 pi = HeapAlloc(GetProcessHeap(), 0, needed);
261 }
262 res = pEnumPorts(NULL, 1, (LPBYTE) pi, needed, &needed, &returned);
263
264 if (!res) {
265 skip("no ports found\n");
266 HeapFree(GetProcessHeap(), 0, pi);
267 return;
268 }
269
270 id = 0;
271 while (id < returned) {
272 res = lstrlenW(pi[id].pName);
273 if ((res >= PORTNAME_MINSIZE) && (res < PORTNAME_MAXSIZE) &&
274 (pi[id].pName[res-1] == ':')) {
275 /* copy only the prefix ("LPT" or "COM") */
276 memcpy(&nameW, pi[id].pName, PORTNAME_PREFIX * sizeof(WCHAR));
277 nameW[PORTNAME_PREFIX] = '\0';
278
279 if (!have_com[0] && (lstrcmpiW(nameW, portname_comW) == 0)) {
280 memcpy(&have_com, pi[id].pName, (res+1) * sizeof(WCHAR));
281 }
282
283 if (!have_lpt[0] && (lstrcmpiW(nameW, portname_lptW) == 0)) {
284 memcpy(&have_lpt, pi[id].pName, (res+1) * sizeof(WCHAR));
285 }
286
287 if (!have_file[0] && (lstrcmpiW(pi[id].pName, portname_fileW) == 0)) {
288 memcpy(&have_file, pi[id].pName, (res+1) * sizeof(WCHAR));
289 }
290 }
291 id++;
292 }
293
294 HeapFree(GetProcessHeap(), 0, pi);
295 }
296
297 /* ########################### */
298
299 static void test_AddPort(void)
300 {
301 DWORD res;
302
303 /* moved to localui.dll since w2k */
304 if (!pAddPort) return;
305
306 if (0)
307 {
308 /* NT4 crash on this test */
309 pAddPort(NULL, 0, NULL);
310 }
311
312 /* Testing-Results (localmon.dll from NT4.0):
313 - The Servername is ignored
314 - Case of MonitorName is ignored
315 */
316
317 SetLastError(0xdeadbeef);
318 res = pAddPort(NULL, 0, emptyW);
319 ok(!res, "returned %d with %u (expected '0')\n", res, GetLastError());
320
321 SetLastError(0xdeadbeef);
322 res = pAddPort(NULL, 0, does_not_existW);
323 ok(!res, "returned %d with %u (expected '0')\n", res, GetLastError());
324
325 }
326
327 /* ########################### */
328
329 static void test_AddPortEx(void)
330 {
331 PORT_INFO_2W pi;
332 DWORD res;
333
334 if (!pAddPortEx) {
335 skip("AddPortEx\n");
336 return;
337 }
338 if ((!pDeletePort) && (!hXcv)) {
339 skip("No API to delete a Port\n");
340 return;
341 }
342
343 /* start test with clean ports */
344 delete_port(tempfileW);
345
346 pi.pPortName = tempfileW;
347 if (0) {
348 /* tests crash with native localspl.dll in w2k,
349 but works with native localspl.dll in wine */
350 SetLastError(0xdeadbeef);
351 res = pAddPortEx(NULL, 1, (LPBYTE) &pi, LocalPortW);
352 trace("returned %u with %u\n", res, GetLastError() );
353 ok( res, "got %u with %u (expected '!= 0')\n", res, GetLastError());
354
355 /* port already exists: */
356 SetLastError(0xdeadbeef);
357 res = pAddPortEx(NULL, 1, (LPBYTE) &pi, LocalPortW);
358 trace("returned %u with %u\n", res, GetLastError() );
359 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
360 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
361 res, GetLastError());
362 delete_port(tempfileW);
363
364
365 /* NULL for pMonitorName is documented for Printmonitors, but
366 localspl.dll fails always with ERROR_INVALID_PARAMETER */
367 SetLastError(0xdeadbeef);
368 res = pAddPortEx(NULL, 1, (LPBYTE) &pi, NULL);
369 trace("returned %u with %u\n", res, GetLastError() );
370 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
371 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
372 res, GetLastError());
373 if (res) delete_port(tempfileW);
374
375
376 SetLastError(0xdeadbeef);
377 res = pAddPortEx(NULL, 1, (LPBYTE) &pi, emptyW);
378 trace("returned %u with %u\n", res, GetLastError() );
379 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
380 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
381 res, GetLastError());
382 if (res) delete_port(tempfileW);
383
384
385 SetLastError(0xdeadbeef);
386 res = pAddPortEx(NULL, 1, (LPBYTE) &pi, does_not_existW);
387 trace("returned %u with %u\n", res, GetLastError() );
388 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
389 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
390 res, GetLastError());
391 if (res) delete_port(tempfileW);
392 }
393
394 pi.pPortName = NULL;
395 SetLastError(0xdeadbeef);
396 res = pAddPortEx(NULL, 1, (LPBYTE) &pi, LocalPortW);
397 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
398 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
399 res, GetLastError());
400
401 /* level 2 is documented as supported for Printmonitors,
402 but localspl.dll fails always with ERROR_INVALID_LEVEL */
403
404 pi.pPortName = tempfileW;
405 pi.pMonitorName = LocalPortW;
406 pi.pDescription = wineW;
407 pi.fPortType = PORT_TYPE_WRITE;
408
409 SetLastError(0xdeadbeef);
410 res = pAddPortEx(NULL, 2, (LPBYTE) &pi, LocalPortW);
411 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
412 "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
413 res, GetLastError());
414 if (res) delete_port(tempfileW);
415
416
417 /* invalid levels */
418 SetLastError(0xdeadbeef);
419 res = pAddPortEx(NULL, 0, (LPBYTE) &pi, LocalPortW);
420 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
421 "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
422 res, GetLastError());
423 if (res) delete_port(tempfileW);
424
425
426 SetLastError(0xdeadbeef);
427 res = pAddPortEx(NULL, 3, (LPBYTE) &pi, LocalPortW);
428 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
429 "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
430 res, GetLastError());
431 if (res) delete_port(tempfileW);
432
433 /* cleanup */
434 delete_port(tempfileW);
435 }
436
437 /* ########################### */
438
439 static void test_ClosePort(void)
440 {
441 HANDLE hPort;
442 HANDLE hPort2;
443 LPWSTR nameW = NULL;
444 DWORD res;
445 DWORD res2;
446
447
448 if (!pOpenPort || !pClosePort) return;
449
450 if (have_com[0]) {
451 nameW = have_com;
452
453 hPort = (HANDLE) 0xdeadbeef;
454 res = pOpenPort(nameW, &hPort);
455 hPort2 = (HANDLE) 0xdeadbeef;
456 res2 = pOpenPort(nameW, &hPort2);
457
458 if (res2 && (hPort2 != hPort)) {
459 SetLastError(0xdeadbeef);
460 res2 = pClosePort(hPort2);
461 ok(res2, "got %u with %u (expected '!= 0')\n", res2, GetLastError());
462 }
463
464 if (res) {
465 SetLastError(0xdeadbeef);
466 res = pClosePort(hPort);
467 ok(res, "got %u with %u (expected '!= 0')\n", res, GetLastError());
468 }
469 }
470
471
472 if (have_lpt[0]) {
473 nameW = have_lpt;
474
475 hPort = (HANDLE) 0xdeadbeef;
476 res = pOpenPort(nameW, &hPort);
477 hPort2 = (HANDLE) 0xdeadbeef;
478 res2 = pOpenPort(nameW, &hPort2);
479
480 if (res2 && (hPort2 != hPort)) {
481 SetLastError(0xdeadbeef);
482 res2 = pClosePort(hPort2);
483 ok(res2, "got %u with %u (expected '!= 0')\n", res2, GetLastError());
484 }
485
486 if (res) {
487 SetLastError(0xdeadbeef);
488 res = pClosePort(hPort);
489 ok(res, "got %u with %u (expected '!= 0')\n", res, GetLastError());
490 }
491 }
492
493
494 if (have_file[0]) {
495 nameW = have_file;
496
497 hPort = (HANDLE) 0xdeadbeef;
498 res = pOpenPort(nameW, &hPort);
499 hPort2 = (HANDLE) 0xdeadbeef;
500 res2 = pOpenPort(nameW, &hPort2);
501
502 if (res2 && (hPort2 != hPort)) {
503 SetLastError(0xdeadbeef);
504 res2 = pClosePort(hPort2);
505 ok(res2, "got %u with %u (expected '!= 0')\n", res2, GetLastError());
506 }
507
508 if (res) {
509 SetLastError(0xdeadbeef);
510 res = pClosePort(hPort);
511 ok(res, "got %u with %u (expected '!= 0')\n", res, GetLastError());
512 }
513
514 }
515
516 if (0) {
517 /* an invalid HANDLE crash native localspl.dll */
518
519 SetLastError(0xdeadbeef);
520 res = pClosePort(NULL);
521 trace("got %u with %u\n", res, GetLastError());
522
523 SetLastError(0xdeadbeef);
524 res = pClosePort( (HANDLE) 0xdeadbeef);
525 trace("got %u with %u\n", res, GetLastError());
526
527 SetLastError(0xdeadbeef);
528 res = pClosePort(INVALID_HANDLE_VALUE);
529 trace("got %u with %u\n", res, GetLastError());
530 }
531
532 }
533
534 /* ########################### */
535
536 static void test_ConfigurePort(void)
537 {
538 DWORD res;
539
540 /* moved to localui.dll since w2k */
541 if (!pConfigurePort) return;
542
543 if (0)
544 {
545 /* NT4 crash on this test */
546 pConfigurePort(NULL, 0, NULL);
547 }
548
549 /* Testing-Results (localmon.dll from NT4.0):
550 - Case of Portname is ignored
551 - "COM1:" and "COM01:" are the same (Compared by value)
552 - Portname without ":" => Dialog "Nothing to configure" comes up; Success
553 - "LPT1:", "LPT0:" and "LPT:" are the same (Numbers in "LPT:" are ignored)
554 - Empty Servername (LPT1:) => Dialog comes up (Servername is ignored)
555 - "FILE:" => Dialog "Nothing to configure" comes up; Success
556 - Empty Portname => => Dialog "Nothing to configure" comes up; Success
557 - Port "does_not_exist" => Dialog "Nothing to configure" comes up; Success
558 */
559 if (winetest_interactive > 0) {
560
561 SetLastError(0xdeadbeef);
562 res = pConfigurePort(NULL, 0, portname_com1W);
563 trace("returned %d with %u\n", res, GetLastError());
564
565 SetLastError(0xdeadbeef);
566 res = pConfigurePort(NULL, 0, portname_lpt1W);
567 trace("returned %d with %u\n", res, GetLastError());
568
569 SetLastError(0xdeadbeef);
570 res = pConfigurePort(NULL, 0, portname_fileW);
571 trace("returned %d with %u\n", res, GetLastError());
572 }
573 }
574
575 /* ########################### */
576
577 static void test_DeletePort(void)
578 {
579 DWORD res;
580
581 /* moved to localui.dll since w2k */
582 if (!pDeletePort) return;
583
584 if (0)
585 {
586 /* NT4 crash on this test */
587 pDeletePort(NULL, 0, NULL);
588 }
589
590 /* Testing-Results (localmon.dll from NT4.0):
591 - Case of Portname is ignored (returned '1' on Success)
592 - "COM1:" and "COM01:" are different (Compared as string)
593 - server_does_not_exist (LPT1:) => Port deleted, Success (Servername is ignored)
594 - Empty Portname => => FALSE (LastError not changed)
595 - Port "does_not_exist" => FALSE (LastError not changed)
596 */
597
598 SetLastError(0xdeadbeef);
599 res = pDeletePort(NULL, 0, emptyW);
600 ok(!res, "returned %d with %u (expected '0')\n", res, GetLastError());
601
602 SetLastError(0xdeadbeef);
603 res = pDeletePort(NULL, 0, does_not_existW);
604 ok(!res, "returned %d with %u (expected '0')\n", res, GetLastError());
605
606 }
607
608 /* ########################### */
609
610 static void test_EnumPorts(void)
611 {
612 DWORD res;
613 DWORD level;
614 LPBYTE buffer;
615 DWORD cbBuf;
616 DWORD pcbNeeded;
617 DWORD pcReturned;
618
619 if (!pEnumPorts) return;
620
621 /* valid levels are 1 and 2 */
622 for(level = 0; level < 4; level++) {
623
624 cbBuf = 0xdeadbeef;
625 pcReturned = 0xdeadbeef;
626 SetLastError(0xdeadbeef);
627 res = pEnumPorts(NULL, level, NULL, 0, &cbBuf, &pcReturned);
628
629 /* use only a short test, when we test with an invalid level */
630 if(!level || (level > 2)) {
631 /* NT4 fails with ERROR_INVALID_LEVEL (as expected)
632 XP succeeds with ERROR_SUCCESS () */
633 ok( (cbBuf == 0) && (pcReturned == 0),
634 "(%d) returned %d with %u and %d, %d (expected 0, 0)\n",
635 level, res, GetLastError(), cbBuf, pcReturned);
636 continue;
637 }
638
639 ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
640 "(%d) returned %d with %u and %d, %d (expected '0' with "
641 "ERROR_INSUFFICIENT_BUFFER)\n",
642 level, res, GetLastError(), cbBuf, pcReturned);
643
644 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf * 2);
645 if (buffer == NULL) continue;
646
647 pcbNeeded = 0xdeadbeef;
648 pcReturned = 0xdeadbeef;
649 SetLastError(0xdeadbeef);
650 res = pEnumPorts(NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
651 ok( res, "(%d) returned %d with %u and %d, %d (expected '!= 0')\n",
652 level, res, GetLastError(), pcbNeeded, pcReturned);
653 /* We can compare the returned Data with the Registry / "win.ini",[Ports] here */
654
655 pcbNeeded = 0xdeadbeef;
656 pcReturned = 0xdeadbeef;
657 SetLastError(0xdeadbeef);
658 res = pEnumPorts(NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
659 ok( res, "(%d) returned %d with %u and %d, %d (expected '!= 0')\n",
660 level, res, GetLastError(), pcbNeeded, pcReturned);
661
662 pcbNeeded = 0xdeadbeef;
663 pcReturned = 0xdeadbeef;
664 SetLastError(0xdeadbeef);
665 res = pEnumPorts(NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
666 ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
667 "(%d) returned %d with %u and %d, %d (expected '0' with "
668 "ERROR_INSUFFICIENT_BUFFER)\n",
669 level, res, GetLastError(), pcbNeeded, pcReturned);
670
671 if (0)
672 {
673 /* The following tests crash this app with native localmon/localspl */
674 pEnumPorts(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
675 pEnumPorts(NULL, level, buffer, cbBuf, NULL, &pcReturned);
676 pEnumPorts(NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
677 }
678
679 /* The Servername is ignored */
680 pcbNeeded = 0xdeadbeef;
681 pcReturned = 0xdeadbeef;
682 SetLastError(0xdeadbeef);
683 res = pEnumPorts(emptyW, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
684 ok( res, "(%d) returned %d with %u and %d, %d (expected '!= 0')\n",
685 level, res, GetLastError(), pcbNeeded, pcReturned);
686
687 pcbNeeded = 0xdeadbeef;
688 pcReturned = 0xdeadbeef;
689 SetLastError(0xdeadbeef);
690 res = pEnumPorts(server_does_not_existW, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
691 ok( res, "(%d) returned %d with %u and %d, %d (expected '!= 0')\n",
692 level, res, GetLastError(), pcbNeeded, pcReturned);
693
694 HeapFree(GetProcessHeap(), 0, buffer);
695 }
696 }
697
698 /* ########################### */
699
700
701 static void test_InitializePrintMonitor(void)
702 {
703 LPMONITOREX res;
704
705 if (!pInitializePrintMonitor) return;
706
707 SetLastError(0xdeadbeef);
708 res = pInitializePrintMonitor(NULL);
709 /* The Parameter was unchecked before w2k */
710 ok( res || (GetLastError() == ERROR_INVALID_PARAMETER),
711 "returned %p with %u\n (expected '!= NULL' or: NULL with "
712 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
713
714 SetLastError(0xdeadbeef);
715 res = pInitializePrintMonitor(emptyW);
716 ok( res || (GetLastError() == ERROR_INVALID_PARAMETER),
717 "returned %p with %u\n (expected '!= NULL' or: NULL with "
718 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
719
720 /* Every call with a non-empty string returns the same Pointer */
721 SetLastError(0xdeadbeef);
722 res = pInitializePrintMonitor(Monitors_LocalPortW);
723 ok( res == pm,
724 "returned %p with %u (expected %p)\n", res, GetLastError(), pm);
725 ok(res->dwMonitorSize == sizeof(MONITOR), "wrong dwMonitorSize %u\n", res->dwMonitorSize);
726 }
727
728 static void test_InitializePrintMonitor2(void)
729 {
730 MONITORINIT init;
731 MONITOR2 *monitor2;
732 HANDLE hmon;
733
734 if (!pInitializePrintMonitor2) return;
735
736 memset(&init, 0, sizeof(init));
737 init.cbSize = sizeof(init);
738 init.hckRegistryRoot = 0;
739 init.pMonitorReg = &monreg;
740 init.bLocal = TRUE;
741
742 monitor2 = pInitializePrintMonitor2(&init, &hmon);
743 ok(monitor2 != NULL, "InitializePrintMonitor2 error %u\n", GetLastError());
744 ok(monitor2->cbSize >= FIELD_OFFSET(MONITOR2, pfnSendRecvBidiDataFromPort), "wrong cbSize %u\n", monitor2->cbSize);
745 }
746
747 /* ########################### */
748
749 static void test_OpenPort(void)
750 {
751 HANDLE hPort;
752 HANDLE hPort2;
753 LPWSTR nameW = NULL;
754 DWORD res;
755 DWORD res2;
756
757 if (!pOpenPort || !pClosePort) return;
758
759 if (have_com[0]) {
760 nameW = have_com;
761
762 hPort = (HANDLE) 0xdeadbeef;
763 SetLastError(0xdeadbeef);
764 res = pOpenPort(nameW, &hPort);
765 ok( res, "got %u with %u and %p (expected '!= 0')\n",
766 res, GetLastError(), hPort);
767
768 /* the same HANDLE is returned for a second OpenPort in native localspl */
769 hPort2 = (HANDLE) 0xdeadbeef;
770 SetLastError(0xdeadbeef);
771 res2 = pOpenPort(nameW, &hPort2);
772 ok( res2, "got %u with %u and %p (expected '!= 0')\n",
773 res2, GetLastError(), hPort2);
774
775 if (res) pClosePort(hPort);
776 if (res2 && (hPort2 != hPort)) pClosePort(hPort2);
777 }
778
779 if (have_lpt[0]) {
780 nameW = have_lpt;
781
782 hPort = (HANDLE) 0xdeadbeef;
783 SetLastError(0xdeadbeef);
784 res = pOpenPort(nameW, &hPort);
785 ok( res || (GetLastError() == ERROR_ACCESS_DENIED),
786 "got %u with %u and %p (expected '!= 0' or '0' with ERROR_ACCESS_DENIED)\n",
787 res, GetLastError(), hPort);
788
789 /* the same HANDLE is returned for a second OpenPort in native localspl */
790 hPort2 = (HANDLE) 0xdeadbeef;
791 SetLastError(0xdeadbeef);
792 res2 = pOpenPort(nameW, &hPort2);
793 ok( res2 || (GetLastError() == ERROR_ACCESS_DENIED),
794 "got %u with %u and %p (expected '!= 0' or '0' with ERROR_ACCESS_DENIED)\n",
795 res2, GetLastError(), hPort2);
796
797 if (res) pClosePort(hPort);
798 if (res2 && (hPort2 != hPort)) pClosePort(hPort2);
799 }
800
801 if (have_file[0]) {
802 nameW = have_file;
803
804 hPort = (HANDLE) 0xdeadbeef;
805 SetLastError(0xdeadbeef);
806 res = pOpenPort(nameW, &hPort);
807 ok( res, "got %u with %u and %p (expected '!= 0')\n",
808 res, GetLastError(), hPort);
809
810 /* a different HANDLE is returned for a second OpenPort */
811 hPort2 = (HANDLE) 0xdeadbeef;
812 SetLastError(0xdeadbeef);
813 res2 = pOpenPort(nameW, &hPort2);
814 ok( res2 && (hPort2 != hPort),
815 "got %u with %u and %p (expected '!= 0' and '!= %p')\n",
816 res2, GetLastError(), hPort2, hPort);
817
818 if (res) pClosePort(hPort);
819 if (res2 && (hPort2 != hPort)) pClosePort(hPort2);
820 }
821
822 if (0) {
823 /* this test crash native localspl (w2k+xp) */
824 if (nameW) {
825 hPort = (HANDLE) 0xdeadbeef;
826 SetLastError(0xdeadbeef);
827 res = pOpenPort(nameW, NULL);
828 trace("got %u with %u and %p\n", res, GetLastError(), hPort);
829 }
830 }
831
832 hPort = (HANDLE) 0xdeadbeef;
833 SetLastError(0xdeadbeef);
834 res = pOpenPort(does_not_existW, &hPort);
835 ok (!res && (hPort == (HANDLE) 0xdeadbeef),
836 "got %u with 0x%x and %p (expected '0' and 0xdeadbeef)\n", res, GetLastError(), hPort);
837 if (res) pClosePort(hPort);
838
839 hPort = (HANDLE) 0xdeadbeef;
840 SetLastError(0xdeadbeef);
841 res = pOpenPort(emptyW, &hPort);
842 ok (!res && (hPort == (HANDLE) 0xdeadbeef),
843 "got %u with 0x%x and %p (expected '0' and 0xdeadbeef)\n", res, GetLastError(), hPort);
844 if (res) pClosePort(hPort);
845
846
847 /* NULL as name crash native localspl (w2k+xp) */
848 if (0) {
849 hPort = (HANDLE) 0xdeadbeef;
850 SetLastError(0xdeadbeef);
851 res = pOpenPort(NULL, &hPort);
852 trace("got %u with %u and %p\n", res, GetLastError(), hPort);
853 }
854
855 }
856
857 /* ########################### */
858
859 static void test_XcvClosePort(void)
860 {
861 DWORD res;
862 HANDLE hXcv2;
863
864
865 if (0)
866 {
867 /* crash with native localspl.dll (w2k+xp) */
868 pXcvClosePort(NULL);
869 pXcvClosePort(INVALID_HANDLE_VALUE);
870 }
871
872
873 SetLastError(0xdeadbeef);
874 hXcv2 = (HANDLE) 0xdeadbeef;
875 res = pXcvOpenPort(emptyW, SERVER_ACCESS_ADMINISTER, &hXcv2);
876 ok(res, "returned %d with %u and %p (expected '!= 0')\n", res, GetLastError(), hXcv2);
877
878 if (res) {
879 SetLastError(0xdeadbeef);
880 res = pXcvClosePort(hXcv2);
881 ok(res, "returned %d with %u (expected '!= 0')\n", res, GetLastError());
882
883 if (0)
884 {
885 /* test for "Double Free": crash with native localspl.dll (w2k+xp) */
886 pXcvClosePort(hXcv2);
887 }
888 }
889 }
890
891 /* ########################### */
892
893 static void test_XcvDataPort_AddPort(void)
894 {
895 DWORD res;
896
897 /*
898 * The following tests crash with native localspl.dll on w2k and xp,
899 * but it works, when the native dll (w2k and xp) is used in wine.
900 * also tested (same crash): replacing emptyW with portname_lpt1W
901 * and replacing "NULL, 0, NULL" with "buffer, MAX_PATH, &needed"
902 *
903 * We need to use a different API (AddPortEx) instead
904 */
905 if (0)
906 {
907 /* create a Port for a normal, writable file */
908 SetLastError(0xdeadbeef);
909 res = pXcvDataPort(hXcv, cmd_AddPortW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, NULL);
910 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
911
912 /* add our testport again */
913 SetLastError(0xdeadbeef);
914 res = pXcvDataPort(hXcv, cmd_AddPortW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, NULL);
915 ok( res == ERROR_ALREADY_EXISTS, "returned %d with %u (expected ERROR_ALREADY_EXISTS)\n", res, GetLastError());
916
917 /* create a well-known Port */
918 SetLastError(0xdeadbeef);
919 res = pXcvDataPort(hXcv, cmd_AddPortW, (PBYTE) portname_lpt1W, (lstrlenW(portname_lpt1W) + 1) * sizeof(WCHAR), NULL, 0, NULL);
920 ok( res == ERROR_ALREADY_EXISTS, "returned %d with %u (expected ERROR_ALREADY_EXISTS)\n", res, GetLastError());
921
922 /* ERROR_ALREADY_EXISTS is also returned from native localspl.dll on wine,
923 when "RPT1:" was already installed for redmonnt.dll:
924 res = pXcvDataPort(hXcv, cmd_AddPortW, (PBYTE) portname_rpt1W, ...
925 */
926
927 /* cleanup */
928 SetLastError(0xdeadbeef);
929 res = pXcvDataPort(hXcv, cmd_DeletePortW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, NULL);
930 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
931 }
932
933 }
934
935 /* ########################### */
936
937 static void test_XcvDataPort_ConfigureLPTPortCommandOK(void)
938 {
939 CHAR org_value[16];
940 CHAR buffer[16];
941 HKEY hroot = NULL;
942 DWORD res;
943 DWORD needed;
944
945
946 /* Read the original value from the registry */
947 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsA, 0, KEY_ALL_ACCESS, &hroot);
948 if (res == ERROR_ACCESS_DENIED) {
949 skip("ACCESS_DENIED\n");
950 return;
951 }
952
953 if (res != ERROR_SUCCESS) {
954 /* unable to open the registry: skip the test */
955 skip("got %d\n", res);
956 return;
957 }
958 org_value[0] = '\0';
959 needed = sizeof(org_value)-1 ;
960 res = RegQueryValueExA(hroot, TransmissionRetryTimeoutA, NULL, NULL, (PBYTE) org_value, &needed);
961 ok( (res == ERROR_SUCCESS) || (res == ERROR_FILE_NOT_FOUND),
962 "returned %u and %u for \"%s\" (expected ERROR_SUCCESS or "
963 "ERROR_FILE_NOT_FOUND)\n", res, needed, org_value);
964
965 RegDeleteValueA(hroot, TransmissionRetryTimeoutA);
966
967 /* set to "0" */
968 needed = (DWORD) 0xdeadbeef;
969 SetLastError(0xdeadbeef);
970 res = pXcvDataPort(hXcv, cmd_ConfigureLPTPortCommandOKW, (PBYTE) num_0W, sizeof(num_0W), NULL, 0, &needed);
971 if (res == ERROR_INVALID_PARAMETER) {
972 skip("'ConfigureLPTPortCommandOK' not supported\n");
973 return;
974 }
975 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
976 needed = sizeof(buffer)-1 ;
977 res = RegQueryValueExA(hroot, TransmissionRetryTimeoutA, NULL, NULL, (PBYTE) buffer, &needed);
978 ok( (res == ERROR_SUCCESS) && (lstrcmpA(buffer, num_0A) == 0),
979 "returned %d and '%s' (expected ERROR_SUCCESS and '%s')\n",
980 res, buffer, num_0A);
981
982
983 /* set to "1" */
984 needed = (DWORD) 0xdeadbeef;
985 SetLastError(0xdeadbeef);
986 res = pXcvDataPort(hXcv, cmd_ConfigureLPTPortCommandOKW, (PBYTE) num_1W, sizeof(num_1W), NULL, 0, &needed);
987 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
988 needed = sizeof(buffer)-1 ;
989 res = RegQueryValueExA(hroot, TransmissionRetryTimeoutA, NULL, NULL, (PBYTE) buffer, &needed);
990 ok( (res == ERROR_SUCCESS) && (lstrcmpA(buffer, num_1A) == 0),
991 "returned %d and '%s' (expected ERROR_SUCCESS and '%s')\n",
992 res, buffer, num_1A);
993
994 /* set to "999999" */
995 needed = (DWORD) 0xdeadbeef;
996 SetLastError(0xdeadbeef);
997 res = pXcvDataPort(hXcv, cmd_ConfigureLPTPortCommandOKW, (PBYTE) num_999999W, sizeof(num_999999W), NULL, 0, &needed);
998 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
999 needed = sizeof(buffer)-1 ;
1000 res = RegQueryValueExA(hroot, TransmissionRetryTimeoutA, NULL, NULL, (PBYTE) buffer, &needed);
1001 ok( (res == ERROR_SUCCESS) && (lstrcmpA(buffer, num_999999A) == 0),
1002 "returned %d and '%s' (expected ERROR_SUCCESS and '%s')\n",
1003 res, buffer, num_999999A);
1004
1005 /* set to "1000000" */
1006 needed = (DWORD) 0xdeadbeef;
1007 SetLastError(0xdeadbeef);
1008 res = pXcvDataPort(hXcv, cmd_ConfigureLPTPortCommandOKW, (PBYTE) num_1000000W, sizeof(num_1000000W), NULL, 0, &needed);
1009 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
1010 needed = sizeof(buffer)-1 ;
1011 res = RegQueryValueExA(hroot, TransmissionRetryTimeoutA, NULL, NULL, (PBYTE) buffer, &needed);
1012 ok( (res == ERROR_SUCCESS) && (lstrcmpA(buffer, num_1000000A) == 0),
1013 "returned %d and '%s' (expected ERROR_SUCCESS and '%s')\n",
1014 res, buffer, num_1000000A);
1015
1016 /* using cmd_ConfigureLPTPortCommandOKW with does_not_existW:
1017 the string "does_not_exist" is written to the registry */
1018
1019
1020 /* restore the original value */
1021 RegDeleteValueA(hroot, TransmissionRetryTimeoutA);
1022 if (org_value[0]) {
1023 res = RegSetValueExA(hroot, TransmissionRetryTimeoutA, 0, REG_SZ, (PBYTE)org_value, lstrlenA(org_value)+1);
1024 ok(res == ERROR_SUCCESS, "unable to restore original value (got %u): %s\n", res, org_value);
1025 }
1026
1027 RegCloseKey(hroot);
1028
1029 }
1030
1031 /* ########################### */
1032
1033 static void test_XcvDataPort_DeletePort(void)
1034 {
1035 DWORD res;
1036 DWORD needed;
1037
1038
1039 /* cleanup: just to make sure */
1040 needed = (DWORD) 0xdeadbeef;
1041 SetLastError(0xdeadbeef);
1042 res = pXcvDataPort(hXcv, cmd_DeletePortW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, &needed);
1043 ok( !res || (res == ERROR_FILE_NOT_FOUND),
1044 "returned %d with %u (expected ERROR_SUCCESS or ERROR_FILE_NOT_FOUND)\n",
1045 res, GetLastError());
1046
1047
1048 /* ToDo: cmd_AddPortW for tempfileW, then cmd_DeletePortW for the existing Port */
1049
1050
1051 /* try to delete a nonexistent Port */
1052 needed = (DWORD) 0xdeadbeef;
1053 SetLastError(0xdeadbeef);
1054 res = pXcvDataPort(hXcv, cmd_DeletePortW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, &needed);
1055 ok( res == ERROR_FILE_NOT_FOUND,
1056 "returned %d with %u (expected ERROR_FILE_NOT_FOUND)\n", res, GetLastError());
1057
1058 /* emptyW as Portname: ERROR_FILE_NOT_FOUND is returned */
1059 /* NULL as Portname: Native localspl.dll crashed */
1060
1061 }
1062
1063 /* ########################### */
1064
1065 static void test_XcvDataPort_GetTransmissionRetryTimeout(void)
1066 {
1067 CHAR org_value[16];
1068 HKEY hroot = NULL;
1069 DWORD buffer[2];
1070 DWORD res;
1071 DWORD needed;
1072 DWORD len;
1073
1074
1075 /* ask for needed size */
1076 needed = (DWORD) 0xdeadbeef;
1077 SetLastError(0xdeadbeef);
1078 res = pXcvDataPort(hXcv, cmd_GetTransmissionRetryTimeoutW, NULL, 0, NULL, 0, &needed);
1079 if (res == ERROR_INVALID_PARAMETER) {
1080 skip("'GetTransmissionRetryTimeout' not supported\n");
1081 return;
1082 }
1083 len = sizeof(DWORD);
1084 ok( (res == ERROR_INSUFFICIENT_BUFFER) && (needed == len),
1085 "returned %d with %u and %u (expected ERROR_INSUFFICIENT_BUFFER "
1086 "and '%u')\n", res, GetLastError(), needed, len);
1087 len = needed;
1088
1089 /* Read the original value from the registry */
1090 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsA, 0, KEY_ALL_ACCESS, &hroot);
1091 if (res == ERROR_ACCESS_DENIED) {
1092 skip("ACCESS_DENIED\n");
1093 return;
1094 }
1095
1096 if (res != ERROR_SUCCESS) {
1097 /* unable to open the registry: skip the test */
1098 skip("got %d\n", res);
1099 return;
1100 }
1101
1102 org_value[0] = '\0';
1103 needed = sizeof(org_value)-1 ;
1104 res = RegQueryValueExA(hroot, TransmissionRetryTimeoutA, NULL, NULL, (PBYTE) org_value, &needed);
1105 ok( (res == ERROR_SUCCESS) || (res == ERROR_FILE_NOT_FOUND),
1106 "returned %u and %u for \"%s\" (expected ERROR_SUCCESS or "
1107 "ERROR_FILE_NOT_FOUND)\n", res, needed, org_value);
1108
1109 /* Get default value (documented as 90 in the w2k reskit, but that is wrong) */
1110 RegDeleteValueA(hroot, TransmissionRetryTimeoutA);
1111 needed = (DWORD) 0xdeadbeef;
1112 buffer[0] = 0xdeadbeef;
1113 SetLastError(0xdeadbeef);
1114 res = pXcvDataPort(hXcv, cmd_GetTransmissionRetryTimeoutW, NULL, 0, (PBYTE) buffer, len, &needed);
1115 ok( (res == ERROR_SUCCESS) && (buffer[0] == 45),
1116 "returned %d with %u and %u for %d\n (expected ERROR_SUCCESS "
1117 "for '45')\n", res, GetLastError(), needed, buffer[0]);
1118
1119 /* the default timeout is returned, when the value is empty */
1120 res = RegSetValueExA(hroot, TransmissionRetryTimeoutA, 0, REG_SZ, (PBYTE)emptyA, 1);
1121 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
1122 needed = (DWORD) 0xdeadbeef;
1123 buffer[0] = 0xdeadbeef;
1124 SetLastError(0xdeadbeef);
1125 res = pXcvDataPort(hXcv, cmd_GetTransmissionRetryTimeoutW, NULL, 0, (PBYTE) buffer, len, &needed);
1126 ok( (res == ERROR_SUCCESS) && (buffer[0] == 45),
1127 "returned %d with %u and %u for %d\n (expected ERROR_SUCCESS "
1128 "for '45')\n", res, GetLastError(), needed, buffer[0]);
1129
1130 /* the dialog is limited (1 - 999999), but that is done somewhere else */
1131 res = RegSetValueExA(hroot, TransmissionRetryTimeoutA, 0, REG_SZ, (PBYTE)num_0A, lstrlenA(num_0A)+1);
1132 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
1133 needed = (DWORD) 0xdeadbeef;
1134 buffer[0] = 0xdeadbeef;
1135 SetLastError(0xdeadbeef);
1136 res = pXcvDataPort(hXcv, cmd_GetTransmissionRetryTimeoutW, NULL, 0, (PBYTE) buffer, len, &needed);
1137 ok( (res == ERROR_SUCCESS) && (buffer[0] == 0),
1138 "returned %d with %u and %u for %d\n (expected ERROR_SUCCESS "
1139 "for '0')\n", res, GetLastError(), needed, buffer[0]);
1140
1141
1142 res = RegSetValueExA(hroot, TransmissionRetryTimeoutA, 0, REG_SZ, (PBYTE)num_1A, lstrlenA(num_1A)+1);
1143 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
1144 needed = (DWORD) 0xdeadbeef;
1145 buffer[0] = 0xdeadbeef;
1146 SetLastError(0xdeadbeef);
1147 res = pXcvDataPort(hXcv, cmd_GetTransmissionRetryTimeoutW, NULL, 0, (PBYTE) buffer, len, &needed);
1148 ok( (res == ERROR_SUCCESS) && (buffer[0] == 1),
1149 "returned %d with %u and %u for %d\n (expected 'ERROR_SUCCESS' "
1150 "for '1')\n", res, GetLastError(), needed, buffer[0]);
1151
1152 res = RegSetValueExA(hroot, TransmissionRetryTimeoutA, 0, REG_SZ, (PBYTE)num_999999A, lstrlenA(num_999999A)+1);
1153 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
1154 needed = (DWORD) 0xdeadbeef;
1155 buffer[0] = 0xdeadbeef;
1156 SetLastError(0xdeadbeef);
1157 res = pXcvDataPort(hXcv, cmd_GetTransmissionRetryTimeoutW, NULL, 0, (PBYTE) buffer, len, &needed);
1158 ok( (res == ERROR_SUCCESS) && (buffer[0] == 999999),
1159 "returned %d with %u and %u for %d\n (expected ERROR_SUCCESS "
1160 "for '999999')\n", res, GetLastError(), needed, buffer[0]);
1161
1162
1163 res = RegSetValueExA(hroot, TransmissionRetryTimeoutA, 0, REG_SZ, (PBYTE)num_1000000A, lstrlenA(num_1000000A)+1);
1164 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
1165 needed = (DWORD) 0xdeadbeef;
1166 buffer[0] = 0xdeadbeef;
1167 SetLastError(0xdeadbeef);
1168 res = pXcvDataPort(hXcv, cmd_GetTransmissionRetryTimeoutW, NULL, 0, (PBYTE) buffer, len, &needed);
1169 ok( (res == ERROR_SUCCESS) && (buffer[0] == 1000000),
1170 "returned %d with %u and %u for %d\n (expected ERROR_SUCCESS "
1171 "for '1000000')\n", res, GetLastError(), needed, buffer[0]);
1172
1173 /* restore the original value */
1174 RegDeleteValueA(hroot, TransmissionRetryTimeoutA);
1175 if (org_value[0]) {
1176 res = RegSetValueExA(hroot, TransmissionRetryTimeoutA, 0, REG_SZ, (PBYTE)org_value, lstrlenA(org_value)+1);
1177 ok(res == ERROR_SUCCESS, "unable to restore original value (got %u): %s\n", res, org_value);
1178 }
1179
1180 RegCloseKey(hroot);
1181 }
1182
1183 /* ########################### */
1184
1185 static void test_XcvDataPort_MonitorUI(void)
1186 {
1187 DWORD res;
1188 BYTE buffer[MAX_PATH + 2];
1189 DWORD needed;
1190 DWORD len;
1191
1192
1193 /* ask for needed size */
1194 needed = (DWORD) 0xdeadbeef;
1195 SetLastError(0xdeadbeef);
1196 res = pXcvDataPort(hXcv, cmd_MonitorUIW, NULL, 0, NULL, 0, &needed);
1197 if (res == ERROR_INVALID_PARAMETER) {
1198 skip("'MonitorUI' nor supported\n");
1199 return;
1200 }
1201 ok( (res == ERROR_INSUFFICIENT_BUFFER) && (needed <= MAX_PATH),
1202 "returned %d with %u and 0x%x (expected 'ERROR_INSUFFICIENT_BUFFER' "
1203 " and '<= MAX_PATH')\n", res, GetLastError(), needed);
1204
1205 if (needed > MAX_PATH) {
1206 skip("buffer overflow (%u)\n", needed);
1207 return;
1208 }
1209 len = needed;
1210
1211 /* the command is required */
1212 needed = (DWORD) 0xdeadbeef;
1213 SetLastError(0xdeadbeef);
1214 res = pXcvDataPort(hXcv, emptyW, NULL, 0, NULL, 0, &needed);
1215 ok( res == ERROR_INVALID_PARAMETER, "returned %d with %u and 0x%x "
1216 "(expected 'ERROR_INVALID_PARAMETER')\n", res, GetLastError(), needed);
1217
1218 if (0) {
1219 /* crash with native localspl.dll (w2k+xp) */
1220 pXcvDataPort(hXcv, NULL, NULL, 0, buffer, MAX_PATH, &needed);
1221 pXcvDataPort(hXcv, cmd_MonitorUIW, NULL, 0, NULL, len, &needed);
1222 pXcvDataPort(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, NULL);
1223 }
1224
1225
1226 /* hXcv is ignored for the command "MonitorUI" */
1227 needed = (DWORD) 0xdeadbeef;
1228 SetLastError(0xdeadbeef);
1229 res = pXcvDataPort(NULL, cmd_MonitorUIW, NULL, 0, buffer, len, &needed);
1230 ok( res == ERROR_SUCCESS, "returned %d with %u and 0x%x "
1231 "(expected 'ERROR_SUCCESS')\n", res, GetLastError(), needed);
1232
1233
1234 /* pszDataName is case-sensitive */
1235 memset(buffer, 0, len);
1236 needed = (DWORD) 0xdeadbeef;
1237 SetLastError(0xdeadbeef);
1238 res = pXcvDataPort(hXcv, cmd_MonitorUI_lcaseW, NULL, 0, buffer, len, &needed);
1239 ok( res == ERROR_INVALID_PARAMETER, "returned %d with %u and 0x%x "
1240 "(expected 'ERROR_INVALID_PARAMETER')\n", res, GetLastError(), needed);
1241
1242 /* off by one: larger */
1243 needed = (DWORD) 0xdeadbeef;
1244 SetLastError(0xdeadbeef);
1245 res = pXcvDataPort(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len+1, &needed);
1246 ok( res == ERROR_SUCCESS, "returned %d with %u and 0x%x "
1247 "(expected 'ERROR_SUCCESS')\n", res, GetLastError(), needed);
1248
1249
1250 /* off by one: smaller */
1251 /* the buffer is not modified for NT4, w2k, XP */
1252 needed = (DWORD) 0xdeadbeef;
1253 SetLastError(0xdeadbeef);
1254 res = pXcvDataPort(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len-1, &needed);
1255 ok( res == ERROR_INSUFFICIENT_BUFFER, "returned %d with %u and 0x%x "
1256 "(expected 'ERROR_INSUFFICIENT_BUFFER')\n", res, GetLastError(), needed);
1257
1258 /* Normal use. The DLL-Name without a Path is returned */
1259 memset(buffer, 0, len);
1260 needed = (DWORD) 0xdeadbeef;
1261 SetLastError(0xdeadbeef);
1262 res = pXcvDataPort(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, &needed);
1263 ok( res == ERROR_SUCCESS, "returned %d with %u and 0x%x "
1264 "(expected 'ERROR_SUCCESS')\n", res, GetLastError(), needed);
1265
1266
1267 /* small check without access-rights: */
1268 if (!hXcv_noaccess) return;
1269
1270 /* The ACCESS_MASK is ignored for "MonitorUI" */
1271 memset(buffer, 0, len);
1272 needed = (DWORD) 0xdeadbeef;
1273 SetLastError(0xdeadbeef);
1274 res = pXcvDataPort(hXcv_noaccess, cmd_MonitorUIW, NULL, 0, buffer, sizeof(buffer), &needed);
1275 ok( res == ERROR_SUCCESS, "returned %d with %u and 0x%x "
1276 "(expected 'ERROR_SUCCESS')\n", res, GetLastError(), needed);
1277 }
1278
1279 /* ########################### */
1280
1281 static void test_XcvDataPort_PortIsValid(void)
1282 {
1283 DWORD res;
1284 DWORD needed;
1285
1286 /* normal use: "LPT1:" */
1287 needed = (DWORD) 0xdeadbeef;
1288 SetLastError(0xdeadbeef);
1289 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, &needed);
1290 if (res == ERROR_INVALID_PARAMETER) {
1291 skip("'PostIsValid' not supported\n");
1292 return;
1293 }
1294 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
1295
1296
1297 if (0) {
1298 /* crash with native localspl.dll (w2k+xp) */
1299 pXcvDataPort(hXcv, cmd_PortIsValidW, NULL, 0, NULL, 0, &needed);
1300 }
1301
1302
1303 /* hXcv is ignored for the command "PortIsValid" */
1304 needed = (DWORD) 0xdeadbeef;
1305 SetLastError(0xdeadbeef);
1306 res = pXcvDataPort(NULL, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, NULL);
1307 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
1308
1309 /* needed is ignored */
1310 needed = (DWORD) 0xdeadbeef;
1311 SetLastError(0xdeadbeef);
1312 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, NULL);
1313 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
1314
1315
1316 /* cbInputData is ignored */
1317 needed = (DWORD) 0xdeadbeef;
1318 SetLastError(0xdeadbeef);
1319 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, 0, NULL, 0, &needed);
1320 ok( res == ERROR_SUCCESS,
1321 "returned %d with %u and 0x%x (expected ERROR_SUCCESS)\n",
1322 res, GetLastError(), needed);
1323
1324 needed = (DWORD) 0xdeadbeef;
1325 SetLastError(0xdeadbeef);
1326 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, 1, NULL, 0, &needed);
1327 ok( res == ERROR_SUCCESS,
1328 "returned %d with %u and 0x%x (expected ERROR_SUCCESS)\n",
1329 res, GetLastError(), needed);
1330
1331 needed = (DWORD) 0xdeadbeef;
1332 SetLastError(0xdeadbeef);
1333 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W) -1, NULL, 0, &needed);
1334 ok( res == ERROR_SUCCESS,
1335 "returned %d with %u and 0x%x (expected ERROR_SUCCESS)\n",
1336 res, GetLastError(), needed);
1337
1338 needed = (DWORD) 0xdeadbeef;
1339 SetLastError(0xdeadbeef);
1340 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W) -2, NULL, 0, &needed);
1341 ok( res == ERROR_SUCCESS,
1342 "returned %d with %u and 0x%x (expected ERROR_SUCCESS)\n",
1343 res, GetLastError(), needed);
1344
1345
1346 /* an empty name is not allowed */
1347 needed = (DWORD) 0xdeadbeef;
1348 SetLastError(0xdeadbeef);
1349 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) emptyW, sizeof(emptyW), NULL, 0, &needed);
1350 ok( res == ERROR_PATH_NOT_FOUND,
1351 "returned %d with %u and 0x%x (expected ERROR_PATH_NOT_FOUND)\n",
1352 res, GetLastError(), needed);
1353
1354
1355 /* a directory is not allowed */
1356 needed = (DWORD) 0xdeadbeef;
1357 SetLastError(0xdeadbeef);
1358 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) tempdirW, (lstrlenW(tempdirW) + 1) * sizeof(WCHAR), NULL, 0, &needed);
1359 /* XP(admin): ERROR_INVALID_NAME, XP(user): ERROR_PATH_NOT_FOUND, w2k ERROR_ACCESS_DENIED */
1360 ok( (res == ERROR_INVALID_NAME) || (res == ERROR_PATH_NOT_FOUND) ||
1361 (res == ERROR_ACCESS_DENIED), "returned %d with %u and 0x%x "
1362 "(expected ERROR_INVALID_NAME, ERROR_PATH_NOT_FOUND or ERROR_ACCESS_DENIED)\n",
1363 res, GetLastError(), needed);
1364
1365
1366 /* test more valid well known Ports: */
1367 needed = (DWORD) 0xdeadbeef;
1368 SetLastError(0xdeadbeef);
1369 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt2W, sizeof(portname_lpt2W), NULL, 0, &needed);
1370 ok( res == ERROR_SUCCESS,
1371 "returned %d with %u and 0x%x (expected ERROR_SUCCESS)\n",
1372 res, GetLastError(), needed);
1373
1374
1375 needed = (DWORD) 0xdeadbeef;
1376 SetLastError(0xdeadbeef);
1377 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_com1W, sizeof(portname_com1W), NULL, 0, &needed);
1378 ok( res == ERROR_SUCCESS,
1379 "returned %d with %u and 0x%x (expected ERROR_SUCCESS)\n",
1380 res, GetLastError(), needed);
1381
1382
1383 needed = (DWORD) 0xdeadbeef;
1384 SetLastError(0xdeadbeef);
1385 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_com2W, sizeof(portname_com2W), NULL, 0, &needed);
1386 ok( res == ERROR_SUCCESS,
1387 "returned %d with %u and 0x%x (expected ERROR_SUCCESS)\n",
1388 res, GetLastError(), needed);
1389
1390
1391 needed = (DWORD) 0xdeadbeef;
1392 SetLastError(0xdeadbeef);
1393 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) portname_fileW, sizeof(portname_fileW), NULL, 0, &needed);
1394 ok( res == ERROR_SUCCESS,
1395 "returned %d with %u and 0x%x (expected ERROR_SUCCESS)\n",
1396 res, GetLastError(), needed);
1397
1398
1399 /* a normal, writable file is allowed */
1400 needed = (DWORD) 0xdeadbeef;
1401 SetLastError(0xdeadbeef);
1402 res = pXcvDataPort(hXcv, cmd_PortIsValidW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, &needed);
1403 ok( res == ERROR_SUCCESS,
1404 "returned %d with %u and 0x%x (expected ERROR_SUCCESS)\n",
1405 res, GetLastError(), needed);
1406
1407
1408 /* small check without access-rights: */
1409 if (!hXcv_noaccess) return;
1410
1411 /* The ACCESS_MASK from XcvOpenPort is ignored in "PortIsValid" */
1412 needed = (DWORD) 0xdeadbeef;
1413 SetLastError(0xdeadbeef);
1414 res = pXcvDataPort(hXcv_noaccess, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, &needed);
1415 ok( res == ERROR_SUCCESS, "returned %d with %u (expected ERROR_SUCCESS)\n", res, GetLastError());
1416
1417 }
1418
1419 /* ########################### */
1420
1421 static void test_XcvOpenPort(void)
1422 {
1423 DWORD res;
1424 HANDLE hXcv2;
1425
1426
1427 if (0)
1428 {
1429 /* crash with native localspl.dll (w2k+xp) */
1430 pXcvOpenPort(NULL, SERVER_ACCESS_ADMINISTER, &hXcv2);
1431 pXcvOpenPort(emptyW, SERVER_ACCESS_ADMINISTER, NULL);
1432 }
1433
1434
1435 /* The returned handle is the result from a previous "spoolss.dll,DllAllocSplMem" */
1436 SetLastError(0xdeadbeef);
1437 hXcv2 = (HANDLE) 0xdeadbeef;
1438 res = pXcvOpenPort(emptyW, SERVER_ACCESS_ADMINISTER, &hXcv2);
1439 ok(res, "returned %d with %u and %p (expected '!= 0')\n", res, GetLastError(), hXcv2);
1440 if (res) pXcvClosePort(hXcv2);
1441
1442
1443 /* The ACCESS_MASK is not checked in XcvOpenPort */
1444 SetLastError(0xdeadbeef);
1445 hXcv2 = (HANDLE) 0xdeadbeef;
1446 res = pXcvOpenPort(emptyW, 0, &hXcv2);
1447 ok(res, "returned %d with %u and %p (expected '!= 0')\n", res, GetLastError(), hXcv2);
1448 if (res) pXcvClosePort(hXcv2);
1449
1450
1451 /* A copy of pszObject is saved in the Memory-Block */
1452 SetLastError(0xdeadbeef);
1453 hXcv2 = (HANDLE) 0xdeadbeef;
1454 res = pXcvOpenPort(portname_lpt1W, SERVER_ALL_ACCESS, &hXcv2);
1455 ok(res, "returned %d with %u and %p (expected '!= 0')\n", res, GetLastError(), hXcv2);
1456 if (res) pXcvClosePort(hXcv2);
1457
1458 SetLastError(0xdeadbeef);
1459 hXcv2 = (HANDLE) 0xdeadbeef;
1460 res = pXcvOpenPort(portname_fileW, SERVER_ALL_ACCESS, &hXcv2);
1461 ok(res, "returned %d with %u and %p (expected '!= 0')\n", res, GetLastError(), hXcv2);
1462 if (res) pXcvClosePort(hXcv2);
1463
1464 }
1465
1466 /* ########################### */
1467
1468 #define GET_MONITOR_FUNC(name) \
1469 if (pm) p##name = pm->Monitor.pfn##name; \
1470 else if (pm2) p##name = pm2->pfn##name;
1471
1472 #define GET_MONITOR_FUNC2(name) \
1473 if (pm) p##name = pm->Monitor.pfn##name; \
1474 else if (pm2) p##name##2 = pm2->pfn##name;
1475
1476 START_TEST(localmon)
1477 {
1478 DWORD numentries;
1479 DWORD res;
1480
1481 LoadLibraryA("winspool.drv");
1482 /* This DLL does not exist on Win9x */
1483 hdll = LoadLibraryA("localspl.dll");
1484 if (!hdll) {
1485 skip("localspl.dll cannot be loaded, most likely running on Win9x\n");
1486 return;
1487 }
1488
1489 tempdirW[0] = '\0';
1490 tempfileW[0] = '\0';
1491 res = GetTempPathW(MAX_PATH, tempdirW);
1492 ok(res != 0, "with %u\n", GetLastError());
1493 res = GetTempFileNameW(tempdirW, wineW, 0, tempfileW);
1494 ok(res != 0, "with %u\n", GetLastError());
1495
1496 pInitializePrintMonitor = (void *) GetProcAddress(hdll, "InitializePrintMonitor");
1497 pInitializePrintMonitor2 = (void *) GetProcAddress(hdll, "InitializePrintMonitor2");
1498
1499 if (!pInitializePrintMonitor) {
1500 /* The Monitor for "Local Ports" was in a separate dll before w2k */
1501 hlocalmon = LoadLibraryA("localmon.dll");
1502 if (hlocalmon) {
1503 pInitializePrintMonitor = (void *) GetProcAddress(hlocalmon, "InitializePrintMonitor");
1504 }
1505 }
1506 if (!pInitializePrintMonitor && !pInitializePrintMonitor2) {
1507 skip("InitializePrintMonitor or InitializePrintMonitor2 not found\n");
1508 return;
1509 }
1510
1511 /* Native localmon.dll / localspl.dll need a valid Port-Entry in:
1512 a) since xp: HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports
1513 b) up to w2k: Section "Ports" in win.ini
1514 or InitializePrintMonitor fails. */
1515 if (pInitializePrintMonitor)
1516 pm = pInitializePrintMonitor(Monitors_LocalPortW);
1517 else if (pInitializePrintMonitor2) {
1518 MONITORINIT init;
1519
1520 memset(&init, 0, sizeof(init));
1521 init.cbSize = sizeof(init);
1522 init.hckRegistryRoot = 0;
1523 init.pMonitorReg = &monreg;
1524 init.bLocal = TRUE;
1525
1526 pm2 = pInitializePrintMonitor2(&init, &hmon);
1527 ok(pm2 != NULL, "InitializePrintMonitor2 error %u\n", GetLastError());
1528 ok(pm2->cbSize >= FIELD_OFFSET(MONITOR2, pfnSendRecvBidiDataFromPort), "wrong cbSize %u\n", pm2->cbSize);
1529 }
1530
1531 if (pm || pm2) {
1532 if (pm) {
1533 ok(pm->dwMonitorSize == sizeof(MONITOR), "wrong dwMonitorSize %u\n", pm->dwMonitorSize);
1534 numentries = (pm->dwMonitorSize ) / sizeof(VOID *);
1535 /* NT4: 14, since w2k: 17 */
1536 ok( numentries == 14 || numentries == 17,
1537 "dwMonitorSize (%u) => %u Functions\n", pm->dwMonitorSize, numentries);
1538 }
1539 else if (pm2) {
1540 numentries = (pm2->cbSize ) / sizeof(VOID *);
1541 ok( numentries >= 20,
1542 "cbSize (%u) => %u Functions\n", pm2->cbSize, numentries);
1543 }
1544
1545 GET_MONITOR_FUNC2(EnumPorts);
1546 GET_MONITOR_FUNC2(OpenPort);
1547 GET_MONITOR_FUNC2(OpenPortEx);
1548 GET_MONITOR_FUNC(StartDocPort);
1549 GET_MONITOR_FUNC(WritePort);
1550 GET_MONITOR_FUNC(ReadPort);
1551 GET_MONITOR_FUNC(EndDocPort);
1552 GET_MONITOR_FUNC(ClosePort);
1553 GET_MONITOR_FUNC2(AddPort);
1554 GET_MONITOR_FUNC2(AddPortEx);
1555 GET_MONITOR_FUNC2(ConfigurePort);
1556 GET_MONITOR_FUNC2(DeletePort);
1557 GET_MONITOR_FUNC(GetPrinterDataFromPort);
1558 GET_MONITOR_FUNC(SetPortTimeOuts);
1559 GET_MONITOR_FUNC2(XcvOpenPort);
1560 GET_MONITOR_FUNC(XcvDataPort);
1561 GET_MONITOR_FUNC(XcvClosePort);
1562
1563 if ((pXcvOpenPort) && (pXcvDataPort) && (pXcvClosePort)) {
1564 SetLastError(0xdeadbeef);
1565 res = pXcvOpenPort(emptyW, SERVER_ACCESS_ADMINISTER, &hXcv);
1566 ok(res, "hXcv: %d with %u and %p (expected '!= 0')\n", res, GetLastError(), hXcv);
1567
1568 SetLastError(0xdeadbeef);
1569 res = pXcvOpenPort(emptyW, 0, &hXcv_noaccess);
1570 ok(res, "hXcv_noaccess: %d with %u and %p (expected '!= 0')\n", res, GetLastError(), hXcv_noaccess);
1571 }
1572 }
1573
1574 test_InitializePrintMonitor();
1575 test_InitializePrintMonitor2();
1576
1577 find_installed_ports();
1578
1579 test_AddPort();
1580 test_AddPortEx();
1581 test_ClosePort();
1582 test_ConfigurePort();
1583 test_DeletePort();
1584 test_EnumPorts();
1585 test_OpenPort();
1586
1587 if ( !hXcv ) {
1588 skip("Xcv not supported\n");
1589 }
1590 else
1591 {
1592 test_XcvClosePort();
1593 test_XcvDataPort_AddPort();
1594 test_XcvDataPort_ConfigureLPTPortCommandOK();
1595 test_XcvDataPort_DeletePort();
1596 test_XcvDataPort_GetTransmissionRetryTimeout();
1597 test_XcvDataPort_MonitorUI();
1598 test_XcvDataPort_PortIsValid();
1599 test_XcvOpenPort();
1600
1601 pXcvClosePort(hXcv);
1602 }
1603 if (hXcv_noaccess) pXcvClosePort(hXcv_noaccess);
1604
1605 /* Cleanup our temporary file */
1606 DeleteFileW(tempfileW);
1607 }