server: Bump priority on server to process messages faster
[wine/multimedia.git] / dlls / spoolss / router.c
blob3d239b4afb9c3a8a39eb1cf66842be15bd0119bb
1 /*
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "winreg.h"
28 #include "wingdi.h"
29 #include "winspool.h"
30 #include "ddk/winsplp.h"
31 #include "spoolss.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
37 /* ################################ */
39 #define MAX_BACKEND 3
41 typedef struct {
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);
129 /* Private Data */
130 HMODULE dll;
131 LPWSTR dllname;
132 LPWSTR name;
133 LPWSTR regroot;
134 DWORD index;
135 } backend_t;
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 =
145 0, 0, &backend_cs,
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 /******************************************************************
156 * strdupW [internal]
158 * create a copy of a unicode-string
162 static LPWSTR strdupW(LPCWSTR p)
164 LPWSTR ret;
165 DWORD len;
167 if(!p) return NULL;
168 len = (lstrlenW(p) + 1) * sizeof(WCHAR);
169 ret = heap_alloc(len);
170 memcpy(ret, p, len);
171 return ret;
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) {
183 used_backends--;
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
199 * PARAMS
200 * name [I] Printprovider to use for the backend. NULL for the local print provider
202 * RETURNS
203 * Success: PTR to the backend
204 * Failure: NULL
207 static backend_t * backend_load(LPWSTR dllname, LPWSTR name, LPWSTR regroot)
210 BOOL (WINAPI *pInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
211 DWORD id;
212 DWORD res;
214 TRACE("(%s, %s, %s)\n", debugstr_w(dllname), debugstr_w(name), debugstr_w(regroot));
216 EnterCriticalSection(&backend_cs);
217 id = used_backends;
219 backend[id] = heap_alloc_zero(sizeof(backend_t));
220 if (!backend[id]) {
221 LeaveCriticalSection(&backend_cs);
222 return NULL;
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);
236 if (res) {
237 used_backends++;
238 backend[id]->index = used_backends;
239 LeaveCriticalSection(&backend_cs);
240 TRACE("--> backend #%d: %p (%s)\n", id, backend[id], debugstr_w(dllname));
241 return backend[id];
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]);
250 backend[id] = NULL;
251 LeaveCriticalSection(&backend_cs);
252 WARN("failed to init %s: %u\n", debugstr_w(dllname), GetLastError());
253 return NULL;
256 /******************************************************************************
257 * backend_load_all [internal]
259 * load and init all backends
261 * RETURNS
262 * Success: TRUE
263 * Failure: FALSE
266 BOOL backend_load_all(void)
268 static BOOL failed = FALSE;
270 EnterCriticalSection(&backend_cs);
272 /* if we failed before, don't try again */
273 if (!failed && (used_backends == 0)) {
274 backend_load(localsplW, NULL, NULL);
276 /* ToDo: parse the registry and load all other backends */
278 failed = (used_backends == 0);
280 LeaveCriticalSection(&backend_cs);
281 TRACE("-> %d\n", !failed);
282 return (!failed);
285 /******************************************************************************
286 * backend_first [internal]
288 * find the first usable backend
290 * RETURNS
291 * Success: PTR to the backend
292 * Failure: NULL
295 static backend_t * backend_first(LPWSTR name)
298 EnterCriticalSection(&backend_cs);
299 /* Load all backends, when not done yet */
300 if (used_backends || backend_load_all()) {
302 /* test for the local system first */
303 if (!name || !name[0]) {
304 LeaveCriticalSection(&backend_cs);
305 return backend[0];
309 FIXME("server %s not supported in %d backends\n", debugstr_w(name), used_backends);
310 LeaveCriticalSection(&backend_cs);
311 return NULL;
314 /******************************************************************
315 * AddMonitorW (spoolss.@)
317 * Install a Printmonitor
319 * PARAMS
320 * pName [I] Servername or NULL (local Computer)
321 * Level [I] Structure-Level (Must be 2)
322 * pMonitors [I] PTR to MONITOR_INFO_2
324 * RETURNS
325 * Success: TRUE
326 * Failure: FALSE
328 * NOTES
329 * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32")
332 BOOL WINAPI AddMonitorW(LPWSTR pName, DWORD Level, LPBYTE pMonitors)
334 backend_t * pb;
335 DWORD res = ROUTER_UNKNOWN;
337 TRACE("(%s, %d, %p)\n", debugstr_w(pName), Level, pMonitors);
339 if (Level != 2) {
340 SetLastError(ERROR_INVALID_LEVEL);
341 return FALSE;
344 pb = backend_first(pName);
345 if (pb && pb->fpAddMonitor)
346 res = pb->fpAddMonitor(pName, Level, pMonitors);
347 else
349 SetLastError(ERROR_PROC_NOT_FOUND);
352 TRACE("got %u with %u\n", res, GetLastError());
353 return (res == ROUTER_SUCCESS);
356 /******************************************************************
357 * AddPrinterDriverExW (spoolss.@)
359 * Install a Printer Driver with the Option to upgrade / downgrade the Files
361 * PARAMS
362 * pName [I] Servername or NULL (local Computer)
363 * level [I] Level for the supplied DRIVER_INFO_*W struct
364 * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter
365 * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files
367 * RESULTS
368 * Success: TRUE
369 * Failure: FALSE
372 BOOL WINAPI AddPrinterDriverExW(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
374 backend_t * pb;
375 DWORD res = ROUTER_UNKNOWN;
377 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags);
379 if (!pDriverInfo) {
380 SetLastError(ERROR_INVALID_PARAMETER);
381 return FALSE;
384 pb = backend_first(pName);
385 if (pb && pb->fpAddPrinterDriverEx)
386 res = pb->fpAddPrinterDriverEx(pName, level, pDriverInfo, dwFileCopyFlags);
387 else
389 SetLastError(ERROR_PROC_NOT_FOUND);
392 TRACE("got %u with %u\n", res, GetLastError());
393 return (res == ROUTER_SUCCESS);
396 /******************************************************************
397 * DeleteMonitorW (spoolss.@)
399 * Delete a specific Printmonitor from a Printing-Environment
401 * PARAMS
402 * pName [I] Servername or NULL (local Computer)
403 * pEnvironment [I] Printing-Environment of the Monitor or NULL (Default)
404 * pMonitorName [I] Name of the Monitor, that should be deleted
406 * RETURNS
407 * Success: TRUE
408 * Failure: FALSE
411 BOOL WINAPI DeleteMonitorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName)
413 backend_t * pb;
414 DWORD res = ROUTER_UNKNOWN;
416 TRACE("(%s, %s, %s)\n", debugstr_w(pName), debugstr_w(pEnvironment), debugstr_w(pMonitorName));
418 pb = backend_first(pName);
419 if (pb && pb->fpDeleteMonitor)
420 res = pb->fpDeleteMonitor(pName, pEnvironment, pMonitorName);
421 else
423 SetLastError(ERROR_PROC_NOT_FOUND);
426 TRACE("got %u with %u\n", res, GetLastError());
427 return (res == ROUTER_SUCCESS);
430 /******************************************************************
431 * EnumMonitorsW (spoolss.@)
433 * Enumerate available Port-Monitors
435 * PARAMS
436 * pName [I] Servername or NULL (local Computer)
437 * Level [I] Structure-Level
438 * pMonitors [O] PTR to Buffer that receives the Result
439 * cbBuf [I] Size of Buffer at pMonitors
440 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors
441 * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors
443 * RETURNS
444 * Success: TRUE
445 * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small
448 BOOL WINAPI EnumMonitorsW(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf,
449 LPDWORD pcbNeeded, LPDWORD pcReturned)
451 backend_t * pb;
452 DWORD res = ROUTER_UNKNOWN;
454 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors,
455 cbBuf, pcbNeeded, pcReturned);
457 if (pcbNeeded) *pcbNeeded = 0;
458 if (pcReturned) *pcReturned = 0;
460 pb = backend_first(pName);
461 if (pb && pb->fpEnumMonitors)
462 res = pb->fpEnumMonitors(pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
463 else
465 SetLastError(ERROR_PROC_NOT_FOUND);
468 TRACE("got %u with %u (%u byte for %u entries)\n\n", res, GetLastError(),
469 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
471 return (res == ROUTER_SUCCESS);
474 /******************************************************************
475 * EnumPortsW (spoolss.@)
477 * Enumerate available Ports
479 * PARAMS
480 * pName [I] Servername or NULL (local Computer)
481 * Level [I] Structure-Level (1 or 2)
482 * pPorts [O] PTR to Buffer that receives the Result
483 * cbBuf [I] Size of Buffer at pPorts
484 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
485 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
487 * RETURNS
488 * Success: TRUE
489 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
492 BOOL WINAPI EnumPortsW(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf,
493 LPDWORD pcbNeeded, LPDWORD pcReturned)
495 backend_t * pb;
496 DWORD res = ROUTER_UNKNOWN;
498 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts, cbBuf,
499 pcbNeeded, pcReturned);
501 if (pcbNeeded) *pcbNeeded = 0;
502 if (pcReturned) *pcReturned = 0;
504 pb = backend_first(pName);
505 if (pb && pb->fpEnumPorts)
506 res = pb->fpEnumPorts(pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
507 else
509 SetLastError(ERROR_PROC_NOT_FOUND);
512 TRACE("got %u with %u (%u byte for %u entries)\n", res, GetLastError(),
513 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
515 return (res == ROUTER_SUCCESS);
518 /******************************************************************
519 * GetPrinterDriverDirectoryW (spoolss.@)
521 * Return the PATH for the Printer-Drivers
523 * PARAMS
524 * pName [I] Servername or NULL (local Computer)
525 * pEnvironment [I] Printing-Environment or NULL (Default)
526 * Level [I] Structure-Level (must be 1)
527 * pDriverDirectory [O] PTR to Buffer that receives the Result
528 * cbBuf [I] Size of Buffer at pDriverDirectory
529 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used /
530 * required for pDriverDirectory
532 * RETURNS
533 * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory
534 * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory,
535 * if cbBuf is too small
537 * Native Values returned in pDriverDirectory on Success:
538 *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86"
539 *| NT(Windows x64): "%winsysdir%\\spool\\DRIVERS\\x64"
540 *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40"
541 *| win9x(Windows 4.0): "%winsysdir%"
543 * "%winsysdir%" is the Value from GetSystemDirectoryW()
546 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
547 DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded)
549 backend_t * pb;
550 DWORD res = ROUTER_UNKNOWN;
552 TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName),
553 debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
555 if (pcbNeeded) *pcbNeeded = 0;
557 pb = backend_first(pName);
558 if (pb && pb->fpGetPrinterDriverDirectory)
559 res = pb->fpGetPrinterDriverDirectory(pName, pEnvironment, Level,
560 pDriverDirectory, cbBuf, pcbNeeded);
561 else
563 SetLastError(ERROR_PROC_NOT_FOUND);
566 TRACE("got %u with %u (%u byte)\n",
567 res, GetLastError(), pcbNeeded ? *pcbNeeded : 0);
569 return (res == ROUTER_SUCCESS);