ntdll: Validate blocks in the heap pending free request list.
[wine.git] / dlls / spoolss / router.c
blob4d6d7c43559efe31413bc1ff76a88caf56fe80b8
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>
22 #include <stdlib.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "winreg.h"
29 #include "wingdi.h"
30 #include "winspool.h"
31 #include "ddk/winsplp.h"
32 #include "spoolss.h"
34 #include "wine/debug.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"localspl.dll";
156 /******************************************************************
157 * backend_unload_all [internal]
159 * unload all backends
161 void backend_unload_all(void)
163 EnterCriticalSection(&backend_cs);
164 while (used_backends > 0) {
165 used_backends--;
166 FreeLibrary(backend[used_backends]->dll);
167 free(backend[used_backends]->dllname);
168 free(backend[used_backends]->name);
169 free(backend[used_backends]->regroot);
170 free(backend[used_backends]);
171 backend[used_backends] = NULL;
173 LeaveCriticalSection(&backend_cs);
176 /******************************************************************************
177 * backend_load [internal]
179 * load and init a backend
181 * PARAMS
182 * name [I] Printprovider to use for the backend. NULL for the local print provider
184 * RETURNS
185 * Success: PTR to the backend
186 * Failure: NULL
189 static backend_t * backend_load(LPWSTR dllname, LPWSTR name, LPWSTR regroot)
192 BOOL (WINAPI *pInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
193 DWORD id;
194 DWORD res;
196 TRACE("(%s, %s, %s)\n", debugstr_w(dllname), debugstr_w(name), debugstr_w(regroot));
198 EnterCriticalSection(&backend_cs);
199 id = used_backends;
201 backend[id] = calloc(1, sizeof(backend_t));
202 if (!backend[id]) {
203 LeaveCriticalSection(&backend_cs);
204 return NULL;
207 backend[id]->dllname = wcsdup(dllname);
208 backend[id]->name = wcsdup(name);
209 backend[id]->regroot = wcsdup(regroot);
211 backend[id]->dll = LoadLibraryW(dllname);
212 if (backend[id]->dll) {
213 pInitializePrintProvidor = (void *) GetProcAddress(backend[id]->dll, "InitializePrintProvidor");
214 if (pInitializePrintProvidor) {
216 /* native localspl does not clear unused entries */
217 res = pInitializePrintProvidor((PRINTPROVIDOR *) backend[id], sizeof(PRINTPROVIDOR), regroot);
218 if (res) {
219 used_backends++;
220 backend[id]->index = used_backends;
221 LeaveCriticalSection(&backend_cs);
222 TRACE("--> backend #%ld: %p (%s)\n", id, backend[id], debugstr_w(dllname));
223 return backend[id];
226 FreeLibrary(backend[id]->dll);
228 free(backend[id]->dllname);
229 free(backend[id]->name);
230 free(backend[id]->regroot);
231 free(backend[id]);
232 backend[id] = NULL;
233 LeaveCriticalSection(&backend_cs);
234 WARN("failed to init %s: %lu\n", debugstr_w(dllname), GetLastError());
235 return NULL;
238 /******************************************************************************
239 * backend_load_all [internal]
241 * load and init all backends
243 * RETURNS
244 * Success: TRUE
245 * Failure: FALSE
248 BOOL backend_load_all(void)
250 static BOOL failed = FALSE;
252 EnterCriticalSection(&backend_cs);
254 /* if we failed before, don't try again */
255 if (!failed && (used_backends == 0)) {
256 backend_load(localsplW, NULL, NULL);
258 /* ToDo: parse the registry and load all other backends */
260 failed = (used_backends == 0);
262 LeaveCriticalSection(&backend_cs);
263 TRACE("-> %d\n", !failed);
264 return (!failed);
267 /******************************************************************************
268 * backend_first [internal]
270 * find the first usable backend
272 * RETURNS
273 * Success: PTR to the backend
274 * Failure: NULL
277 static backend_t * backend_first(LPWSTR name)
280 EnterCriticalSection(&backend_cs);
281 /* Load all backends, when not done yet */
282 if (used_backends || backend_load_all()) {
284 /* test for the local system first */
285 if (!name || !name[0]) {
286 LeaveCriticalSection(&backend_cs);
287 return backend[0];
291 FIXME("server %s not supported in %ld backends\n", debugstr_w(name), used_backends);
292 LeaveCriticalSection(&backend_cs);
293 return NULL;
296 /******************************************************************
297 * AddMonitorW (spoolss.@)
299 * Install a Printmonitor
301 * PARAMS
302 * pName [I] Servername or NULL (local Computer)
303 * Level [I] Structure-Level (Must be 2)
304 * pMonitors [I] PTR to MONITOR_INFO_2
306 * RETURNS
307 * Success: TRUE
308 * Failure: FALSE
310 * NOTES
311 * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32")
314 BOOL WINAPI AddMonitorW(LPWSTR pName, DWORD Level, LPBYTE pMonitors)
316 backend_t * pb;
317 DWORD res = ROUTER_UNKNOWN;
319 TRACE("(%s, %ld, %p)\n", debugstr_w(pName), Level, pMonitors);
321 if (Level != 2) {
322 SetLastError(ERROR_INVALID_LEVEL);
323 return FALSE;
326 pb = backend_first(pName);
327 if (pb && pb->fpAddMonitor)
328 res = pb->fpAddMonitor(pName, Level, pMonitors);
329 else
331 SetLastError(ERROR_PROC_NOT_FOUND);
334 TRACE("got %lu with %lu\n", res, GetLastError());
335 return (res == ROUTER_SUCCESS);
338 /******************************************************************
339 * AddPrinterDriverExW (spoolss.@)
341 * Install a Printer Driver with the Option to upgrade / downgrade the Files
343 * PARAMS
344 * pName [I] Servername or NULL (local Computer)
345 * level [I] Level for the supplied DRIVER_INFO_*W struct
346 * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter
347 * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files
349 * RESULTS
350 * Success: TRUE
351 * Failure: FALSE
354 BOOL WINAPI AddPrinterDriverExW(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
356 backend_t * pb;
357 DWORD res = ROUTER_UNKNOWN;
359 TRACE("(%s, %ld, %p, 0x%lx)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags);
361 if (!pDriverInfo) {
362 SetLastError(ERROR_INVALID_PARAMETER);
363 return FALSE;
366 pb = backend_first(pName);
367 if (pb && pb->fpAddPrinterDriverEx)
368 res = pb->fpAddPrinterDriverEx(pName, level, pDriverInfo, dwFileCopyFlags);
369 else
371 SetLastError(ERROR_PROC_NOT_FOUND);
374 TRACE("got %lu with %lu\n", res, GetLastError());
375 return (res == ROUTER_SUCCESS);
378 /******************************************************************
379 * DeleteMonitorW (spoolss.@)
381 * Delete a specific Printmonitor from a Printing-Environment
383 * PARAMS
384 * pName [I] Servername or NULL (local Computer)
385 * pEnvironment [I] Printing-Environment of the Monitor or NULL (Default)
386 * pMonitorName [I] Name of the Monitor, that should be deleted
388 * RETURNS
389 * Success: TRUE
390 * Failure: FALSE
393 BOOL WINAPI DeleteMonitorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName)
395 backend_t * pb;
396 DWORD res = ROUTER_UNKNOWN;
398 TRACE("(%s, %s, %s)\n", debugstr_w(pName), debugstr_w(pEnvironment), debugstr_w(pMonitorName));
400 pb = backend_first(pName);
401 if (pb && pb->fpDeleteMonitor)
402 res = pb->fpDeleteMonitor(pName, pEnvironment, pMonitorName);
403 else
405 SetLastError(ERROR_PROC_NOT_FOUND);
408 TRACE("got %lu with %lu\n", res, GetLastError());
409 return (res == ROUTER_SUCCESS);
412 /******************************************************************
413 * EnumMonitorsW (spoolss.@)
415 * Enumerate available Port-Monitors
417 * PARAMS
418 * pName [I] Servername or NULL (local Computer)
419 * Level [I] Structure-Level
420 * pMonitors [O] PTR to Buffer that receives the Result
421 * cbBuf [I] Size of Buffer at pMonitors
422 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors
423 * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors
425 * RETURNS
426 * Success: TRUE
427 * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small
430 BOOL WINAPI EnumMonitorsW(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf,
431 LPDWORD pcbNeeded, LPDWORD pcReturned)
433 backend_t * pb;
434 DWORD res = ROUTER_UNKNOWN;
436 TRACE("(%s, %ld, %p, %ld, %p, %p)\n", debugstr_w(pName), Level, pMonitors,
437 cbBuf, pcbNeeded, pcReturned);
439 if (pcbNeeded) *pcbNeeded = 0;
440 if (pcReturned) *pcReturned = 0;
442 pb = backend_first(pName);
443 if (pb && pb->fpEnumMonitors)
444 res = pb->fpEnumMonitors(pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
445 else
447 SetLastError(ERROR_PROC_NOT_FOUND);
450 TRACE("got %lu with %lu (%lu byte for %lu entries)\n\n", res, GetLastError(),
451 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
453 return (res == ROUTER_SUCCESS);
456 /******************************************************************
457 * EnumPortsW (spoolss.@)
459 * Enumerate available Ports
461 * PARAMS
462 * pName [I] Servername or NULL (local Computer)
463 * Level [I] Structure-Level (1 or 2)
464 * pPorts [O] PTR to Buffer that receives the Result
465 * cbBuf [I] Size of Buffer at pPorts
466 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
467 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
469 * RETURNS
470 * Success: TRUE
471 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
474 BOOL WINAPI EnumPortsW(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf,
475 LPDWORD pcbNeeded, LPDWORD pcReturned)
477 backend_t * pb;
478 DWORD res = ROUTER_UNKNOWN;
480 TRACE("(%s, %ld, %p, %ld, %p, %p)\n", debugstr_w(pName), Level, pPorts, cbBuf,
481 pcbNeeded, pcReturned);
483 if (pcbNeeded) *pcbNeeded = 0;
484 if (pcReturned) *pcReturned = 0;
486 pb = backend_first(pName);
487 if (pb && pb->fpEnumPorts)
488 res = pb->fpEnumPorts(pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
489 else
491 SetLastError(ERROR_PROC_NOT_FOUND);
494 TRACE("got %lu with %lu (%lu byte for %lu entries)\n", res, GetLastError(),
495 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
497 return (res == ROUTER_SUCCESS);
500 /******************************************************************
501 * GetPrinterDriverDirectoryW (spoolss.@)
503 * Return the PATH for the Printer-Drivers
505 * PARAMS
506 * pName [I] Servername or NULL (local Computer)
507 * pEnvironment [I] Printing-Environment or NULL (Default)
508 * Level [I] Structure-Level (must be 1)
509 * pDriverDirectory [O] PTR to Buffer that receives the Result
510 * cbBuf [I] Size of Buffer at pDriverDirectory
511 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used /
512 * required for pDriverDirectory
514 * RETURNS
515 * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory
516 * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory,
517 * if cbBuf is too small
519 * Native Values returned in pDriverDirectory on Success:
520 *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86"
521 *| NT(Windows x64): "%winsysdir%\\spool\\DRIVERS\\x64"
522 *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40"
523 *| win9x(Windows 4.0): "%winsysdir%"
525 * "%winsysdir%" is the Value from GetSystemDirectoryW()
528 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
529 DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded)
531 backend_t * pb;
532 DWORD res = ROUTER_UNKNOWN;
534 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", debugstr_w(pName),
535 debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
537 if (pcbNeeded) *pcbNeeded = 0;
539 pb = backend_first(pName);
540 if (pb && pb->fpGetPrinterDriverDirectory)
541 res = pb->fpGetPrinterDriverDirectory(pName, pEnvironment, Level,
542 pDriverDirectory, cbBuf, pcbNeeded);
543 else
545 SetLastError(ERROR_PROC_NOT_FOUND);
548 TRACE("got %lu with %lu (%lu byte)\n",
549 res, GetLastError(), pcbNeeded ? *pcbNeeded : 0);
551 return (res == ROUTER_SUCCESS);