user32: ToUnicodeEx should return 0 for an unknown key.
[wine/dibdrv.git] / dlls / localspl / localmon.c
blob30681fe7e06cca0ea5af68e070fa796c70d17356
1 /*
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
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winreg.h"
31 #include "winver.h"
32 #include "winnls.h"
34 #include "winspool.h"
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 * enumerate the local Ports from the Registry (internal)
54 * See localmon_EnumPortsW.
56 * NOTES
57 * returns the needed size (in bytes) for pPorts
58 * and *lpreturned is set to number of entries returned in pPorts
62 static DWORD get_ports_from_reg(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned)
64 HKEY hroot = 0;
65 LPWSTR ptr;
66 LPPORT_INFO_2W out;
67 WCHAR portname[MAX_PATH];
68 WCHAR res_PortW[32];
69 WCHAR res_MonitorW[32];
70 INT reslen_PortW;
71 INT reslen_MonitorW;
72 DWORD len;
73 DWORD res;
74 DWORD needed = 0;
75 DWORD numentries;
76 DWORD entrysize;
77 DWORD id = 0;
79 TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned);
81 entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W);
83 numentries = *lpreturned; /* this is 0, when we scan the registry */
84 needed = entrysize * numentries;
85 ptr = (LPWSTR) &pPorts[needed];
87 if (needed > cbBuf) pPorts = NULL; /* No buffer for the structs */
89 numentries = 0;
90 needed = 0;
92 /* we do not check more parameters as done in windows */
93 if ((level < 1) || (level > 2)) {
94 goto getports_cleanup;
97 /* "+1" for '\0' */
98 reslen_MonitorW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALMONITOR, res_MonitorW, 32) + 1;
99 reslen_PortW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALPORT, res_PortW, 32) + 1;
101 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
102 if (res == ERROR_SUCCESS) {
104 /* Scan all Port-Names */
105 while (res == ERROR_SUCCESS) {
106 len = MAX_PATH;
107 portname[0] = '\0';
108 res = RegEnumValueW(hroot, id, portname, &len, NULL, NULL, NULL, NULL);
110 if ((res == ERROR_SUCCESS) && (portname[0])) {
111 numentries++;
112 /* calsulate the required size */
113 needed += entrysize;
114 needed += (len + 1) * sizeof(WCHAR);
115 if (level > 1) {
116 needed += (reslen_MonitorW + reslen_PortW) * sizeof(WCHAR);
119 /* Now fill the user-buffer, if available */
120 if (pPorts && (cbBuf >= needed)){
121 out = (LPPORT_INFO_2W) pPorts;
122 pPorts += entrysize;
123 TRACE("%p: writing PORT_INFO_%dW #%d (%s)\n", out, level, numentries, debugstr_w(portname));
124 out->pPortName = ptr;
125 lstrcpyW(ptr, portname); /* Name of the Port */
126 ptr += (len + 1);
127 if (level > 1) {
128 out->pMonitorName = ptr;
129 lstrcpyW(ptr, res_MonitorW); /* Name of the Monitor */
130 ptr += reslen_MonitorW;
132 out->pDescription = ptr;
133 lstrcpyW(ptr, res_PortW); /* Port Description */
134 ptr += reslen_PortW;
136 out->fPortType = PORT_TYPE_WRITE;
137 out->Reserved = 0;
140 id++;
143 RegCloseKey(hroot);
145 else
147 ERR("failed with %d for %s\n", res, debugstr_w(WinNT_CV_PortsW));
148 SetLastError(res);
151 getports_cleanup:
152 *lpreturned = numentries;
153 TRACE("need %d byte for %d entries (%d)\n", needed, numentries, GetLastError());
154 return needed;
157 /*****************************************************
158 * localmon_EnumPortsW [exported through MONITOREX]
160 * Enumerate all local Ports
162 * PARAMS
163 * pName [I] Servername (ignored)
164 * level [I] Structure-Level (1 or 2)
165 * pPorts [O] PTR to Buffer that receives the Result
166 * cbBuf [I] Size of Buffer at pPorts
167 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
168 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
170 * RETURNS
171 * Success: TRUE
172 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
174 * NOTES
175 *| Windows ignores pName
176 *| Windows crash the app, when pPorts, pcbNeeded or pcReturned are NULL
177 *| Windows >NT4.0 does not check for illegal levels (TRUE is returned)
179 * ToDo
180 * "HCU\Software\Wine\Spooler\<portname>" - redirection
183 BOOL WINAPI localmon_EnumPortsW(LPWSTR pName, DWORD level, LPBYTE pPorts,
184 DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
186 BOOL res = FALSE;
187 DWORD needed;
188 DWORD numentries;
190 TRACE("(%s, %d, %p, %d, %p, %p)\n",
191 debugstr_w(pName), level, pPorts, cbBuf, pcbNeeded, pcReturned);
193 numentries = 0;
194 needed = get_ports_from_reg(level, NULL, 0, &numentries);
195 /* we calculated the needed buffersize. now do the error-checks */
196 if (cbBuf < needed) {
197 SetLastError(ERROR_INSUFFICIENT_BUFFER);
198 goto cleanup;
201 /* fill the buffer with the Port-Names */
202 needed = get_ports_from_reg(level, pPorts, cbBuf, &numentries);
203 res = TRUE;
205 if (pcReturned) *pcReturned = numentries;
207 cleanup:
208 if (pcbNeeded) *pcbNeeded = needed;
210 TRACE("returning %d with %d (%d byte for %d entries)\n",
211 res, GetLastError(), needed, numentries);
213 return (res);
216 /*****************************************************
217 * InitializePrintMonitor (LOCALSPL.@)
219 * Initialize the Monitor for the Local Ports
221 * PARAMS
222 * regroot [I] Registry-Path, where the settings are stored
224 * RETURNS
225 * Success: Pointer to a MONITOREX Structure
226 * Failure: NULL
228 * NOTES
229 * The fixed location "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports"
230 * is used to store the Ports (IniFileMapping from "win.ini", Section "Ports").
231 * Native localspl.dll fails, when no valid Port-Entry is present.
235 LPMONITOREX WINAPI InitializePrintMonitor(LPWSTR regroot)
237 static MONITOREX mymonitorex =
239 sizeof(MONITOREX) - sizeof(DWORD),
241 localmon_EnumPortsW
245 TRACE("(%s)\n", debugstr_w(regroot));
246 /* Parameter "regroot" is ignored on NT4.0 (localmon.dll) */
247 if (!regroot || !regroot[0]) {
248 SetLastError(ERROR_INVALID_PARAMETER);
249 return NULL;
251 TRACE("=> %p\n", &mymonitorex);
252 /* Native windows returns always the same pointer on success */
253 return &mymonitorex;