2 * Routing for Spooler-Service helper DLL
4 * Copyright 2006-2009 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
30 #include "ddk/winsplp.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
37 /* ################################ */
42 /* PRINTPROVIDOR functions */
43 DWORD (WINAPI *fpOpenPrinter)(LPWSTR, HANDLE *, LPPRINTER_DEFAULTSW);
44 DWORD (WINAPI *fpSetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD);
45 DWORD (WINAPI *fpGetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD, LPDWORD);
46 DWORD (WINAPI *fpEnumJobs)(HANDLE, DWORD, DWORD, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
47 HANDLE (WINAPI *fpAddPrinter)(LPWSTR, DWORD, LPBYTE);
48 DWORD (WINAPI *fpDeletePrinter)(HANDLE);
49 DWORD (WINAPI *fpSetPrinter)(HANDLE, DWORD, LPBYTE, DWORD);
50 DWORD (WINAPI *fpGetPrinter)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
51 DWORD (WINAPI *fpEnumPrinters)(DWORD, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
52 DWORD (WINAPI *fpAddPrinterDriver)(LPWSTR, DWORD, LPBYTE);
53 DWORD (WINAPI *fpEnumPrinterDrivers)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
54 DWORD (WINAPI *fpGetPrinterDriver)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
55 DWORD (WINAPI *fpGetPrinterDriverDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
56 DWORD (WINAPI *fpDeletePrinterDriver)(LPWSTR, LPWSTR, LPWSTR);
57 DWORD (WINAPI *fpAddPrintProcessor)(LPWSTR, LPWSTR, LPWSTR, LPWSTR);
58 DWORD (WINAPI *fpEnumPrintProcessors)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
59 DWORD (WINAPI *fpGetPrintProcessorDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
60 DWORD (WINAPI *fpDeletePrintProcessor)(LPWSTR, LPWSTR, LPWSTR);
61 DWORD (WINAPI *fpEnumPrintProcessorDatatypes)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
62 DWORD (WINAPI *fpStartDocPrinter)(HANDLE, DWORD, LPBYTE);
63 DWORD (WINAPI *fpStartPagePrinter)(HANDLE);
64 DWORD (WINAPI *fpWritePrinter)(HANDLE, LPVOID, DWORD, LPDWORD);
65 DWORD (WINAPI *fpEndPagePrinter)(HANDLE);
66 DWORD (WINAPI *fpAbortPrinter)(HANDLE);
67 DWORD (WINAPI *fpReadPrinter)(HANDLE, LPVOID, DWORD, LPDWORD);
68 DWORD (WINAPI *fpEndDocPrinter)(HANDLE);
69 DWORD (WINAPI *fpAddJob)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
70 DWORD (WINAPI *fpScheduleJob)(HANDLE, DWORD);
71 DWORD (WINAPI *fpGetPrinterData)(HANDLE, LPWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
72 DWORD (WINAPI *fpSetPrinterData)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD);
73 DWORD (WINAPI *fpWaitForPrinterChange)(HANDLE, DWORD);
74 DWORD (WINAPI *fpClosePrinter)(HANDLE);
75 DWORD (WINAPI *fpAddForm)(HANDLE, DWORD, LPBYTE);
76 DWORD (WINAPI *fpDeleteForm)(HANDLE, LPWSTR);
77 DWORD (WINAPI *fpGetForm)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
78 DWORD (WINAPI *fpSetForm)(HANDLE, LPWSTR, DWORD, LPBYTE);
79 DWORD (WINAPI *fpEnumForms)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
80 DWORD (WINAPI *fpEnumMonitors)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
81 DWORD (WINAPI *fpEnumPorts)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
82 DWORD (WINAPI *fpAddPort)(LPWSTR, HWND, LPWSTR);
83 DWORD (WINAPI *fpConfigurePort)(LPWSTR, HWND, LPWSTR);
84 DWORD (WINAPI *fpDeletePort)(LPWSTR, HWND, LPWSTR);
85 HANDLE (WINAPI *fpCreatePrinterIC)(HANDLE, LPDEVMODEW);
86 DWORD (WINAPI *fpPlayGdiScriptOnPrinterIC)(HANDLE, LPBYTE, DWORD, LPBYTE, DWORD, DWORD);
87 DWORD (WINAPI *fpDeletePrinterIC)(HANDLE);
88 DWORD (WINAPI *fpAddPrinterConnection)(LPWSTR);
89 DWORD (WINAPI *fpDeletePrinterConnection)(LPWSTR);
90 DWORD (WINAPI *fpPrinterMessageBox)(HANDLE, DWORD, HWND, LPWSTR, LPWSTR, DWORD);
91 DWORD (WINAPI *fpAddMonitor)(LPWSTR, DWORD, LPBYTE);
92 DWORD (WINAPI *fpDeleteMonitor)(LPWSTR, LPWSTR, LPWSTR);
93 DWORD (WINAPI *fpResetPrinter)(HANDLE, LPPRINTER_DEFAULTSW);
94 DWORD (WINAPI *fpGetPrinterDriverEx)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, DWORD, DWORD, PDWORD, PDWORD);
95 HANDLE (WINAPI *fpFindFirstPrinterChangeNotification)(HANDLE, DWORD, DWORD, LPVOID);
96 DWORD (WINAPI *fpFindClosePrinterChangeNotification)(HANDLE);
97 DWORD (WINAPI *fpAddPortEx)(HANDLE, LPWSTR, DWORD, LPBYTE, LPWSTR);
98 DWORD (WINAPI *fpShutDown)(LPVOID);
99 DWORD (WINAPI *fpRefreshPrinterChangeNotification)(HANDLE, DWORD, PVOID, PVOID);
100 DWORD (WINAPI *fpOpenPrinterEx)(LPWSTR, LPHANDLE, LPPRINTER_DEFAULTSW, LPBYTE, DWORD);
101 HANDLE (WINAPI *fpAddPrinterEx)(LPWSTR, DWORD, LPBYTE, LPBYTE, DWORD);
102 DWORD (WINAPI *fpSetPort)(LPWSTR, LPWSTR, DWORD, LPBYTE);
103 DWORD (WINAPI *fpEnumPrinterData)(HANDLE, DWORD, LPWSTR, DWORD, LPDWORD, LPDWORD, LPBYTE, DWORD, LPDWORD);
104 DWORD (WINAPI *fpDeletePrinterData)(HANDLE, LPWSTR);
105 DWORD (WINAPI *fpClusterSplOpen)(LPCWSTR, LPCWSTR, PHANDLE, LPCWSTR, LPCWSTR);
106 DWORD (WINAPI *fpClusterSplClose)(HANDLE);
107 DWORD (WINAPI *fpClusterSplIsAlive)(HANDLE);
108 DWORD (WINAPI *fpSetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, DWORD, LPBYTE, DWORD);
109 DWORD (WINAPI *fpGetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
110 DWORD (WINAPI *fpEnumPrinterDataEx)(HANDLE, LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD);
111 DWORD (WINAPI *fpEnumPrinterKey)(HANDLE, LPCWSTR, LPWSTR, DWORD, LPDWORD);
112 DWORD (WINAPI *fpDeletePrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR);
113 DWORD (WINAPI *fpDeletePrinterKey)(HANDLE hPrinter, LPCWSTR pKeyName);
114 DWORD (WINAPI *fpSeekPrinter)(HANDLE, LARGE_INTEGER, PLARGE_INTEGER, DWORD, BOOL);
115 DWORD (WINAPI *fpDeletePrinterDriverEx)(LPWSTR, LPWSTR, LPWSTR, DWORD, DWORD);
116 DWORD (WINAPI *fpAddPerMachineConnection)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
117 DWORD (WINAPI *fpDeletePerMachineConnection)(LPCWSTR, LPCWSTR);
118 DWORD (WINAPI *fpEnumPerMachineConnections)(LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD);
119 DWORD (WINAPI *fpXcvData)(HANDLE, LPCWSTR, PBYTE, DWORD, PBYTE, DWORD, PDWORD, PDWORD);
120 DWORD (WINAPI *fpAddPrinterDriverEx)(LPWSTR, DWORD, LPBYTE, DWORD);
121 DWORD (WINAPI *fpSplReadPrinter)(HANDLE, LPBYTE *, DWORD);
122 DWORD (WINAPI *fpDriverUnloadComplete)(LPWSTR);
123 DWORD (WINAPI *fpGetSpoolFileInfo)(HANDLE, LPWSTR *, LPHANDLE, HANDLE, HANDLE);
124 DWORD (WINAPI *fpCommitSpoolData)(HANDLE, DWORD);
125 DWORD (WINAPI *fpCloseSpoolFileHandle)(HANDLE);
126 DWORD (WINAPI *fpFlushPrinter)(HANDLE, LPBYTE, DWORD, LPDWORD, DWORD);
127 DWORD (WINAPI *fpSendRecvBidiData)(HANDLE, LPCWSTR, LPBIDI_REQUEST_CONTAINER, LPBIDI_RESPONSE_CONTAINER *);
128 DWORD (WINAPI *fpAddDriverCatalog)(HANDLE, DWORD, VOID *, DWORD);
137 /* ################################ */
139 static backend_t *backend[MAX_BACKEND];
140 static DWORD used_backends = 0;
142 static CRITICAL_SECTION backend_cs;
143 static CRITICAL_SECTION_DEBUG backend_cs_debug =
146 { &backend_cs_debug.ProcessLocksList, &backend_cs_debug.ProcessLocksList },
147 0, 0, { (DWORD_PTR)(__FILE__ ": backend_cs") }
149 static CRITICAL_SECTION backend_cs = { &backend_cs_debug, -1, 0, 0, 0, 0 };
151 /* ################################ */
153 static WCHAR localsplW[] = {'l','o','c','a','l','s','p','l','.','d','l','l',0};
155 /******************************************************************
158 * create a copy of a unicode-string
162 static LPWSTR strdupW(LPCWSTR p)
168 len = (lstrlenW(p) + 1) * sizeof(WCHAR);
169 ret = heap_alloc(len);
174 /******************************************************************
175 * backend_unload_all [internal]
177 * unload all backends
179 void backend_unload_all(void)
181 EnterCriticalSection(&backend_cs);
182 while (used_backends > 0) {
184 FreeLibrary(backend[used_backends]->dll);
185 heap_free(backend[used_backends]->dllname);
186 heap_free(backend[used_backends]->name);
187 heap_free(backend[used_backends]->regroot);
188 heap_free(backend[used_backends]);
189 backend[used_backends] = NULL;
191 LeaveCriticalSection(&backend_cs);
194 /******************************************************************************
195 * backend_load [internal]
197 * load and init a backend
200 * name [I] Printprovider to use for the backend. NULL for the local print provider
203 * Success: PTR to the backend
207 static backend_t * backend_load(LPWSTR dllname, LPWSTR name, LPWSTR regroot)
210 BOOL (WINAPI *pInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
214 TRACE("(%s, %s, %s)\n", debugstr_w(dllname), debugstr_w(name), debugstr_w(regroot));
216 EnterCriticalSection(&backend_cs);
219 backend[id] = heap_alloc_zero(sizeof(backend_t));
221 LeaveCriticalSection(&backend_cs);
225 backend[id]->dllname = strdupW(dllname);
226 backend[id]->name = strdupW(name);
227 backend[id]->regroot = strdupW(regroot);
229 backend[id]->dll = LoadLibraryW(dllname);
230 if (backend[id]->dll) {
231 pInitializePrintProvidor = (void *) GetProcAddress(backend[id]->dll, "InitializePrintProvidor");
232 if (pInitializePrintProvidor) {
234 /* native localspl does not clear unused entries */
235 res = pInitializePrintProvidor((PRINTPROVIDOR *) backend[id], sizeof(PRINTPROVIDOR), regroot);
238 backend[id]->index = used_backends;
239 LeaveCriticalSection(&backend_cs);
240 TRACE("--> backend #%d: %p (%s)\n", id, backend[id], debugstr_w(dllname));
244 FreeLibrary(backend[id]->dll);
246 heap_free(backend[id]->dllname);
247 heap_free(backend[id]->name);
248 heap_free(backend[id]->regroot);
249 heap_free(backend[id]);
251 LeaveCriticalSection(&backend_cs);
252 WARN("failed to init %s: %u\n", debugstr_w(dllname), GetLastError());
256 /******************************************************************************
257 * backend_load_all [internal]
259 * load and init all backends
266 BOOL backend_load_all(void)
268 static BOOL failed = FALSE;
271 EnterCriticalSection(&backend_cs);
273 /* if we failed before, dont try again */
274 if (!failed && (used_backends == 0)) {
275 pb = backend_load(localsplW, NULL, NULL);
277 /* ToDo: parse the registry and load all other backends */
279 failed = (used_backends == 0);
281 LeaveCriticalSection(&backend_cs);
282 TRACE("-> %d\n", !failed);
286 /******************************************************************************
287 * backend_first [internal]
289 * find the first usable backend
292 * Success: PTR to the backend
296 static backend_t * backend_first(LPWSTR name)
299 EnterCriticalSection(&backend_cs);
300 /* Load all backends, when not done yet */
301 if (used_backends || backend_load_all()) {
303 /* test for the local system first */
304 if (!name || !name[0]) {
305 LeaveCriticalSection(&backend_cs);
310 FIXME("server %s not supported in %d backends\n", debugstr_w(name), used_backends);
311 LeaveCriticalSection(&backend_cs);
315 /******************************************************************
316 * EnumMonitorsW (spoolss.@)
318 * Enumerate available Port-Monitors
321 * pName [I] Servername or NULL (local Computer)
322 * Level [I] Structure-Level
323 * pMonitors [O] PTR to Buffer that receives the Result
324 * cbBuf [I] Size of Buffer at pMonitors
325 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors
326 * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors
330 * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small
333 BOOL WINAPI EnumMonitorsW(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf,
334 LPDWORD pcbNeeded, LPDWORD pcReturned)
337 DWORD res = ROUTER_UNKNOWN;
339 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors,
340 cbBuf, pcbNeeded, pcReturned);
342 if (pcbNeeded) *pcbNeeded = 0;
343 if (pcReturned) *pcReturned = 0;
345 pb = backend_first(pName);
346 if (pb && pb->fpEnumMonitors)
347 res = pb->fpEnumMonitors(pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
350 SetLastError(ERROR_PROC_NOT_FOUND);
353 TRACE("got %u with %u (%u byte for %u entries)\n\n", res, GetLastError(),
354 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
356 return (res == ROUTER_SUCCESS);
359 /******************************************************************
360 * EnumPortsW (spoolss.@)
362 * Enumerate available Ports
365 * pName [I] Servername or NULL (local Computer)
366 * Level [I] Structure-Level (1 or 2)
367 * pPorts [O] PTR to Buffer that receives the Result
368 * cbBuf [I] Size of Buffer at pPorts
369 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
370 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
374 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
377 BOOL WINAPI EnumPortsW(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf,
378 LPDWORD pcbNeeded, LPDWORD pcReturned)
381 DWORD res = ROUTER_UNKNOWN;
383 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts, cbBuf,
384 pcbNeeded, pcReturned);
386 if (pcbNeeded) *pcbNeeded = 0;
387 if (pcReturned) *pcReturned = 0;
389 pb = backend_first(pName);
390 if (pb && pb->fpEnumPorts)
391 res = pb->fpEnumPorts(pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
394 SetLastError(ERROR_PROC_NOT_FOUND);
397 TRACE("got %u with %u (%u byte for %u entries)\n", res, GetLastError(),
398 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
400 return (res == ROUTER_SUCCESS);