directmanipulation: Return S_OK form viewport_SetViewportOptions stub.
[wine/zf.git] / dlls / localui / localui.c
blob87522494a1d5fc6616bbeee65226d122adcb868e
1 /*
2 * Implementation of the Local Printmonitor User Interface
4 * Copyright 2007 Detlef Riekenberg
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.
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.
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winreg.h"
27 #include "winuser.h"
29 #include "winspool.h"
30 #include "ddk/winsplp.h"
32 #include "wine/debug.h"
33 #include "localui.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(localui);
37 /*****************************************************/
39 static HINSTANCE LOCALUI_hInstance;
41 /*****************************************************/
43 typedef struct tag_addportui_t {
44 LPWSTR portname;
45 HANDLE hXcv;
46 } addportui_t;
48 typedef struct tag_lptconfig_t {
49 HANDLE hXcv;
50 DWORD value;
51 } lptconfig_t;
54 static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
56 /*****************************************************
57 * strdupWW [internal]
60 static LPWSTR strdupWW(LPCWSTR pPrefix, LPCWSTR pSuffix)
62 LPWSTR ptr;
63 DWORD len;
65 len = lstrlenW(pPrefix) + (pSuffix ? lstrlenW(pSuffix) : 0) + 1;
66 ptr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
67 if (ptr) {
68 lstrcpyW(ptr, pPrefix);
69 if (pSuffix) lstrcatW(ptr, pSuffix);
71 return ptr;
74 /*****************************************************
75 * dlg_configure_com [internal]
79 static BOOL dlg_configure_com(HANDLE hXcv, HWND hWnd, PCWSTR pPortName)
81 COMMCONFIG cfg;
82 LPWSTR shortname;
83 DWORD status;
84 DWORD dummy;
85 DWORD len;
86 BOOL res;
88 /* strip the colon (pPortName is never empty here) */
89 len = lstrlenW(pPortName);
90 shortname = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
91 if (shortname) {
92 memcpy(shortname, pPortName, (len -1) * sizeof(WCHAR));
93 shortname[len-1] = '\0';
95 /* get current settings */
96 len = FIELD_OFFSET(COMMCONFIG, wcProviderData[1]);
97 status = ERROR_SUCCESS;
98 res = XcvDataW( hXcv, L"GetDefaultCommConfig",
99 (PBYTE) shortname,
100 (lstrlenW(shortname) +1) * sizeof(WCHAR),
101 (PBYTE) &cfg, len, &len, &status);
103 if (res && (status == ERROR_SUCCESS)) {
104 /* display the Dialog */
105 res = CommConfigDialogW(pPortName, hWnd, &cfg);
106 if (res) {
107 status = ERROR_SUCCESS;
108 /* set new settings */
109 res = XcvDataW(hXcv, L"SetDefaultCommConfig",
110 (PBYTE) &cfg, len,
111 (PBYTE) &dummy, 0, &len, &status);
114 HeapFree(GetProcessHeap(), 0, shortname);
115 return res;
117 return FALSE;
121 /*****************************************************
122 * dlg_configure_lpt [internal]
126 static BOOL dlg_configure_lpt(HANDLE hXcv, HWND hWnd)
128 lptconfig_t data;
129 BOOL res;
132 data.hXcv = hXcv;
134 res = DialogBoxParamW(LOCALUI_hInstance, MAKEINTRESOURCEW(LPTCONFIG_DIALOG), hWnd,
135 dlgproc_lptconfig, (LPARAM) &data);
137 TRACE("got %u with %u\n", res, GetLastError());
139 if (!res) SetLastError(ERROR_CANCELLED);
140 return res;
143 /******************************************************************
144 * dlg_port_already_exists [internal]
147 static void dlg_port_already_exists(HWND hWnd, LPCWSTR portname)
149 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
150 WCHAR res_PortExistsW[IDS_PORTEXISTS_MAXLEN];
151 LPWSTR message;
152 DWORD len;
154 res_PortW[0] = '\0';
155 res_PortExistsW[0] = '\0';
156 LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN);
157 LoadStringW(LOCALUI_hInstance, IDS_PORTEXISTS, res_PortExistsW, IDS_PORTEXISTS_MAXLEN);
159 len = lstrlenW(portname) + IDS_PORTEXISTS_MAXLEN + 1;
160 message = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
161 if (message) {
162 message[0] = '\0';
163 swprintf(message, len, res_PortExistsW, portname);
164 MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR);
165 HeapFree(GetProcessHeap(), 0, message);
169 /******************************************************************
170 * dlg_invalid_portname [internal]
173 static void dlg_invalid_portname(HWND hWnd, LPCWSTR portname)
175 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
176 WCHAR res_InvalidNameW[IDS_INVALIDNAME_MAXLEN];
177 LPWSTR message;
178 DWORD len;
180 res_PortW[0] = '\0';
181 res_InvalidNameW[0] = '\0';
182 LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN);
183 LoadStringW(LOCALUI_hInstance, IDS_INVALIDNAME, res_InvalidNameW, IDS_INVALIDNAME_MAXLEN);
185 len = lstrlenW(portname) + IDS_INVALIDNAME_MAXLEN;
186 message = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
187 if (message) {
188 message[0] = '\0';
189 swprintf(message, len, res_InvalidNameW, portname);
190 MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR);
191 HeapFree(GetProcessHeap(), 0, message);
195 /******************************************************************
196 * display the Dialog "Nothing to configure"
200 static void dlg_nothingtoconfig(HWND hWnd)
202 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
203 WCHAR res_nothingW[IDS_NOTHINGTOCONFIG_MAXLEN];
205 res_PortW[0] = '\0';
206 res_nothingW[0] = '\0';
207 LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN);
208 LoadStringW(LOCALUI_hInstance, IDS_NOTHINGTOCONFIG, res_nothingW, IDS_NOTHINGTOCONFIG_MAXLEN);
210 MessageBoxW(hWnd, res_nothingW, res_PortW, MB_OK | MB_ICONINFORMATION);
213 /******************************************************************
214 * dlg_win32error [internal]
217 static void dlg_win32error(HWND hWnd, DWORD lasterror)
219 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
220 LPWSTR message = NULL;
221 DWORD res;
223 res_PortW[0] = '\0';
224 LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN);
227 res = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
228 NULL, lasterror, 0, (LPWSTR) &message, 0, NULL);
230 if (res > 0) {
231 MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR);
232 LocalFree(message);
236 /*****************************************************************************
240 static INT_PTR CALLBACK dlgproc_addport(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
242 addportui_t * data;
243 DWORD status;
244 DWORD dummy;
245 DWORD len;
246 DWORD res;
248 switch(msg)
250 case WM_INITDIALOG:
251 SetWindowLongPtrW(hwnd, DWLP_USER, lparam);
252 return TRUE;
254 case WM_COMMAND:
255 if (wparam == MAKEWPARAM(IDOK, BN_CLICKED))
257 data = (addportui_t *) GetWindowLongPtrW(hwnd, DWLP_USER);
258 /* length in WCHAR, without the '\0' */
259 len = SendDlgItemMessageW(hwnd, ADDPORT_EDIT, WM_GETTEXTLENGTH, 0, 0);
260 data->portname = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
262 if (!data->portname) {
263 EndDialog(hwnd, FALSE);
264 return TRUE;
266 /* length is in WCHAR, including the '\0' */
267 GetDlgItemTextW(hwnd, ADDPORT_EDIT, data->portname, len + 1);
268 status = ERROR_SUCCESS;
269 res = XcvDataW( data->hXcv, L"PortIsValid", (BYTE *) data->portname,
270 (lstrlenW(data->portname) + 1) * sizeof(WCHAR),
271 (PBYTE) &dummy, 0, &len, &status);
273 TRACE("got %u with status %u\n", res, status);
274 if (res && (status == ERROR_SUCCESS)) {
275 /* The caller must free data->portname */
276 EndDialog(hwnd, TRUE);
277 return TRUE;
280 if (res && (status == ERROR_INVALID_NAME)) {
281 dlg_invalid_portname(hwnd, data->portname);
282 HeapFree(GetProcessHeap(), 0, data->portname);
283 data->portname = NULL;
284 return TRUE;
287 dlg_win32error(hwnd, status);
288 HeapFree(GetProcessHeap(), 0, data->portname);
289 data->portname = NULL;
290 return TRUE;
293 if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED))
295 EndDialog(hwnd, FALSE);
296 return TRUE;
298 return FALSE;
300 return FALSE;
303 /*****************************************************************************
304 * dlgproc_lptconfig [internal]
306 * Our message-proc is simple, as the range-check is done only during the
307 * command "OK" and the dialog is set to the start-value at "out of range".
309 * Native localui.dll does the check during keyboard-input and set the dialog
310 * to the previous value.
314 static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
316 lptconfig_t * data;
317 WCHAR bufferW[16];
318 DWORD status;
319 DWORD dummy;
320 DWORD len;
321 DWORD res;
324 switch(msg)
326 case WM_INITDIALOG:
327 SetWindowLongPtrW(hwnd, DWLP_USER, lparam);
328 data = (lptconfig_t *) lparam;
330 /* Get current setting */
331 data->value = 45;
332 status = ERROR_SUCCESS;
333 res = XcvDataW( data->hXcv, L"GetTransmissionRetryTimeout",
334 (PBYTE) &dummy, 0,
335 (PBYTE) &data->value, sizeof(data->value), &len, &status);
337 TRACE("got %u with status %u\n", res, status);
339 /* Set current setting as the initial value in the Dialog */
340 SetDlgItemInt(hwnd, LPTCONFIG_EDIT, data->value, FALSE);
341 return TRUE;
343 case WM_COMMAND:
344 if (wparam == MAKEWPARAM(IDOK, BN_CLICKED))
346 data = (lptconfig_t *) GetWindowLongPtrW(hwnd, DWLP_USER);
348 status = FALSE;
349 res = GetDlgItemInt(hwnd, LPTCONFIG_EDIT, (BOOL *) &status, FALSE);
350 /* length is in WCHAR, including the '\0' */
351 GetDlgItemTextW(hwnd, LPTCONFIG_EDIT, bufferW, ARRAY_SIZE(bufferW));
352 TRACE("got %s and %u (translated: %u)\n", debugstr_w(bufferW), res, status);
354 /* native localui.dll use the same limits */
355 if ((res > 0) && (res < 1000000) && status) {
356 swprintf(bufferW, ARRAY_SIZE(bufferW), L"%u", res);
357 res = XcvDataW( data->hXcv, L"ConfigureLPTPortCommandOK",
358 (PBYTE) bufferW,
359 (lstrlenW(bufferW) +1) * sizeof(WCHAR),
360 (PBYTE) &dummy, 0, &len, &status);
362 TRACE("got %u with status %u\n", res, status);
363 EndDialog(hwnd, TRUE);
364 return TRUE;
367 /* Set initial value and rerun the Dialog */
368 SetDlgItemInt(hwnd, LPTCONFIG_EDIT, data->value, FALSE);
369 return TRUE;
372 if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED))
374 EndDialog(hwnd, FALSE);
375 return TRUE;
377 return FALSE;
379 return FALSE;
383 /*****************************************************
384 * get_type_from_name (internal)
388 static DWORD get_type_from_name(LPCWSTR name)
390 HANDLE hfile;
392 if (!wcsnicmp(name, L"LPT", ARRAY_SIZE(L"LPT") -1))
393 return PORT_IS_LPT;
395 if (!wcsnicmp(name, L"COM", ARRAY_SIZE(L"COM") -1))
396 return PORT_IS_COM;
398 if (!wcsicmp(name, L"FILE:"))
399 return PORT_IS_FILE;
401 if (name[0] == '/')
402 return PORT_IS_UNIXNAME;
404 if (name[0] == '|')
405 return PORT_IS_PIPE;
407 if (!wcsncmp(name, L"CUPS:", ARRAY_SIZE(L"CUPS:") -1))
408 return PORT_IS_CUPS;
410 if (!wcsncmp(name, L"LPR:", ARRAY_SIZE(L"LPR:") -1))
411 return PORT_IS_LPR;
413 /* Must be a file or a directory. Does the file exist ? */
414 hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
415 TRACE("%p for OPEN_EXISTING on %s\n", hfile, debugstr_w(name));
416 if (hfile == INVALID_HANDLE_VALUE) {
417 /* Can we create the file? */
418 hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
419 TRACE("%p for OPEN_ALWAYS\n", hfile);
421 if (hfile != INVALID_HANDLE_VALUE) {
422 CloseHandle(hfile);
423 return PORT_IS_FILENAME;
425 /* We can't use the name. use GetLastError() for the reason */
426 return PORT_IS_UNKNOWN;
429 /*****************************************************
430 * open_monitor_by_name [internal]
433 static BOOL open_monitor_by_name(LPCWSTR pPrefix, LPCWSTR pPort, HANDLE * phandle)
435 PRINTER_DEFAULTSW pd;
436 LPWSTR fullname;
437 BOOL res;
439 * phandle = 0;
440 TRACE("(%s,%s)\n", debugstr_w(pPrefix),debugstr_w(pPort) );
442 fullname = strdupWW(pPrefix, pPort);
443 pd.pDatatype = NULL;
444 pd.pDevMode = NULL;
445 pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
447 res = OpenPrinterW(fullname, phandle, &pd);
448 HeapFree(GetProcessHeap(), 0, fullname);
449 return res;
452 /*****************************************************
453 * localui_AddPortUI [exported through MONITORUI]
455 * Display a Dialog to add a local Port
457 * PARAMS
458 * pName [I] Servername or NULL (local Computer)
459 * hWnd [I] Handle to parent Window for the Dialog-Box or NULL
460 * pMonitorName[I] Name of the Monitor, that should be used to add a Port or NULL
461 * ppPortName [O] PTR to PTR of a buffer, that receive the Name of the new Port or NULL
463 * RETURNS
464 * Success: TRUE
465 * Failure: FALSE
467 * NOTES
468 * The caller must free the buffer (returned in ppPortName) with GlobalFree().
469 * Native localui.dll failed with ERROR_INVALID_PARAMETER, when the user tried
470 * to add a Port, that start with "COM" or "LPT".
473 static BOOL WINAPI localui_AddPortUI(PCWSTR pName, HWND hWnd, PCWSTR pMonitorName, PWSTR *ppPortName)
475 addportui_t data;
476 HANDLE hXcv;
477 DWORD needed;
478 DWORD dummy;
479 DWORD status;
480 DWORD res = FALSE;
482 TRACE( "(%s, %p, %s, %p) (*ppPortName: %p)\n", debugstr_w(pName), hWnd,
483 debugstr_w(pMonitorName), ppPortName, ppPortName ? *ppPortName : NULL);
485 if (open_monitor_by_name(L",XcvMonitor ", pMonitorName, &hXcv)) {
487 ZeroMemory(&data, sizeof(addportui_t));
488 data.hXcv = hXcv;
489 res = DialogBoxParamW(LOCALUI_hInstance, MAKEINTRESOURCEW(ADDPORT_DIALOG), hWnd,
490 dlgproc_addport, (LPARAM) &data);
492 TRACE("got %u with %u for %s\n", res, GetLastError(), debugstr_w(data.portname));
494 if (ppPortName) *ppPortName = NULL;
496 if (res) {
497 res = XcvDataW(hXcv, L"AddPort", (BYTE *) data.portname,
498 (lstrlenW(data.portname)+1) * sizeof(WCHAR),
499 (PBYTE) &dummy, 0, &needed, &status);
501 TRACE("got %u with status %u\n", res, status);
502 if (res && (status == ERROR_SUCCESS) && ppPortName) {
503 /* Native localui uses GlobalAlloc also.
504 The caller must GlobalFree the buffer */
505 *ppPortName = GlobalAlloc(GPTR, (lstrlenW(data.portname)+1) * sizeof(WCHAR));
506 if (*ppPortName) lstrcpyW(*ppPortName, data.portname);
509 if (res && (status == ERROR_ALREADY_EXISTS)) {
510 dlg_port_already_exists(hWnd, data.portname);
511 /* Native localui also return "TRUE" from AddPortUI in this case */
514 HeapFree(GetProcessHeap(), 0, data.portname);
516 else
518 SetLastError(ERROR_CANCELLED);
520 ClosePrinter(hXcv);
523 TRACE("=> %u with %u\n", res, GetLastError());
524 return res;
528 /*****************************************************
529 * localui_ConfigurePortUI [exported through MONITORUI]
531 * Display the Configuration-Dialog for a specific Port
533 * PARAMS
534 * pName [I] Servername or NULL (local Computer)
535 * hWnd [I] Handle to parent Window for the Dialog-Box or NULL
536 * pPortName [I] Name of the Port, that should be configured
538 * RETURNS
539 * Success: TRUE
540 * Failure: FALSE
543 static BOOL WINAPI localui_ConfigurePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPortName)
545 HANDLE hXcv;
546 DWORD res;
548 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName));
549 if (open_monitor_by_name(L",XcvPort ", pPortName, &hXcv)) {
551 res = get_type_from_name(pPortName);
552 switch(res)
555 case PORT_IS_COM:
556 res = dlg_configure_com(hXcv, hWnd, pPortName);
557 break;
559 case PORT_IS_LPT:
560 res = dlg_configure_lpt(hXcv, hWnd);
561 break;
563 default:
564 dlg_nothingtoconfig(hWnd);
565 SetLastError(ERROR_CANCELLED);
566 res = FALSE;
569 ClosePrinter(hXcv);
570 return res;
572 return FALSE;
576 /*****************************************************
577 * localui_DeletePortUI [exported through MONITORUI]
579 * Delete a specific Port
581 * PARAMS
582 * pName [I] Servername or NULL (local Computer)
583 * hWnd [I] Handle to parent Window
584 * pPortName [I] Name of the Port, that should be deleted
586 * RETURNS
587 * Success: TRUE
588 * Failure: FALSE
590 * NOTES
591 * Native localui does not allow deleting a COM/LPT port (ERROR_NOT_SUPPORTED)
594 static BOOL WINAPI localui_DeletePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPortName)
596 HANDLE hXcv;
597 DWORD dummy;
598 DWORD needed;
599 DWORD status;
601 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName));
603 if ((!pPortName) || (!pPortName[0])) {
604 SetLastError(ERROR_INVALID_PARAMETER);
605 return FALSE;
608 if (open_monitor_by_name(L",XcvPort ", pPortName, &hXcv)) {
609 /* native localui tests here for LPT / COM - Ports and failed with
610 ERROR_NOT_SUPPORTED. */
611 if (XcvDataW(hXcv, L"DeletePort", (BYTE *) pPortName,
612 (lstrlenW(pPortName)+1) * sizeof(WCHAR), (LPBYTE) &dummy, 0, &needed, &status)) {
614 ClosePrinter(hXcv);
615 if (status != ERROR_SUCCESS) SetLastError(status);
616 return (status == ERROR_SUCCESS);
618 ClosePrinter(hXcv);
619 return FALSE;
621 SetLastError(ERROR_UNKNOWN_PORT);
622 return FALSE;
625 /*****************************************************
626 * InitializePrintMonitorUI (LOCALUI.@)
628 * Initialize the User-Interface for the Local Ports
630 * RETURNS
631 * Success: Pointer to a MONITORUI Structure
632 * Failure: NULL
636 PMONITORUI WINAPI InitializePrintMonitorUI(void)
638 static MONITORUI mymonitorui =
640 sizeof(MONITORUI),
641 localui_AddPortUI,
642 localui_ConfigurePortUI,
643 localui_DeletePortUI
646 TRACE("=> %p\n", &mymonitorui);
647 return &mymonitorui;
650 /*****************************************************
651 * DllMain
653 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
655 TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved);
657 switch(fdwReason)
659 case DLL_PROCESS_ATTACH:
660 DisableThreadLibraryCalls( hinstDLL );
661 LOCALUI_hInstance = hinstDLL;
662 break;
664 return TRUE;