2acfc7ecafaeb38527e1e7aa85bf7ee917389db8
[reactos.git] / reactos / 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 #include <stdarg.h>
22
23 #define NONAMELESSUNION
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winreg.h"
29 #include "winuser.h"
30
31 #include "winspool.h"
32 #include "ddk/winsplp.h"
33
34 #include "wine/debug.h"
35 #include "wine/unicode.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 = sizeof(cfg);
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 snprintfW(message, len, 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 snprintfW(message, len, 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, sizeof(bufferW) / sizeof(bufferW[0]));
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 sprintfW(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 (!strncmpiW(name, portname_LPT, sizeof(portname_LPT) / sizeof(WCHAR) -1))
422 return PORT_IS_LPT;
423
424 if (!strncmpiW(name, portname_COM, sizeof(portname_COM) / sizeof(WCHAR) -1))
425 return PORT_IS_COM;
426
427 if (!strcmpiW(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 (!strncmpW(name, portname_CUPS, sizeof(portname_CUPS) / sizeof(WCHAR) -1))
437 return PORT_IS_CUPS;
438
439 if (!strncmpW(name, portname_LPR, sizeof(portname_LPR) / sizeof(WCHAR) -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 LPWSTR ptr = NULL;
507 DWORD needed;
508 DWORD dummy;
509 DWORD status;
510 DWORD res = FALSE;
511
512 TRACE( "(%s, %p, %s, %p) (*ppPortName: %p)\n", debugstr_w(pName), hWnd,
513 debugstr_w(pMonitorName), ppPortName, ppPortName ? *ppPortName : NULL);
514
515 if (open_monitor_by_name(XcvMonitorW, pMonitorName, &hXcv)) {
516
517 ZeroMemory(&data, sizeof(addportui_t));
518 data.hXcv = hXcv;
519 res = DialogBoxParamW(LOCALUI_hInstance, MAKEINTRESOURCEW(ADDPORT_DIALOG), hWnd,
520 dlgproc_addport, (LPARAM) &data);
521
522 TRACE("got %u with %u for %s\n", res, GetLastError(), debugstr_w(data.portname));
523
524 if (ppPortName) *ppPortName = NULL;
525
526 if (res) {
527 res = XcvDataW(hXcv, cmd_AddPortW, (PBYTE) data.portname,
528 (lstrlenW(data.portname)+1) * sizeof(WCHAR),
529 (PBYTE) &dummy, 0, &needed, &status);
530
531 TRACE("got %u with status %u\n", res, status);
532 if (res && (status == ERROR_SUCCESS)) {
533 /* Native localui uses GlobalAlloc also.
534 The caller must GlobalFree the buffer */
535 ptr = GlobalAlloc(GPTR, (lstrlenW(data.portname)+1) * sizeof(WCHAR));
536 if (ptr) {
537 lstrcpyW(ptr, data.portname);
538 if (ppPortName) *ppPortName = ptr;
539 }
540 }
541
542 if (res && (status == ERROR_ALREADY_EXISTS)) {
543 dlg_port_already_exists(hWnd, data.portname);
544 /* Native localui also return "TRUE" from AddPortUI in this case */
545 }
546
547 HeapFree(GetProcessHeap(), 0, data.portname);
548 }
549 else
550 {
551 SetLastError(ERROR_CANCELLED);
552 }
553 ClosePrinter(hXcv);
554 }
555
556 TRACE("=> %u with %u\n", res, GetLastError());
557 return res;
558 }
559
560
561 /*****************************************************
562 * localui_ConfigurePortUI [exported through MONITORUI]
563 *
564 * Display the Configuration-Dialog for a specific Port
565 *
566 * PARAMS
567 * pName [I] Servername or NULL (local Computer)
568 * hWnd [I] Handle to parent Window for the Dialog-Box or NULL
569 * pPortName [I] Name of the Port, that should be configured
570 *
571 * RETURNS
572 * Success: TRUE
573 * Failure: FALSE
574 *
575 */
576 static BOOL WINAPI localui_ConfigurePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPortName)
577 {
578 HANDLE hXcv;
579 DWORD res;
580
581 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName));
582 if (open_monitor_by_name(XcvPortW, pPortName, &hXcv)) {
583
584 res = get_type_from_name(pPortName);
585 switch(res)
586 {
587
588 case PORT_IS_COM:
589 res = dlg_configure_com(hXcv, hWnd, pPortName);
590 break;
591
592 case PORT_IS_LPT:
593 res = dlg_configure_lpt(hXcv, hWnd);
594 break;
595
596 default:
597 dlg_nothingtoconfig(hWnd);
598 SetLastError(ERROR_CANCELLED);
599 res = FALSE;
600 }
601
602 ClosePrinter(hXcv);
603 return res;
604 }
605 return FALSE;
606
607 }
608
609 /*****************************************************
610 * localui_DeletePortUI [exported through MONITORUI]
611 *
612 * Delete a specific Port
613 *
614 * PARAMS
615 * pName [I] Servername or NULL (local Computer)
616 * hWnd [I] Handle to parent Window
617 * pPortName [I] Name of the Port, that should be deleted
618 *
619 * RETURNS
620 * Success: TRUE
621 * Failure: FALSE
622 *
623 * NOTES
624 * Native localui does not allow to delete a COM / LPT - Port (ERROR_NOT_SUPPORTED)
625 *
626 */
627 static BOOL WINAPI localui_DeletePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPortName)
628 {
629 HANDLE hXcv;
630 DWORD dummy;
631 DWORD needed;
632 DWORD status;
633
634 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName));
635
636 if ((!pPortName) || (!pPortName[0])) {
637 SetLastError(ERROR_INVALID_PARAMETER);
638 return FALSE;
639 }
640
641 if (open_monitor_by_name(XcvPortW, pPortName, &hXcv)) {
642 /* native localui tests here for LPT / COM - Ports and failed with
643 ERROR_NOT_SUPPORTED. */
644 if (XcvDataW(hXcv, cmd_DeletePortW, (LPBYTE) pPortName,
645 (lstrlenW(pPortName)+1) * sizeof(WCHAR), (LPBYTE) &dummy, 0, &needed, &status)) {
646
647 ClosePrinter(hXcv);
648 if (status != ERROR_SUCCESS) SetLastError(status);
649 return (status == ERROR_SUCCESS);
650 }
651 ClosePrinter(hXcv);
652 return FALSE;
653 }
654 SetLastError(ERROR_UNKNOWN_PORT);
655 return FALSE;
656 }
657
658 /*****************************************************
659 * InitializePrintMonitorUI (LOCALUI.@)
660 *
661 * Initialize the User-Interface for the Local Ports
662 *
663 * RETURNS
664 * Success: Pointer to a MONITORUI Structure
665 * Failure: NULL
666 *
667 */
668
669 PMONITORUI WINAPI InitializePrintMonitorUI(void)
670 {
671 static MONITORUI mymonitorui =
672 {
673 sizeof(MONITORUI),
674 localui_AddPortUI,
675 localui_ConfigurePortUI,
676 localui_DeletePortUI
677 };
678
679 TRACE("=> %p\n", &mymonitorui);
680 return &mymonitorui;
681 }
682
683 /*****************************************************
684 * DllMain
685 */
686 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
687 {
688 TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved);
689
690 switch(fdwReason)
691 {
692 case DLL_PROCESS_ATTACH:
693 DisableThreadLibraryCalls( hinstDLL );
694 LOCALUI_hInstance = hinstDLL;
695 break;
696 }
697 return TRUE;
698 }