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
CreateKey(HANDLE hcKey,LPCWSTR pszSubKey,DWORD dwOptions,REGSAM samDesired,PSECURITY_ATTRIBUTES pSecurityAttributes,PHANDLE phckResult,PDWORD pdwDisposition,HANDLE hSpooler)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
OpenKey(HANDLE hcKey,LPCWSTR pszSubKey,REGSAM samDesired,PHANDLE phkResult,HANDLE hSpooler)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
CloseKey(HANDLE hcKey,HANDLE hSpooler)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
DeleteKey(HANDLE hcKey,LPCWSTR pszSubKey,HANDLE hSpooler)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
EnumKey(HANDLE hcKey,DWORD dwIndex,LPWSTR pszName,PDWORD pcchName,PFILETIME pftLastWriteTime,HANDLE hSpooler)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
QueryInfoKey(HANDLE hcKey,PDWORD pcSubKeys,PDWORD pcbKey,PDWORD pcValues,PDWORD pcbValue,PDWORD pcbData,PDWORD pcbSecurityDescriptor,PFILETIME pftLastWriteTime,HANDLE hSpooler)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
SetValue(HANDLE hcKey,LPCWSTR pszValue,DWORD dwType,const BYTE * pData,DWORD cbData,HANDLE hSpooler)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
DeleteValue(HANDLE hcKey,LPCWSTR pszValue,HANDLE hSpooler)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
EnumValue(HANDLE hcKey,DWORD dwIndex,LPWSTR pszValue,PDWORD pcbValue,PDWORD pType,PBYTE pData,PDWORD pcbData,HANDLE hSpooler)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
QueryValue(HANDLE hcKey,LPCWSTR pszValue,PDWORD pType,PBYTE pData,PDWORD pcbData,HANDLE hSpooler)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
delete_port(LPWSTR portname)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
find_installed_ports(void)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
test_AddPort(void)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
test_AddPortEx(void)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
test_ClosePort(void)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
test_ConfigurePort(void)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
test_DeletePort(void)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
test_EnumPorts(void)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
test_InitializePrintMonitor(void)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
test_InitializePrintMonitor2(void)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
test_OpenPort(void)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
test_XcvClosePort(void)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
test_XcvDataPort_AddPort(void)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
test_XcvDataPort_ConfigureLPTPortCommandOK(void)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
test_XcvDataPort_DeletePort(void)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
test_XcvDataPort_GetTransmissionRetryTimeout(void)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
test_XcvDataPort_MonitorUI(void)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
test_XcvDataPort_PortIsValid(void)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
test_XcvOpenPort(void)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
START_TEST(localmon)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 }
1608