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
];
87 WCHAR res_MonitorW
[32];
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
, 32) + 1;
117 reslen_PortW
= LoadStringW(LOCALSPL_hInstance
, IDS_LOCALPORT
, res_PortW
, 32) + 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_EnumPortsW [exported through MONITOREX]
202 * Enumerate all local Ports
205 * pName [I] Servername (ignored)
206 * level [I] Structure-Level (1 or 2)
207 * pPorts [O] PTR to Buffer that receives the Result
208 * cbBuf [I] Size of Buffer at pPorts
209 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
210 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
214 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
217 *| Windows ignores pName
218 *| Windows crash the app, when pPorts, pcbNeeded or pcReturned are NULL
219 *| Windows >NT4.0 does not check for illegal levels (TRUE is returned)
222 * "HCU\Software\Wine\Spooler\<portname>" - redirection
225 BOOL WINAPI
localmon_EnumPortsW(LPWSTR pName
, DWORD level
, LPBYTE pPorts
,
226 DWORD cbBuf
, LPDWORD pcbNeeded
, LPDWORD pcReturned
)
232 TRACE("(%s, %d, %p, %d, %p, %p)\n",
233 debugstr_w(pName
), level
, pPorts
, cbBuf
, pcbNeeded
, pcReturned
);
236 needed
= get_ports_from_reg(level
, NULL
, 0, &numentries
);
237 /* we calculated the needed buffersize. now do the error-checks */
238 if (cbBuf
< needed
) {
239 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
243 /* fill the buffer with the Port-Names */
244 needed
= get_ports_from_reg(level
, pPorts
, cbBuf
, &numentries
);
247 if (pcReturned
) *pcReturned
= numentries
;
250 if (pcbNeeded
) *pcbNeeded
= needed
;
252 TRACE("returning %d with %d (%d byte for %d entries)\n",
253 res
, GetLastError(), needed
, numentries
);
258 /*****************************************************
259 * InitializePrintMonitor (LOCALSPL.@)
261 * Initialize the Monitor for the Local Ports
264 * regroot [I] Registry-Path, where the settings are stored
267 * Success: Pointer to a MONITOREX Structure
271 * The fixed location "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports"
272 * is used to store the Ports (IniFileMapping from "win.ini", Section "Ports").
273 * Native localspl.dll fails, when no valid Port-Entry is present.
277 LPMONITOREX WINAPI
InitializePrintMonitor(LPWSTR regroot
)
279 static MONITOREX mymonitorex
=
281 sizeof(MONITOREX
) - sizeof(DWORD
),
284 NULL
, /* localmon_OpenPortW */
285 NULL
, /* localmon_OpenPortExW */
286 NULL
, /* localmon_StartDocPortW */
287 NULL
, /* localmon_WritePortW */
288 NULL
, /* localmon_ReadPortW */
289 NULL
, /* localmon_EndDocPortW */
290 NULL
, /* localmon_ClosePortW */
291 NULL
, /* localmon_AddPortW */
292 NULL
, /* localmon_AddPortExW */
293 localmon_ConfigurePortW
297 TRACE("(%s)\n", debugstr_w(regroot
));
298 /* Parameter "regroot" is ignored on NT4.0 (localmon.dll) */
299 if (!regroot
|| !regroot
[0]) {
300 SetLastError(ERROR_INVALID_PARAMETER
);
303 TRACE("=> %p\n", &mymonitorex
);
304 /* Native windows returns always the same pointer on success */