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