2 * Implementation of the Local Printmonitor
4 * Copyright 2006 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
24 #define NONAMELESSUNION
35 #include "ddk/winsplp.h"
36 #include "localspl_private.h"
38 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(localspl);
43 /*****************************************************/
45 static const WCHAR WinNT_CV_PortsW[] = {'S','o','f','t','w','a','r','e','\\',
46 'M','i','c','r','o','s','o','f','t','\\',
47 'W','i','n','d','o','w','s',' ','N','T','\\',
48 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
49 'P','o','r','t','s',0};
51 /******************************************************************
52 * display the Dialog "Nothing to configure"
56 static void dlg_nothingtoconfig(HWND hWnd)
58 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
59 WCHAR res_nothingW[IDS_NOTHINGTOCONFIG_MAXLEN];
62 res_nothingW[0] = '\0';
63 LoadStringW(LOCALSPL_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN);
64 LoadStringW(LOCALSPL_hInstance, IDS_NOTHINGTOCONFIG, res_nothingW, IDS_NOTHINGTOCONFIG_MAXLEN);
66 MessageBoxW(hWnd, res_nothingW, res_PortW, MB_OK | MB_ICONINFORMATION);
69 /******************************************************************
70 * enumerate the local Ports from the Registry (internal)
72 * See localmon_EnumPortsW.
75 * returns the needed size (in bytes) for pPorts
76 * and *lpreturned is set to number of entries returned in pPorts
80 static DWORD get_ports_from_reg(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned)
85 WCHAR portname[MAX_PATH];
86 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
87 WCHAR res_MonitorW[IDS_LOCALMONITOR_MAXLEN];
97 TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned);
99 entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W);
101 numentries = *lpreturned; /* this is 0, when we scan the registry */
102 needed = entrysize * numentries;
103 ptr = (LPWSTR) &pPorts[needed];
105 if (needed > cbBuf) pPorts = NULL; /* No buffer for the structs */
110 /* we do not check more parameters as done in windows */
111 if ((level < 1) || (level > 2)) {
112 goto getports_cleanup;
116 reslen_MonitorW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALMONITOR, res_MonitorW, IDS_LOCALMONITOR_MAXLEN) + 1;
117 reslen_PortW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN) + 1;
119 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
120 if (res == ERROR_SUCCESS) {
122 /* Scan all Port-Names */
123 while (res == ERROR_SUCCESS) {
126 res = RegEnumValueW(hroot, id, portname, &len, NULL, NULL, NULL, NULL);
128 if ((res == ERROR_SUCCESS) && (portname[0])) {
130 /* calsulate the required size */
132 needed += (len + 1) * sizeof(WCHAR);
134 needed += (reslen_MonitorW + reslen_PortW) * sizeof(WCHAR);
137 /* Now fill the user-buffer, if available */
138 if (pPorts && (cbBuf >= needed)){
139 out = (LPPORT_INFO_2W) pPorts;
141 TRACE("%p: writing PORT_INFO_%dW #%d (%s)\n", out, level, numentries, debugstr_w(portname));
142 out->pPortName = ptr;
143 lstrcpyW(ptr, portname); /* Name of the Port */
146 out->pMonitorName = ptr;
147 lstrcpyW(ptr, res_MonitorW); /* Name of the Monitor */
148 ptr += reslen_MonitorW;
150 out->pDescription = ptr;
151 lstrcpyW(ptr, res_PortW); /* Port Description */
154 out->fPortType = PORT_TYPE_WRITE;
165 ERR("failed with %d for %s\n", res, debugstr_w(WinNT_CV_PortsW));
170 *lpreturned = numentries;
171 TRACE("need %d byte for %d entries (%d)\n", needed, numentries, GetLastError());
175 /*****************************************************
176 * localmon_ConfigurePortW [exported through MONITOREX]
178 * Display the Configuration-Dialog for a specific Port
181 * pName [I] Servername or NULL (local Computer)
182 * hWnd [I] Handle to parent Window for the Dialog-Box
183 * pPortName [I] Name of the Port, that should be configured
190 BOOL WINAPI localmon_ConfigurePortW(LPWSTR pName, HWND hWnd, LPWSTR pPortName)
192 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName));
193 /* ToDo: Dialogs by Portname ("LPTx:", "COMx:") */
195 dlg_nothingtoconfig(hWnd);
196 return ROUTER_SUCCESS;
199 /*****************************************************
200 * localmon_DeletePortW [exported through MONITOREX]
202 * Delete a specific Port
205 * pName [I] Servername or NULL (local Computer)
206 * hWnd [I] Handle to parent Window
207 * pPortName [I] Name of the Port, that should be deleted
214 BOOL WINAPI localmon_DeletePortW(LPWSTR pName, HWND hWnd, LPWSTR pPortName)
219 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName));
221 if ((!pPortName) || (!pPortName[0])) return FALSE;
223 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
224 if (res == ERROR_SUCCESS) {
225 res = RegDeleteValueW(hroot, pPortName);
228 TRACE("=> %d\n", (res == ERROR_SUCCESS));
229 return (res == ERROR_SUCCESS);
232 /*****************************************************
233 * localmon_EnumPortsW [exported through MONITOREX]
235 * Enumerate all local Ports
238 * pName [I] Servername (ignored)
239 * level [I] Structure-Level (1 or 2)
240 * pPorts [O] PTR to Buffer that receives the Result
241 * cbBuf [I] Size of Buffer at pPorts
242 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
243 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
247 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
250 *| Windows ignores pName
251 *| Windows crash the app, when pPorts, pcbNeeded or pcReturned are NULL
252 *| Windows >NT4.0 does not check for illegal levels (TRUE is returned)
255 * "HCU\Software\Wine\Spooler\<portname>" - redirection
258 BOOL WINAPI localmon_EnumPortsW(LPWSTR pName, DWORD level, LPBYTE pPorts,
259 DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
265 TRACE("(%s, %d, %p, %d, %p, %p)\n",
266 debugstr_w(pName), level, pPorts, cbBuf, pcbNeeded, pcReturned);
269 needed = get_ports_from_reg(level, NULL, 0, &numentries);
270 /* we calculated the needed buffersize. now do the error-checks */
271 if (cbBuf < needed) {
272 SetLastError(ERROR_INSUFFICIENT_BUFFER);
276 /* fill the buffer with the Port-Names */
277 needed = get_ports_from_reg(level, pPorts, cbBuf, &numentries);
280 if (pcReturned) *pcReturned = numentries;
283 if (pcbNeeded) *pcbNeeded = needed;
285 TRACE("returning %d with %d (%d byte for %d entries)\n",
286 res, GetLastError(), needed, numentries);
291 /*****************************************************
292 * InitializePrintMonitor (LOCALSPL.@)
294 * Initialize the Monitor for the Local Ports
297 * regroot [I] Registry-Path, where the settings are stored
300 * Success: Pointer to a MONITOREX Structure
304 * The fixed location "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports"
305 * is used to store the Ports (IniFileMapping from "win.ini", Section "Ports").
306 * Native localspl.dll fails, when no valid Port-Entry is present.
310 LPMONITOREX WINAPI InitializePrintMonitor(LPWSTR regroot)
312 static MONITOREX mymonitorex =
314 sizeof(MONITOREX) - sizeof(DWORD),
317 NULL, /* localmon_OpenPortW */
318 NULL, /* localmon_OpenPortExW */
319 NULL, /* localmon_StartDocPortW */
320 NULL, /* localmon_WritePortW */
321 NULL, /* localmon_ReadPortW */
322 NULL, /* localmon_EndDocPortW */
323 NULL, /* localmon_ClosePortW */
324 NULL, /* localmon_AddPortW */
325 NULL, /* localmon_AddPortExW */
326 localmon_ConfigurePortW,
331 TRACE("(%s)\n", debugstr_w(regroot));
332 /* Parameter "regroot" is ignored on NT4.0 (localmon.dll) */
333 if (!regroot || !regroot[0]) {
334 SetLastError(ERROR_INVALID_PARAMETER);
337 TRACE("=> %p\n", &mymonitorex);
338 /* Native windows returns always the same pointer on success */