wbemprox: Prefer the standard ARRAY_SIZE macro.
[wine.git] / dlls / spoolss / router.c
blob764721b202cc0727d92879ea3ee6a10a995a6f2e
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"
34 #include "wine/heap.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
38 /* ################################ */
40 #define MAX_BACKEND 3
42 typedef struct {
43 /* PRINTPROVIDOR functions */
44 DWORD (WINAPI *fpOpenPrinter)(LPWSTR, HANDLE *, LPPRINTER_DEFAULTSW);
45 DWORD (WINAPI *fpSetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD);
46 DWORD (WINAPI *fpGetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD, LPDWORD);
47 DWORD (WINAPI *fpEnumJobs)(HANDLE, DWORD, DWORD, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
48 HANDLE (WINAPI *fpAddPrinter)(LPWSTR, DWORD, LPBYTE);
49 DWORD (WINAPI *fpDeletePrinter)(HANDLE);
50 DWORD (WINAPI *fpSetPrinter)(HANDLE, DWORD, LPBYTE, DWORD);
51 DWORD (WINAPI *fpGetPrinter)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
52 DWORD (WINAPI *fpEnumPrinters)(DWORD, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
53 DWORD (WINAPI *fpAddPrinterDriver)(LPWSTR, DWORD, LPBYTE);
54 DWORD (WINAPI *fpEnumPrinterDrivers)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
55 DWORD (WINAPI *fpGetPrinterDriver)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
56 DWORD (WINAPI *fpGetPrinterDriverDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
57 DWORD (WINAPI *fpDeletePrinterDriver)(LPWSTR, LPWSTR, LPWSTR);
58 DWORD (WINAPI *fpAddPrintProcessor)(LPWSTR, LPWSTR, LPWSTR, LPWSTR);
59 DWORD (WINAPI *fpEnumPrintProcessors)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
60 DWORD (WINAPI *fpGetPrintProcessorDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
61 DWORD (WINAPI *fpDeletePrintProcessor)(LPWSTR, LPWSTR, LPWSTR);
62 DWORD (WINAPI *fpEnumPrintProcessorDatatypes)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
63 DWORD (WINAPI *fpStartDocPrinter)(HANDLE, DWORD, LPBYTE);
64 DWORD (WINAPI *fpStartPagePrinter)(HANDLE);
65 DWORD (WINAPI *fpWritePrinter)(HANDLE, LPVOID, DWORD, LPDWORD);
66 DWORD (WINAPI *fpEndPagePrinter)(HANDLE);
67 DWORD (WINAPI *fpAbortPrinter)(HANDLE);
68 DWORD (WINAPI *fpReadPrinter)(HANDLE, LPVOID, DWORD, LPDWORD);
69 DWORD (WINAPI *fpEndDocPrinter)(HANDLE);
70 DWORD (WINAPI *fpAddJob)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
71 DWORD (WINAPI *fpScheduleJob)(HANDLE, DWORD);
72 DWORD (WINAPI *fpGetPrinterData)(HANDLE, LPWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
73 DWORD (WINAPI *fpSetPrinterData)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD);
74 DWORD (WINAPI *fpWaitForPrinterChange)(HANDLE, DWORD);
75 DWORD (WINAPI *fpClosePrinter)(HANDLE);
76 DWORD (WINAPI *fpAddForm)(HANDLE, DWORD, LPBYTE);
77 DWORD (WINAPI *fpDeleteForm)(HANDLE, LPWSTR);
78 DWORD (WINAPI *fpGetForm)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
79 DWORD (WINAPI *fpSetForm)(HANDLE, LPWSTR, DWORD, LPBYTE);
80 DWORD (WINAPI *fpEnumForms)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
81 DWORD (WINAPI *fpEnumMonitors)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
82 DWORD (WINAPI *fpEnumPorts)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
83 DWORD (WINAPI *fpAddPort)(LPWSTR, HWND, LPWSTR);
84 DWORD (WINAPI *fpConfigurePort)(LPWSTR, HWND, LPWSTR);
85 DWORD (WINAPI *fpDeletePort)(LPWSTR, HWND, LPWSTR);
86 HANDLE (WINAPI *fpCreatePrinterIC)(HANDLE, LPDEVMODEW);
87 DWORD (WINAPI *fpPlayGdiScriptOnPrinterIC)(HANDLE, LPBYTE, DWORD, LPBYTE, DWORD, DWORD);
88 DWORD (WINAPI *fpDeletePrinterIC)(HANDLE);
89 DWORD (WINAPI *fpAddPrinterConnection)(LPWSTR);
90 DWORD (WINAPI *fpDeletePrinterConnection)(LPWSTR);
91 DWORD (WINAPI *fpPrinterMessageBox)(HANDLE, DWORD, HWND, LPWSTR, LPWSTR, DWORD);
92 DWORD (WINAPI *fpAddMonitor)(LPWSTR, DWORD, LPBYTE);
93 DWORD (WINAPI *fpDeleteMonitor)(LPWSTR, LPWSTR, LPWSTR);
94 DWORD (WINAPI *fpResetPrinter)(HANDLE, LPPRINTER_DEFAULTSW);
95 DWORD (WINAPI *fpGetPrinterDriverEx)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, DWORD, DWORD, PDWORD, PDWORD);
96 HANDLE (WINAPI *fpFindFirstPrinterChangeNotification)(HANDLE, DWORD, DWORD, LPVOID);
97 DWORD (WINAPI *fpFindClosePrinterChangeNotification)(HANDLE);
98 DWORD (WINAPI *fpAddPortEx)(HANDLE, LPWSTR, DWORD, LPBYTE, LPWSTR);
99 DWORD (WINAPI *fpShutDown)(LPVOID);
100 DWORD (WINAPI *fpRefreshPrinterChangeNotification)(HANDLE, DWORD, PVOID, PVOID);
101 DWORD (WINAPI *fpOpenPrinterEx)(LPWSTR, LPHANDLE, LPPRINTER_DEFAULTSW, LPBYTE, DWORD);
102 HANDLE (WINAPI *fpAddPrinterEx)(LPWSTR, DWORD, LPBYTE, LPBYTE, DWORD);
103 DWORD (WINAPI *fpSetPort)(LPWSTR, LPWSTR, DWORD, LPBYTE);
104 DWORD (WINAPI *fpEnumPrinterData)(HANDLE, DWORD, LPWSTR, DWORD, LPDWORD, LPDWORD, LPBYTE, DWORD, LPDWORD);
105 DWORD (WINAPI *fpDeletePrinterData)(HANDLE, LPWSTR);
106 DWORD (WINAPI *fpClusterSplOpen)(LPCWSTR, LPCWSTR, PHANDLE, LPCWSTR, LPCWSTR);
107 DWORD (WINAPI *fpClusterSplClose)(HANDLE);
108 DWORD (WINAPI *fpClusterSplIsAlive)(HANDLE);
109 DWORD (WINAPI *fpSetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, DWORD, LPBYTE, DWORD);
110 DWORD (WINAPI *fpGetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
111 DWORD (WINAPI *fpEnumPrinterDataEx)(HANDLE, LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD);
112 DWORD (WINAPI *fpEnumPrinterKey)(HANDLE, LPCWSTR, LPWSTR, DWORD, LPDWORD);
113 DWORD (WINAPI *fpDeletePrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR);
114 DWORD (WINAPI *fpDeletePrinterKey)(HANDLE hPrinter, LPCWSTR pKeyName);
115 DWORD (WINAPI *fpSeekPrinter)(HANDLE, LARGE_INTEGER, PLARGE_INTEGER, DWORD, BOOL);
116 DWORD (WINAPI *fpDeletePrinterDriverEx)(LPWSTR, LPWSTR, LPWSTR, DWORD, DWORD);
117 DWORD (WINAPI *fpAddPerMachineConnection)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
118 DWORD (WINAPI *fpDeletePerMachineConnection)(LPCWSTR, LPCWSTR);
119 DWORD (WINAPI *fpEnumPerMachineConnections)(LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD);
120 DWORD (WINAPI *fpXcvData)(HANDLE, LPCWSTR, PBYTE, DWORD, PBYTE, DWORD, PDWORD, PDWORD);
121 DWORD (WINAPI *fpAddPrinterDriverEx)(LPWSTR, DWORD, LPBYTE, DWORD);
122 DWORD (WINAPI *fpSplReadPrinter)(HANDLE, LPBYTE *, DWORD);
123 DWORD (WINAPI *fpDriverUnloadComplete)(LPWSTR);
124 DWORD (WINAPI *fpGetSpoolFileInfo)(HANDLE, LPWSTR *, LPHANDLE, HANDLE, HANDLE);
125 DWORD (WINAPI *fpCommitSpoolData)(HANDLE, DWORD);
126 DWORD (WINAPI *fpCloseSpoolFileHandle)(HANDLE);
127 DWORD (WINAPI *fpFlushPrinter)(HANDLE, LPBYTE, DWORD, LPDWORD, DWORD);
128 DWORD (WINAPI *fpSendRecvBidiData)(HANDLE, LPCWSTR, LPBIDI_REQUEST_CONTAINER, LPBIDI_RESPONSE_CONTAINER *);
129 DWORD (WINAPI *fpAddDriverCatalog)(HANDLE, DWORD, VOID *, DWORD);
130 /* Private Data */
131 HMODULE dll;
132 LPWSTR dllname;
133 LPWSTR name;
134 LPWSTR regroot;
135 DWORD index;
136 } backend_t;
138 /* ################################ */
140 static backend_t *backend[MAX_BACKEND];
141 static DWORD used_backends = 0;
143 static CRITICAL_SECTION backend_cs;
144 static CRITICAL_SECTION_DEBUG backend_cs_debug =
146 0, 0, &backend_cs,
147 { &backend_cs_debug.ProcessLocksList, &backend_cs_debug.ProcessLocksList },
148 0, 0, { (DWORD_PTR)(__FILE__ ": backend_cs") }
150 static CRITICAL_SECTION backend_cs = { &backend_cs_debug, -1, 0, 0, 0, 0 };
152 /* ################################ */
154 static WCHAR localsplW[] = {'l','o','c','a','l','s','p','l','.','d','l','l',0};
156 /******************************************************************
157 * strdupW [internal]
159 * create a copy of a unicode-string
163 static LPWSTR strdupW(LPCWSTR p)
165 LPWSTR ret;
166 DWORD len;
168 if(!p) return NULL;
169 len = (lstrlenW(p) + 1) * sizeof(WCHAR);
170 ret = heap_alloc(len);
171 memcpy(ret, p, len);
172 return ret;
175 /******************************************************************
176 * backend_unload_all [internal]
178 * unload all backends
180 void backend_unload_all(void)
182 EnterCriticalSection(&backend_cs);
183 while (used_backends > 0) {
184 used_backends--;
185 FreeLibrary(backend[used_backends]->dll);
186 heap_free(backend[used_backends]->dllname);
187 heap_free(backend[used_backends]->name);
188 heap_free(backend[used_backends]->regroot);
189 heap_free(backend[used_backends]);
190 backend[used_backends] = NULL;
192 LeaveCriticalSection(&backend_cs);
195 /******************************************************************************
196 * backend_load [internal]
198 * load and init a backend
200 * PARAMS
201 * name [I] Printprovider to use for the backend. NULL for the local print provider
203 * RETURNS
204 * Success: PTR to the backend
205 * Failure: NULL
208 static backend_t * backend_load(LPWSTR dllname, LPWSTR name, LPWSTR regroot)
211 BOOL (WINAPI *pInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
212 DWORD id;
213 DWORD res;
215 TRACE("(%s, %s, %s)\n", debugstr_w(dllname), debugstr_w(name), debugstr_w(regroot));
217 EnterCriticalSection(&backend_cs);
218 id = used_backends;
220 backend[id] = heap_alloc_zero(sizeof(backend_t));
221 if (!backend[id]) {
222 LeaveCriticalSection(&backend_cs);
223 return NULL;
226 backend[id]->dllname = strdupW(dllname);
227 backend[id]->name = strdupW(name);
228 backend[id]->regroot = strdupW(regroot);
230 backend[id]->dll = LoadLibraryW(dllname);
231 if (backend[id]->dll) {
232 pInitializePrintProvidor = (void *) GetProcAddress(backend[id]->dll, "InitializePrintProvidor");
233 if (pInitializePrintProvidor) {
235 /* native localspl does not clear unused entries */
236 res = pInitializePrintProvidor((PRINTPROVIDOR *) backend[id], sizeof(PRINTPROVIDOR), regroot);
237 if (res) {
238 used_backends++;
239 backend[id]->index = used_backends;
240 LeaveCriticalSection(&backend_cs);
241 TRACE("--> backend #%d: %p (%s)\n", id, backend[id], debugstr_w(dllname));
242 return backend[id];
245 FreeLibrary(backend[id]->dll);
247 heap_free(backend[id]->dllname);
248 heap_free(backend[id]->name);
249 heap_free(backend[id]->regroot);
250 heap_free(backend[id]);
251 backend[id] = NULL;
252 LeaveCriticalSection(&backend_cs);
253 WARN("failed to init %s: %u\n", debugstr_w(dllname), GetLastError());
254 return NULL;
257 /******************************************************************************
258 * backend_load_all [internal]
260 * load and init all backends
262 * RETURNS
263 * Success: TRUE
264 * Failure: FALSE
267 BOOL backend_load_all(void)
269 static BOOL failed = FALSE;
271 EnterCriticalSection(&backend_cs);
273 /* if we failed before, don't try again */
274 if (!failed && (used_backends == 0)) {
275 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);
283 return (!failed);
286 /******************************************************************************
287 * backend_first [internal]
289 * find the first usable backend
291 * RETURNS
292 * Success: PTR to the backend
293 * Failure: NULL
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);
306 return backend[0];
310 FIXME("server %s not supported in %d backends\n", debugstr_w(name), used_backends);
311 LeaveCriticalSection(&backend_cs);
312 return NULL;
315 /******************************************************************
316 * AddMonitorW (spoolss.@)
318 * Install a Printmonitor
320 * PARAMS
321 * pName [I] Servername or NULL (local Computer)
322 * Level [I] Structure-Level (Must be 2)
323 * pMonitors [I] PTR to MONITOR_INFO_2
325 * RETURNS
326 * Success: TRUE
327 * Failure: FALSE
329 * NOTES
330 * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32")
333 BOOL WINAPI AddMonitorW(LPWSTR pName, DWORD Level, LPBYTE pMonitors)
335 backend_t * pb;
336 DWORD res = ROUTER_UNKNOWN;
338 TRACE("(%s, %d, %p)\n", debugstr_w(pName), Level, pMonitors);
340 if (Level != 2) {
341 SetLastError(ERROR_INVALID_LEVEL);
342 return FALSE;
345 pb = backend_first(pName);
346 if (pb && pb->fpAddMonitor)
347 res = pb->fpAddMonitor(pName, Level, pMonitors);
348 else
350 SetLastError(ERROR_PROC_NOT_FOUND);
353 TRACE("got %u with %u\n", res, GetLastError());
354 return (res == ROUTER_SUCCESS);
357 /******************************************************************
358 * AddPrinterDriverExW (spoolss.@)
360 * Install a Printer Driver with the Option to upgrade / downgrade the Files
362 * PARAMS
363 * pName [I] Servername or NULL (local Computer)
364 * level [I] Level for the supplied DRIVER_INFO_*W struct
365 * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter
366 * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files
368 * RESULTS
369 * Success: TRUE
370 * Failure: FALSE
373 BOOL WINAPI AddPrinterDriverExW(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
375 backend_t * pb;
376 DWORD res = ROUTER_UNKNOWN;
378 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags);
380 if (!pDriverInfo) {
381 SetLastError(ERROR_INVALID_PARAMETER);
382 return FALSE;
385 pb = backend_first(pName);
386 if (pb && pb->fpAddPrinterDriverEx)
387 res = pb->fpAddPrinterDriverEx(pName, level, pDriverInfo, dwFileCopyFlags);
388 else
390 SetLastError(ERROR_PROC_NOT_FOUND);
393 TRACE("got %u with %u\n", res, GetLastError());
394 return (res == ROUTER_SUCCESS);
397 /******************************************************************
398 * DeleteMonitorW (spoolss.@)
400 * Delete a specific Printmonitor from a Printing-Environment
402 * PARAMS
403 * pName [I] Servername or NULL (local Computer)
404 * pEnvironment [I] Printing-Environment of the Monitor or NULL (Default)
405 * pMonitorName [I] Name of the Monitor, that should be deleted
407 * RETURNS
408 * Success: TRUE
409 * Failure: FALSE
412 BOOL WINAPI DeleteMonitorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName)
414 backend_t * pb;
415 DWORD res = ROUTER_UNKNOWN;
417 TRACE("(%s, %s, %s)\n", debugstr_w(pName), debugstr_w(pEnvironment), debugstr_w(pMonitorName));
419 pb = backend_first(pName);
420 if (pb && pb->fpDeleteMonitor)
421 res = pb->fpDeleteMonitor(pName, pEnvironment, pMonitorName);
422 else
424 SetLastError(ERROR_PROC_NOT_FOUND);
427 TRACE("got %u with %u\n", res, GetLastError());
428 return (res == ROUTER_SUCCESS);
431 /******************************************************************
432 * EnumMonitorsW (spoolss.@)
434 * Enumerate available Port-Monitors
436 * PARAMS
437 * pName [I] Servername or NULL (local Computer)
438 * Level [I] Structure-Level
439 * pMonitors [O] PTR to Buffer that receives the Result
440 * cbBuf [I] Size of Buffer at pMonitors
441 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors
442 * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors
444 * RETURNS
445 * Success: TRUE
446 * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small
449 BOOL WINAPI EnumMonitorsW(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf,
450 LPDWORD pcbNeeded, LPDWORD pcReturned)
452 backend_t * pb;
453 DWORD res = ROUTER_UNKNOWN;
455 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors,
456 cbBuf, pcbNeeded, pcReturned);
458 if (pcbNeeded) *pcbNeeded = 0;
459 if (pcReturned) *pcReturned = 0;
461 pb = backend_first(pName);
462 if (pb && pb->fpEnumMonitors)
463 res = pb->fpEnumMonitors(pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
464 else
466 SetLastError(ERROR_PROC_NOT_FOUND);
469 TRACE("got %u with %u (%u byte for %u entries)\n\n", res, GetLastError(),
470 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
472 return (res == ROUTER_SUCCESS);
475 /******************************************************************
476 * EnumPortsW (spoolss.@)
478 * Enumerate available Ports
480 * PARAMS
481 * pName [I] Servername or NULL (local Computer)
482 * Level [I] Structure-Level (1 or 2)
483 * pPorts [O] PTR to Buffer that receives the Result
484 * cbBuf [I] Size of Buffer at pPorts
485 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
486 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
488 * RETURNS
489 * Success: TRUE
490 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
493 BOOL WINAPI EnumPortsW(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf,
494 LPDWORD pcbNeeded, LPDWORD pcReturned)
496 backend_t * pb;
497 DWORD res = ROUTER_UNKNOWN;
499 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts, cbBuf,
500 pcbNeeded, pcReturned);
502 if (pcbNeeded) *pcbNeeded = 0;
503 if (pcReturned) *pcReturned = 0;
505 pb = backend_first(pName);
506 if (pb && pb->fpEnumPorts)
507 res = pb->fpEnumPorts(pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
508 else
510 SetLastError(ERROR_PROC_NOT_FOUND);
513 TRACE("got %u with %u (%u byte for %u entries)\n", res, GetLastError(),
514 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
516 return (res == ROUTER_SUCCESS);
519 /******************************************************************
520 * GetPrinterDriverDirectoryW (spoolss.@)
522 * Return the PATH for the Printer-Drivers
524 * PARAMS
525 * pName [I] Servername or NULL (local Computer)
526 * pEnvironment [I] Printing-Environment or NULL (Default)
527 * Level [I] Structure-Level (must be 1)
528 * pDriverDirectory [O] PTR to Buffer that receives the Result
529 * cbBuf [I] Size of Buffer at pDriverDirectory
530 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used /
531 * required for pDriverDirectory
533 * RETURNS
534 * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory
535 * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory,
536 * if cbBuf is too small
538 * Native Values returned in pDriverDirectory on Success:
539 *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86"
540 *| NT(Windows x64): "%winsysdir%\\spool\\DRIVERS\\x64"
541 *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40"
542 *| win9x(Windows 4.0): "%winsysdir%"
544 * "%winsysdir%" is the Value from GetSystemDirectoryW()
547 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
548 DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded)
550 backend_t * pb;
551 DWORD res = ROUTER_UNKNOWN;
553 TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName),
554 debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
556 if (pcbNeeded) *pcbNeeded = 0;
558 pb = backend_first(pName);
559 if (pb && pb->fpGetPrinterDriverDirectory)
560 res = pb->fpGetPrinterDriverDirectory(pName, pEnvironment, Level,
561 pDriverDirectory, cbBuf, pcbNeeded);
562 else
564 SetLastError(ERROR_PROC_NOT_FOUND);
567 TRACE("got %u with %u (%u byte)\n",
568 res, GetLastError(), pcbNeeded ? *pcbNeeded : 0);
570 return (res == ROUTER_SUCCESS);