1 /* 2 * Implementation of the Local Printmonitor User Interface 3 * 4 * Copyright 2007 Detlef Riekenberg 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #ifdef __REACTOS__ 23 #include <wchar.h> 24 #endif 25 26 #include "windef.h" 27 #include "winbase.h" 28 #include "wingdi.h" 29 #include "winreg.h" 30 #include "winuser.h" 31 32 #include "winspool.h" 33 #include "ddk/winsplp.h" 34 35 #include "wine/debug.h" 36 #include "localui.h" 37 38 WINE_DEFAULT_DEBUG_CHANNEL(localui); 39 40 /*****************************************************/ 41 42 static HINSTANCE LOCALUI_hInstance; 43 44 static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0}; 45 static const WCHAR cmd_ConfigureLPTPortCommandOKW[] = {'C','o','n','f','i','g','u','r','e', 46 'L','P','T','P','o','r','t', 47 'C','o','m','m','a','n','d','O','K',0}; 48 static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0}; 49 static const WCHAR cmd_GetDefaultCommConfigW[] = {'G','e','t', 50 'D','e','f','a','u','l','t', 51 'C','o','m','m','C','o','n','f','i','g',0}; 52 static const WCHAR cmd_GetTransmissionRetryTimeoutW[] = {'G','e','t', 53 'T','r','a','n','s','m','i','s','s','i','o','n', 54 'R','e','t','r','y','T','i','m','e','o','u','t',0}; 55 static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0}; 56 static const WCHAR cmd_SetDefaultCommConfigW[] = {'S','e','t', 57 'D','e','f','a','u','l','t', 58 'C','o','m','m','C','o','n','f','i','g',0}; 59 60 static const WCHAR fmt_uW[] = {'%','u',0}; 61 static const WCHAR portname_LPT[] = {'L','P','T',0}; 62 static const WCHAR portname_COM[] = {'C','O','M',0}; 63 static const WCHAR portname_FILE[] = {'F','I','L','E',':',0}; 64 static const WCHAR portname_CUPS[] = {'C','U','P','S',':',0}; 65 static const WCHAR portname_LPR[] = {'L','P','R',':',0}; 66 67 static const WCHAR XcvMonitorW[] = {',','X','c','v','M','o','n','i','t','o','r',' ',0}; 68 static const WCHAR XcvPortW[] = {',','X','c','v','P','o','r','t',' ',0}; 69 70 /*****************************************************/ 71 72 typedef struct tag_addportui_t { 73 LPWSTR portname; 74 HANDLE hXcv; 75 } addportui_t; 76 77 typedef struct tag_lptconfig_t { 78 HANDLE hXcv; 79 DWORD value; 80 } lptconfig_t; 81 82 83 static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); 84 85 /***************************************************** 86 * strdupWW [internal] 87 */ 88 89 static LPWSTR strdupWW(LPCWSTR pPrefix, LPCWSTR pSuffix) 90 { 91 LPWSTR ptr; 92 DWORD len; 93 94 len = lstrlenW(pPrefix) + (pSuffix ? lstrlenW(pSuffix) : 0) + 1; 95 ptr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 96 if (ptr) { 97 lstrcpyW(ptr, pPrefix); 98 if (pSuffix) lstrcatW(ptr, pSuffix); 99 } 100 return ptr; 101 } 102 103 /***************************************************** 104 * dlg_configure_com [internal] 105 * 106 */ 107 108 static BOOL dlg_configure_com(HANDLE hXcv, HWND hWnd, PCWSTR pPortName) 109 { 110 COMMCONFIG cfg; 111 LPWSTR shortname; 112 DWORD status; 113 DWORD dummy; 114 DWORD len; 115 BOOL res; 116 117 /* strip the colon (pPortName is never empty here) */ 118 len = lstrlenW(pPortName); 119 shortname = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 120 if (shortname) { 121 memcpy(shortname, pPortName, (len -1) * sizeof(WCHAR)); 122 shortname[len-1] = '\0'; 123 124 /* get current settings */ 125 len = FIELD_OFFSET(COMMCONFIG, wcProviderData[1]); 126 status = ERROR_SUCCESS; 127 res = XcvDataW( hXcv, cmd_GetDefaultCommConfigW, 128 (PBYTE) shortname, 129 (lstrlenW(shortname) +1) * sizeof(WCHAR), 130 (PBYTE) &cfg, len, &len, &status); 131 132 if (res && (status == ERROR_SUCCESS)) { 133 /* display the Dialog */ 134 res = CommConfigDialogW(pPortName, hWnd, &cfg); 135 if (res) { 136 status = ERROR_SUCCESS; 137 /* set new settings */ 138 res = XcvDataW(hXcv, cmd_SetDefaultCommConfigW, 139 (PBYTE) &cfg, len, 140 (PBYTE) &dummy, 0, &len, &status); 141 } 142 } 143 HeapFree(GetProcessHeap(), 0, shortname); 144 return res; 145 } 146 return FALSE; 147 } 148 149 150 /***************************************************** 151 * dlg_configure_lpt [internal] 152 * 153 */ 154 155 static BOOL dlg_configure_lpt(HANDLE hXcv, HWND hWnd) 156 { 157 lptconfig_t data; 158 BOOL res; 159 160 161 data.hXcv = hXcv; 162 163 res = DialogBoxParamW(LOCALUI_hInstance, MAKEINTRESOURCEW(LPTCONFIG_DIALOG), hWnd, 164 dlgproc_lptconfig, (LPARAM) &data); 165 166 TRACE("got %u with %u\n", res, GetLastError()); 167 168 if (!res) SetLastError(ERROR_CANCELLED); 169 return res; 170 } 171 172 /****************************************************************** 173 * dlg_port_already_exists [internal] 174 */ 175 176 static void dlg_port_already_exists(HWND hWnd, LPCWSTR portname) 177 { 178 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN]; 179 WCHAR res_PortExistsW[IDS_PORTEXISTS_MAXLEN]; 180 LPWSTR message; 181 DWORD len; 182 183 res_PortW[0] = '\0'; 184 res_PortExistsW[0] = '\0'; 185 LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN); 186 LoadStringW(LOCALUI_hInstance, IDS_PORTEXISTS, res_PortExistsW, IDS_PORTEXISTS_MAXLEN); 187 188 len = lstrlenW(portname) + IDS_PORTEXISTS_MAXLEN + 1; 189 message = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 190 if (message) { 191 message[0] = '\0'; 192 swprintf(message, res_PortExistsW, portname); 193 MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR); 194 HeapFree(GetProcessHeap(), 0, message); 195 } 196 } 197 198 /****************************************************************** 199 * dlg_invalid_portname [internal] 200 */ 201 202 static void dlg_invalid_portname(HWND hWnd, LPCWSTR portname) 203 { 204 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN]; 205 WCHAR res_InvalidNameW[IDS_INVALIDNAME_MAXLEN]; 206 LPWSTR message; 207 DWORD len; 208 209 res_PortW[0] = '\0'; 210 res_InvalidNameW[0] = '\0'; 211 LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN); 212 LoadStringW(LOCALUI_hInstance, IDS_INVALIDNAME, res_InvalidNameW, IDS_INVALIDNAME_MAXLEN); 213 214 len = lstrlenW(portname) + IDS_INVALIDNAME_MAXLEN; 215 message = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 216 if (message) { 217 message[0] = '\0'; 218 swprintf(message, res_InvalidNameW, portname); 219 MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR); 220 HeapFree(GetProcessHeap(), 0, message); 221 } 222 } 223 224 /****************************************************************** 225 * display the Dialog "Nothing to configure" 226 * 227 */ 228 229 static void dlg_nothingtoconfig(HWND hWnd) 230 { 231 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN]; 232 WCHAR res_nothingW[IDS_NOTHINGTOCONFIG_MAXLEN]; 233 234 res_PortW[0] = '\0'; 235 res_nothingW[0] = '\0'; 236 LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN); 237 LoadStringW(LOCALUI_hInstance, IDS_NOTHINGTOCONFIG, res_nothingW, IDS_NOTHINGTOCONFIG_MAXLEN); 238 239 MessageBoxW(hWnd, res_nothingW, res_PortW, MB_OK | MB_ICONINFORMATION); 240 } 241 242 /****************************************************************** 243 * dlg_win32error [internal] 244 */ 245 246 static void dlg_win32error(HWND hWnd, DWORD lasterror) 247 { 248 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN]; 249 LPWSTR message = NULL; 250 DWORD res; 251 252 res_PortW[0] = '\0'; 253 LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN); 254 255 256 res = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 257 NULL, lasterror, 0, (LPWSTR) &message, 0, NULL); 258 259 if (res > 0) { 260 MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR); 261 LocalFree(message); 262 } 263 } 264 265 /***************************************************************************** 266 * 267 */ 268 269 static INT_PTR CALLBACK dlgproc_addport(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 270 { 271 addportui_t * data; 272 DWORD status; 273 DWORD dummy; 274 DWORD len; 275 DWORD res; 276 277 switch(msg) 278 { 279 case WM_INITDIALOG: 280 SetWindowLongPtrW(hwnd, DWLP_USER, lparam); 281 return TRUE; 282 283 case WM_COMMAND: 284 if (wparam == MAKEWPARAM(IDOK, BN_CLICKED)) 285 { 286 data = (addportui_t *) GetWindowLongPtrW(hwnd, DWLP_USER); 287 /* length in WCHAR, without the '\0' */ 288 len = SendDlgItemMessageW(hwnd, ADDPORT_EDIT, WM_GETTEXTLENGTH, 0, 0); 289 data->portname = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 290 291 if (!data->portname) { 292 EndDialog(hwnd, FALSE); 293 return TRUE; 294 } 295 /* length is in WCHAR, including the '\0' */ 296 GetDlgItemTextW(hwnd, ADDPORT_EDIT, data->portname, len + 1); 297 status = ERROR_SUCCESS; 298 res = XcvDataW( data->hXcv, cmd_PortIsValidW, (PBYTE) data->portname, 299 (lstrlenW(data->portname) + 1) * sizeof(WCHAR), 300 (PBYTE) &dummy, 0, &len, &status); 301 302 TRACE("got %u with status %u\n", res, status); 303 if (res && (status == ERROR_SUCCESS)) { 304 /* The caller must free data->portname */ 305 EndDialog(hwnd, TRUE); 306 return TRUE; 307 } 308 309 if (res && (status == ERROR_INVALID_NAME)) { 310 dlg_invalid_portname(hwnd, data->portname); 311 HeapFree(GetProcessHeap(), 0, data->portname); 312 data->portname = NULL; 313 return TRUE; 314 } 315 316 dlg_win32error(hwnd, status); 317 HeapFree(GetProcessHeap(), 0, data->portname); 318 data->portname = NULL; 319 return TRUE; 320 } 321 322 if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED)) 323 { 324 EndDialog(hwnd, FALSE); 325 return TRUE; 326 } 327 return FALSE; 328 } 329 return FALSE; 330 } 331 332 /***************************************************************************** 333 * dlgproc_lptconfig [internal] 334 * 335 * Our message-proc is simple, as the range-check is done only during the 336 * command "OK" and the dialog is set to the start-value at "out of range". 337 * 338 * Native localui.dll does the check during keyboard-input and set the dialog 339 * to the previous value. 340 * 341 */ 342 343 static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 344 { 345 lptconfig_t * data; 346 WCHAR bufferW[16]; 347 DWORD status; 348 DWORD dummy; 349 DWORD len; 350 DWORD res; 351 352 353 switch(msg) 354 { 355 case WM_INITDIALOG: 356 SetWindowLongPtrW(hwnd, DWLP_USER, lparam); 357 data = (lptconfig_t *) lparam; 358 359 /* Get current setting */ 360 data->value = 45; 361 status = ERROR_SUCCESS; 362 res = XcvDataW( data->hXcv, cmd_GetTransmissionRetryTimeoutW, 363 (PBYTE) &dummy, 0, 364 (PBYTE) &data->value, sizeof(data->value), &len, &status); 365 366 TRACE("got %u with status %u\n", res, status); 367 368 /* Set current setting as the initial value in the Dialog */ 369 SetDlgItemInt(hwnd, LPTCONFIG_EDIT, data->value, FALSE); 370 return TRUE; 371 372 case WM_COMMAND: 373 if (wparam == MAKEWPARAM(IDOK, BN_CLICKED)) 374 { 375 data = (lptconfig_t *) GetWindowLongPtrW(hwnd, DWLP_USER); 376 377 status = FALSE; 378 res = GetDlgItemInt(hwnd, LPTCONFIG_EDIT, (BOOL *) &status, FALSE); 379 /* length is in WCHAR, including the '\0' */ 380 GetDlgItemTextW(hwnd, LPTCONFIG_EDIT, bufferW, ARRAY_SIZE(bufferW)); 381 TRACE("got %s and %u (translated: %u)\n", debugstr_w(bufferW), res, status); 382 383 /* native localui.dll use the same limits */ 384 if ((res > 0) && (res < 1000000) && status) { 385 swprintf(bufferW, fmt_uW, res); 386 res = XcvDataW( data->hXcv, cmd_ConfigureLPTPortCommandOKW, 387 (PBYTE) bufferW, 388 (lstrlenW(bufferW) +1) * sizeof(WCHAR), 389 (PBYTE) &dummy, 0, &len, &status); 390 391 TRACE("got %u with status %u\n", res, status); 392 EndDialog(hwnd, TRUE); 393 return TRUE; 394 } 395 396 /* Set initial value and rerun the Dialog */ 397 SetDlgItemInt(hwnd, LPTCONFIG_EDIT, data->value, FALSE); 398 return TRUE; 399 } 400 401 if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED)) 402 { 403 EndDialog(hwnd, FALSE); 404 return TRUE; 405 } 406 return FALSE; 407 } 408 return FALSE; 409 } 410 411 412 /***************************************************** 413 * get_type_from_name (internal) 414 * 415 */ 416 417 static DWORD get_type_from_name(LPCWSTR name) 418 { 419 HANDLE hfile; 420 421 if (!_wcsnicmp(name, portname_LPT, ARRAY_SIZE(portname_LPT) -1)) 422 return PORT_IS_LPT; 423 424 if (!_wcsnicmp(name, portname_COM, ARRAY_SIZE(portname_COM) -1)) 425 return PORT_IS_COM; 426 427 if (!wcsicmp(name, portname_FILE)) 428 return PORT_IS_FILE; 429 430 if (name[0] == '/') 431 return PORT_IS_UNIXNAME; 432 433 if (name[0] == '|') 434 return PORT_IS_PIPE; 435 436 if (!wcsncmp(name, portname_CUPS, ARRAY_SIZE(portname_CUPS) -1)) 437 return PORT_IS_CUPS; 438 439 if (!wcsncmp(name, portname_LPR, ARRAY_SIZE(portname_LPR) -1)) 440 return PORT_IS_LPR; 441 442 /* Must be a file or a directory. Does the file exist ? */ 443 hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 444 TRACE("%p for OPEN_EXISTING on %s\n", hfile, debugstr_w(name)); 445 if (hfile == INVALID_HANDLE_VALUE) { 446 /* Can we create the file? */ 447 hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); 448 TRACE("%p for OPEN_ALWAYS\n", hfile); 449 } 450 if (hfile != INVALID_HANDLE_VALUE) { 451 CloseHandle(hfile); 452 return PORT_IS_FILENAME; 453 } 454 /* We can't use the name. use GetLastError() for the reason */ 455 return PORT_IS_UNKNOWN; 456 } 457 458 /***************************************************** 459 * open_monitor_by_name [internal] 460 * 461 */ 462 static BOOL open_monitor_by_name(LPCWSTR pPrefix, LPCWSTR pPort, HANDLE * phandle) 463 { 464 PRINTER_DEFAULTSW pd; 465 LPWSTR fullname; 466 BOOL res; 467 468 * phandle = 0; 469 TRACE("(%s,%s)\n", debugstr_w(pPrefix),debugstr_w(pPort) ); 470 471 fullname = strdupWW(pPrefix, pPort); 472 pd.pDatatype = NULL; 473 pd.pDevMode = NULL; 474 pd.DesiredAccess = SERVER_ACCESS_ADMINISTER; 475 476 res = OpenPrinterW(fullname, phandle, &pd); 477 HeapFree(GetProcessHeap(), 0, fullname); 478 return res; 479 } 480 481 /***************************************************** 482 * localui_AddPortUI [exported through MONITORUI] 483 * 484 * Display a Dialog to add a local Port 485 * 486 * PARAMS 487 * pName [I] Servername or NULL (local Computer) 488 * hWnd [I] Handle to parent Window for the Dialog-Box or NULL 489 * pMonitorName[I] Name of the Monitor, that should be used to add a Port or NULL 490 * ppPortName [O] PTR to PTR of a buffer, that receive the Name of the new Port or NULL 491 * 492 * RETURNS 493 * Success: TRUE 494 * Failure: FALSE 495 * 496 * NOTES 497 * The caller must free the buffer (returned in ppPortName) with GlobalFree(). 498 * Native localui.dll failed with ERROR_INVALID_PARAMETER, when the user tried 499 * to add a Port, that start with "COM" or "LPT". 500 * 501 */ 502 static BOOL WINAPI localui_AddPortUI(PCWSTR pName, HWND hWnd, PCWSTR pMonitorName, PWSTR *ppPortName) 503 { 504 addportui_t data; 505 HANDLE hXcv; 506 DWORD needed; 507 DWORD dummy; 508 DWORD status; 509 DWORD res = FALSE; 510 511 TRACE( "(%s, %p, %s, %p) (*ppPortName: %p)\n", debugstr_w(pName), hWnd, 512 debugstr_w(pMonitorName), ppPortName, ppPortName ? *ppPortName : NULL); 513 514 if (open_monitor_by_name(XcvMonitorW, pMonitorName, &hXcv)) { 515 516 ZeroMemory(&data, sizeof(addportui_t)); 517 data.hXcv = hXcv; 518 res = DialogBoxParamW(LOCALUI_hInstance, MAKEINTRESOURCEW(ADDPORT_DIALOG), hWnd, 519 dlgproc_addport, (LPARAM) &data); 520 521 TRACE("got %u with %u for %s\n", res, GetLastError(), debugstr_w(data.portname)); 522 523 if (ppPortName) *ppPortName = NULL; 524 525 if (res) { 526 res = XcvDataW(hXcv, cmd_AddPortW, (PBYTE) data.portname, 527 (lstrlenW(data.portname)+1) * sizeof(WCHAR), 528 (PBYTE) &dummy, 0, &needed, &status); 529 530 TRACE("got %u with status %u\n", res, status); 531 if (res && (status == ERROR_SUCCESS) && ppPortName) { 532 /* Native localui uses GlobalAlloc also. 533 The caller must GlobalFree the buffer */ 534 *ppPortName = GlobalAlloc(GPTR, (lstrlenW(data.portname)+1) * sizeof(WCHAR)); 535 if (*ppPortName) lstrcpyW(*ppPortName, data.portname); 536 } 537 538 if (res && (status == ERROR_ALREADY_EXISTS)) { 539 dlg_port_already_exists(hWnd, data.portname); 540 /* Native localui also return "TRUE" from AddPortUI in this case */ 541 } 542 543 HeapFree(GetProcessHeap(), 0, data.portname); 544 } 545 else 546 { 547 SetLastError(ERROR_CANCELLED); 548 } 549 ClosePrinter(hXcv); 550 } 551 552 TRACE("=> %u with %u\n", res, GetLastError()); 553 return res; 554 } 555 556 557 /***************************************************** 558 * localui_ConfigurePortUI [exported through MONITORUI] 559 * 560 * Display the Configuration-Dialog for a specific Port 561 * 562 * PARAMS 563 * pName [I] Servername or NULL (local Computer) 564 * hWnd [I] Handle to parent Window for the Dialog-Box or NULL 565 * pPortName [I] Name of the Port, that should be configured 566 * 567 * RETURNS 568 * Success: TRUE 569 * Failure: FALSE 570 * 571 */ 572 static BOOL WINAPI localui_ConfigurePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPortName) 573 { 574 HANDLE hXcv; 575 DWORD res; 576 577 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); 578 if (open_monitor_by_name(XcvPortW, pPortName, &hXcv)) { 579 580 res = get_type_from_name(pPortName); 581 switch(res) 582 { 583 584 case PORT_IS_COM: 585 res = dlg_configure_com(hXcv, hWnd, pPortName); 586 break; 587 588 case PORT_IS_LPT: 589 res = dlg_configure_lpt(hXcv, hWnd); 590 break; 591 592 default: 593 dlg_nothingtoconfig(hWnd); 594 SetLastError(ERROR_CANCELLED); 595 res = FALSE; 596 } 597 598 ClosePrinter(hXcv); 599 return res; 600 } 601 return FALSE; 602 603 } 604 605 /***************************************************** 606 * localui_DeletePortUI [exported through MONITORUI] 607 * 608 * Delete a specific Port 609 * 610 * PARAMS 611 * pName [I] Servername or NULL (local Computer) 612 * hWnd [I] Handle to parent Window 613 * pPortName [I] Name of the Port, that should be deleted 614 * 615 * RETURNS 616 * Success: TRUE 617 * Failure: FALSE 618 * 619 * NOTES 620 * Native localui does not allow deleting a COM/LPT port (ERROR_NOT_SUPPORTED) 621 * 622 */ 623 static BOOL WINAPI localui_DeletePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPortName) 624 { 625 HANDLE hXcv; 626 DWORD dummy; 627 DWORD needed; 628 DWORD status; 629 630 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); 631 632 if ((!pPortName) || (!pPortName[0])) { 633 SetLastError(ERROR_INVALID_PARAMETER); 634 return FALSE; 635 } 636 637 if (open_monitor_by_name(XcvPortW, pPortName, &hXcv)) { 638 /* native localui tests here for LPT / COM - Ports and failed with 639 ERROR_NOT_SUPPORTED. */ 640 if (XcvDataW(hXcv, cmd_DeletePortW, (LPBYTE) pPortName, 641 (lstrlenW(pPortName)+1) * sizeof(WCHAR), (LPBYTE) &dummy, 0, &needed, &status)) { 642 643 ClosePrinter(hXcv); 644 if (status != ERROR_SUCCESS) SetLastError(status); 645 return (status == ERROR_SUCCESS); 646 } 647 ClosePrinter(hXcv); 648 return FALSE; 649 } 650 SetLastError(ERROR_UNKNOWN_PORT); 651 return FALSE; 652 } 653 654 /***************************************************** 655 * InitializePrintMonitorUI (LOCALUI.@) 656 * 657 * Initialize the User-Interface for the Local Ports 658 * 659 * RETURNS 660 * Success: Pointer to a MONITORUI Structure 661 * Failure: NULL 662 * 663 */ 664 665 PMONITORUI WINAPI InitializePrintMonitorUI(void) 666 { 667 static MONITORUI mymonitorui = 668 { 669 sizeof(MONITORUI), 670 localui_AddPortUI, 671 localui_ConfigurePortUI, 672 localui_DeletePortUI 673 }; 674 675 TRACE("=> %p\n", &mymonitorui); 676 return &mymonitorui; 677 } 678 679 /***************************************************** 680 * DllMain 681 */ 682 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 683 { 684 TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved); 685 686 switch(fdwReason) 687 { 688 case DLL_PROCESS_ATTACH: 689 DisableThreadLibraryCalls( hinstDLL ); 690 LOCALUI_hInstance = hinstDLL; 691 break; 692 } 693 return TRUE; 694 } 695