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
;
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
);
285 /******************************************************************************
286 * backend_first [internal]
288 * find the first usable backend
291 * Success: PTR to the backend
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
);
309 FIXME("server %s not supported in %d backends\n", debugstr_w(name
), used_backends
);
310 LeaveCriticalSection(&backend_cs
);
314 /******************************************************************
315 * AddMonitorW (spoolss.@)
317 * Install a Printmonitor
320 * pName [I] Servername or NULL (local Computer)
321 * Level [I] Structure-Level (Must be 2)
322 * pMonitors [I] PTR to MONITOR_INFO_2
329 * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32")
332 BOOL WINAPI
AddMonitorW(LPWSTR pName
, DWORD Level
, LPBYTE pMonitors
)
335 DWORD res
= ROUTER_UNKNOWN
;
337 TRACE("(%s, %d, %p)\n", debugstr_w(pName
), Level
, pMonitors
);
340 SetLastError(ERROR_INVALID_LEVEL
);
344 pb
= backend_first(pName
);
345 if (pb
&& pb
->fpAddMonitor
)
346 res
= pb
->fpAddMonitor(pName
, Level
, pMonitors
);
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
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
372 BOOL WINAPI
AddPrinterDriverExW(LPWSTR pName
, DWORD level
, LPBYTE pDriverInfo
, DWORD dwFileCopyFlags
)
375 DWORD res
= ROUTER_UNKNOWN
;
377 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName
), level
, pDriverInfo
, dwFileCopyFlags
);
380 SetLastError(ERROR_INVALID_PARAMETER
);
384 pb
= backend_first(pName
);
385 if (pb
&& pb
->fpAddPrinterDriverEx
)
386 res
= pb
->fpAddPrinterDriverEx(pName
, level
, pDriverInfo
, dwFileCopyFlags
);
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
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
411 BOOL WINAPI
DeleteMonitorW(LPWSTR pName
, LPWSTR pEnvironment
, LPWSTR pMonitorName
)
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
);
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
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
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
)
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
);
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
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
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
)
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
);
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
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
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
)
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
);
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
);