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