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 } 1608