[RTL][NTDLL]
[reactos.git] / reactos / dll / win32 / spoolss / router.c
1 /*
2 * Routing for Spooler-Service helper DLL
3 *
4 * Copyright 2006-2009 Detlef Riekenberg
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "spoolss.h"
22
23 #include <winreg.h>
24 #include <wingdi.h>
25 #include <winspool.h>
26
27 #include <ddk/winsplp.h>
28
29 /* ################################ */
30
31 #define MAX_BACKEND 3
32
33 typedef struct {
34 /* PRINTPROVIDOR functions */
35 DWORD (WINAPI *fpOpenPrinter)(LPWSTR, HANDLE *, LPPRINTER_DEFAULTSW);
36 DWORD (WINAPI *fpSetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD);
37 DWORD (WINAPI *fpGetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD, LPDWORD);
38 DWORD (WINAPI *fpEnumJobs)(HANDLE, DWORD, DWORD, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
39 HANDLE (WINAPI *fpAddPrinter)(LPWSTR, DWORD, LPBYTE);
40 DWORD (WINAPI *fpDeletePrinter)(HANDLE);
41 DWORD (WINAPI *fpSetPrinter)(HANDLE, DWORD, LPBYTE, DWORD);
42 DWORD (WINAPI *fpGetPrinter)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
43 DWORD (WINAPI *fpEnumPrinters)(DWORD, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
44 DWORD (WINAPI *fpAddPrinterDriver)(LPWSTR, DWORD, LPBYTE);
45 DWORD (WINAPI *fpEnumPrinterDrivers)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
46 DWORD (WINAPI *fpGetPrinterDriver)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
47 DWORD (WINAPI *fpGetPrinterDriverDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
48 DWORD (WINAPI *fpDeletePrinterDriver)(LPWSTR, LPWSTR, LPWSTR);
49 DWORD (WINAPI *fpAddPrintProcessor)(LPWSTR, LPWSTR, LPWSTR, LPWSTR);
50 DWORD (WINAPI *fpEnumPrintProcessors)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
51 DWORD (WINAPI *fpGetPrintProcessorDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
52 DWORD (WINAPI *fpDeletePrintProcessor)(LPWSTR, LPWSTR, LPWSTR);
53 DWORD (WINAPI *fpEnumPrintProcessorDatatypes)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
54 DWORD (WINAPI *fpStartDocPrinter)(HANDLE, DWORD, LPBYTE);
55 DWORD (WINAPI *fpStartPagePrinter)(HANDLE);
56 DWORD (WINAPI *fpWritePrinter)(HANDLE, LPVOID, DWORD, LPDWORD);
57 DWORD (WINAPI *fpEndPagePrinter)(HANDLE);
58 DWORD (WINAPI *fpAbortPrinter)(HANDLE);
59 DWORD (WINAPI *fpReadPrinter)(HANDLE, LPVOID, DWORD, LPDWORD);
60 DWORD (WINAPI *fpEndDocPrinter)(HANDLE);
61 DWORD (WINAPI *fpAddJob)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
62 DWORD (WINAPI *fpScheduleJob)(HANDLE, DWORD);
63 DWORD (WINAPI *fpGetPrinterData)(HANDLE, LPWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
64 DWORD (WINAPI *fpSetPrinterData)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD);
65 DWORD (WINAPI *fpWaitForPrinterChange)(HANDLE, DWORD);
66 DWORD (WINAPI *fpClosePrinter)(HANDLE);
67 DWORD (WINAPI *fpAddForm)(HANDLE, DWORD, LPBYTE);
68 DWORD (WINAPI *fpDeleteForm)(HANDLE, LPWSTR);
69 DWORD (WINAPI *fpGetForm)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
70 DWORD (WINAPI *fpSetForm)(HANDLE, LPWSTR, DWORD, LPBYTE);
71 DWORD (WINAPI *fpEnumForms)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
72 DWORD (WINAPI *fpEnumMonitors)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
73 DWORD (WINAPI *fpEnumPorts)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
74 DWORD (WINAPI *fpAddPort)(LPWSTR, HWND, LPWSTR);
75 DWORD (WINAPI *fpConfigurePort)(LPWSTR, HWND, LPWSTR);
76 DWORD (WINAPI *fpDeletePort)(LPWSTR, HWND, LPWSTR);
77 HANDLE (WINAPI *fpCreatePrinterIC)(HANDLE, LPDEVMODEW);
78 DWORD (WINAPI *fpPlayGdiScriptOnPrinterIC)(HANDLE, LPBYTE, DWORD, LPBYTE, DWORD, DWORD);
79 DWORD (WINAPI *fpDeletePrinterIC)(HANDLE);
80 DWORD (WINAPI *fpAddPrinterConnection)(LPWSTR);
81 DWORD (WINAPI *fpDeletePrinterConnection)(LPWSTR);
82 DWORD (WINAPI *fpPrinterMessageBox)(HANDLE, DWORD, HWND, LPWSTR, LPWSTR, DWORD);
83 DWORD (WINAPI *fpAddMonitor)(LPWSTR, DWORD, LPBYTE);
84 DWORD (WINAPI *fpDeleteMonitor)(LPWSTR, LPWSTR, LPWSTR);
85 DWORD (WINAPI *fpResetPrinter)(HANDLE, LPPRINTER_DEFAULTSW);
86 DWORD (WINAPI *fpGetPrinterDriverEx)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, DWORD, DWORD, PDWORD, PDWORD);
87 HANDLE (WINAPI *fpFindFirstPrinterChangeNotification)(HANDLE, DWORD, DWORD, LPVOID);
88 DWORD (WINAPI *fpFindClosePrinterChangeNotification)(HANDLE);
89 DWORD (WINAPI *fpAddPortEx)(HANDLE, LPWSTR, DWORD, LPBYTE, LPWSTR);
90 DWORD (WINAPI *fpShutDown)(LPVOID);
91 DWORD (WINAPI *fpRefreshPrinterChangeNotification)(HANDLE, DWORD, PVOID, PVOID);
92 DWORD (WINAPI *fpOpenPrinterEx)(LPWSTR, LPHANDLE, LPPRINTER_DEFAULTSW, LPBYTE, DWORD);
93 HANDLE (WINAPI *fpAddPrinterEx)(LPWSTR, DWORD, LPBYTE, LPBYTE, DWORD);
94 DWORD (WINAPI *fpSetPort)(LPWSTR, LPWSTR, DWORD, LPBYTE);
95 DWORD (WINAPI *fpEnumPrinterData)(HANDLE, DWORD, LPWSTR, DWORD, LPDWORD, LPDWORD, LPBYTE, DWORD, LPDWORD);
96 DWORD (WINAPI *fpDeletePrinterData)(HANDLE, LPWSTR);
97 DWORD (WINAPI *fpClusterSplOpen)(LPCWSTR, LPCWSTR, PHANDLE, LPCWSTR, LPCWSTR);
98 DWORD (WINAPI *fpClusterSplClose)(HANDLE);
99 DWORD (WINAPI *fpClusterSplIsAlive)(HANDLE);
100 DWORD (WINAPI *fpSetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, DWORD, LPBYTE, DWORD);
101 DWORD (WINAPI *fpGetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
102 DWORD (WINAPI *fpEnumPrinterDataEx)(HANDLE, LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD);
103 DWORD (WINAPI *fpEnumPrinterKey)(HANDLE, LPCWSTR, LPWSTR, DWORD, LPDWORD);
104 DWORD (WINAPI *fpDeletePrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR);
105 DWORD (WINAPI *fpDeletePrinterKey)(HANDLE hPrinter, LPCWSTR pKeyName);
106 DWORD (WINAPI *fpSeekPrinter)(HANDLE, LARGE_INTEGER, PLARGE_INTEGER, DWORD, BOOL);
107 DWORD (WINAPI *fpDeletePrinterDriverEx)(LPWSTR, LPWSTR, LPWSTR, DWORD, DWORD);
108 DWORD (WINAPI *fpAddPerMachineConnection)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
109 DWORD (WINAPI *fpDeletePerMachineConnection)(LPCWSTR, LPCWSTR);
110 DWORD (WINAPI *fpEnumPerMachineConnections)(LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD);
111 DWORD (WINAPI *fpXcvData)(HANDLE, LPCWSTR, PBYTE, DWORD, PBYTE, DWORD, PDWORD, PDWORD);
112 DWORD (WINAPI *fpAddPrinterDriverEx)(LPWSTR, DWORD, LPBYTE, DWORD);
113 DWORD (WINAPI *fpSplReadPrinter)(HANDLE, LPBYTE *, DWORD);
114 DWORD (WINAPI *fpDriverUnloadComplete)(LPWSTR);
115 DWORD (WINAPI *fpGetSpoolFileInfo)(HANDLE, LPWSTR *, LPHANDLE, HANDLE, HANDLE);
116 DWORD (WINAPI *fpCommitSpoolData)(HANDLE, DWORD);
117 DWORD (WINAPI *fpCloseSpoolFileHandle)(HANDLE);
118 DWORD (WINAPI *fpFlushPrinter)(HANDLE, LPBYTE, DWORD, LPDWORD, DWORD);
119 DWORD (WINAPI *fpSendRecvBidiData)(HANDLE, LPCWSTR, LPBIDI_REQUEST_CONTAINER, LPBIDI_RESPONSE_CONTAINER *);
120 DWORD (WINAPI *fpAddDriverCatalog)(HANDLE, DWORD, VOID *, DWORD);
121 /* Private Data */
122 HMODULE dll;
123 LPWSTR dllname;
124 LPWSTR name;
125 LPWSTR regroot;
126 DWORD index;
127 } backend_t;
128
129 /* ################################ */
130
131 static backend_t *backend[MAX_BACKEND];
132 static DWORD used_backends = 0;
133
134 static CRITICAL_SECTION backend_cs;
135 static CRITICAL_SECTION_DEBUG backend_cs_debug =
136 {
137 0, 0, &backend_cs,
138 { &backend_cs_debug.ProcessLocksList, &backend_cs_debug.ProcessLocksList },
139 0, 0, { (DWORD_PTR)(__FILE__ ": backend_cs") }
140 };
141 static CRITICAL_SECTION backend_cs = { &backend_cs_debug, -1, 0, 0, 0, 0 };
142
143 /* ################################ */
144
145 static WCHAR localsplW[] = {'l','o','c','a','l','s','p','l','.','d','l','l',0};
146
147 /******************************************************************
148 * strdupW [internal]
149 *
150 * create a copy of a unicode-string
151 *
152 */
153
154 static LPWSTR strdupW(LPCWSTR p)
155 {
156 LPWSTR ret;
157 DWORD len;
158
159 if(!p) return NULL;
160 len = (lstrlenW(p) + 1) * sizeof(WCHAR);
161 ret = heap_alloc(len);
162 memcpy(ret, p, len);
163 return ret;
164 }
165
166 /******************************************************************
167 * backend_unload_all [internal]
168 *
169 * unload all backends
170 */
171 void backend_unload_all(void)
172 {
173 EnterCriticalSection(&backend_cs);
174 while (used_backends > 0) {
175 used_backends--;
176 FreeLibrary(backend[used_backends]->dll);
177 heap_free(backend[used_backends]->dllname);
178 heap_free(backend[used_backends]->name);
179 heap_free(backend[used_backends]->regroot);
180 heap_free(backend[used_backends]);
181 backend[used_backends] = NULL;
182 }
183 LeaveCriticalSection(&backend_cs);
184 }
185
186 /******************************************************************************
187 * backend_load [internal]
188 *
189 * load and init a backend
190 *
191 * PARAMS
192 * name [I] Printprovider to use for the backend. NULL for the local print provider
193 *
194 * RETURNS
195 * Success: PTR to the backend
196 * Failure: NULL
197 *
198 */
199 static backend_t * backend_load(LPWSTR dllname, LPWSTR name, LPWSTR regroot)
200 {
201
202 BOOL (WINAPI *pInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
203 DWORD id;
204 DWORD res;
205
206 TRACE("(%s, %s, %s)\n", debugstr_w(dllname), debugstr_w(name), debugstr_w(regroot));
207
208 EnterCriticalSection(&backend_cs);
209 id = used_backends;
210
211 backend[id] = heap_alloc_zero(sizeof(backend_t));
212 if (!backend[id]) {
213 LeaveCriticalSection(&backend_cs);
214 return NULL;
215 }
216
217 backend[id]->dllname = strdupW(dllname);
218 backend[id]->name = strdupW(name);
219 backend[id]->regroot = strdupW(regroot);
220
221 backend[id]->dll = LoadLibraryW(dllname);
222 if (backend[id]->dll) {
223 pInitializePrintProvidor = (void *) GetProcAddress(backend[id]->dll, "InitializePrintProvidor");
224 if (pInitializePrintProvidor) {
225
226 /* native localspl does not clear unused entries */
227 res = pInitializePrintProvidor((PRINTPROVIDOR *) backend[id], sizeof(PRINTPROVIDOR), regroot);
228 if (res) {
229 used_backends++;
230 backend[id]->index = used_backends;
231 LeaveCriticalSection(&backend_cs);
232 TRACE("--> backend #%d: %p (%s)\n", id, backend[id], debugstr_w(dllname));
233 return backend[id];
234 }
235 }
236 FreeLibrary(backend[id]->dll);
237 }
238 heap_free(backend[id]->dllname);
239 heap_free(backend[id]->name);
240 heap_free(backend[id]->regroot);
241 heap_free(backend[id]);
242 backend[id] = NULL;
243 LeaveCriticalSection(&backend_cs);
244 WARN("failed to init %s: %u\n", debugstr_w(dllname), GetLastError());
245 return NULL;
246 }
247
248 /******************************************************************************
249 * backend_load_all [internal]
250 *
251 * load and init all backends
252 *
253 * RETURNS
254 * Success: TRUE
255 * Failure: FALSE
256 *
257 */
258 BOOL backend_load_all(void)
259 {
260 static BOOL failed = FALSE;
261
262 EnterCriticalSection(&backend_cs);
263
264 /* if we failed before, don't try again */
265 if (!failed && (used_backends == 0)) {
266 backend_load(localsplW, NULL, NULL);
267
268 /* ToDo: parse the registry and load all other backends */
269
270 failed = (used_backends == 0);
271 }
272 LeaveCriticalSection(&backend_cs);
273 TRACE("-> %d\n", !failed);
274 return (!failed);
275 }
276
277 /******************************************************************************
278 * backend_first [internal]
279 *
280 * find the first usable backend
281 *
282 * RETURNS
283 * Success: PTR to the backend
284 * Failure: NULL
285 *
286 */
287 static backend_t * backend_first(LPWSTR name)
288 {
289
290 EnterCriticalSection(&backend_cs);
291 /* Load all backends, when not done yet */
292 if (used_backends || backend_load_all()) {
293
294 /* test for the local system first */
295 if (!name || !name[0]) {
296 LeaveCriticalSection(&backend_cs);
297 return backend[0];
298 }
299 }
300
301 FIXME("server %s not supported in %d backends\n", debugstr_w(name), used_backends);
302 LeaveCriticalSection(&backend_cs);
303 return NULL;
304 }
305
306 /******************************************************************
307 * AddMonitorW (spoolss.@)
308 *
309 * Install a Printmonitor
310 *
311 * PARAMS
312 * pName [I] Servername or NULL (local Computer)
313 * Level [I] Structure-Level (Must be 2)
314 * pMonitors [I] PTR to MONITOR_INFO_2
315 *
316 * RETURNS
317 * Success: TRUE
318 * Failure: FALSE
319 *
320 * NOTES
321 * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32")
322 *
323 */
324 BOOL WINAPI AddMonitorW(LPWSTR pName, DWORD Level, LPBYTE pMonitors)
325 {
326 backend_t * pb;
327 DWORD res = ROUTER_UNKNOWN;
328
329 TRACE("(%s, %d, %p)\n", debugstr_w(pName), Level, pMonitors);
330
331 if (Level != 2) {
332 SetLastError(ERROR_INVALID_LEVEL);
333 return FALSE;
334 }
335
336 pb = backend_first(pName);
337 if (pb && pb->fpAddMonitor)
338 res = pb->fpAddMonitor(pName, Level, pMonitors);
339 else
340 {
341 SetLastError(ERROR_PROC_NOT_FOUND);
342 }
343
344 TRACE("got %u with %u\n", res, GetLastError());
345 return (res == ROUTER_SUCCESS);
346 }
347
348 /******************************************************************
349 * AddPrinterDriverExW (spoolss.@)
350 *
351 * Install a Printer Driver with the Option to upgrade / downgrade the Files
352 *
353 * PARAMS
354 * pName [I] Servername or NULL (local Computer)
355 * level [I] Level for the supplied DRIVER_INFO_*W struct
356 * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter
357 * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files
358 *
359 * RESULTS
360 * Success: TRUE
361 * Failure: FALSE
362 *
363 */
364 BOOL WINAPI AddPrinterDriverExW(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
365 {
366 backend_t * pb;
367 DWORD res = ROUTER_UNKNOWN;
368
369 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags);
370
371 if (!pDriverInfo) {
372 SetLastError(ERROR_INVALID_PARAMETER);
373 return FALSE;
374 }
375
376 pb = backend_first(pName);
377 if (pb && pb->fpAddPrinterDriverEx)
378 res = pb->fpAddPrinterDriverEx(pName, level, pDriverInfo, dwFileCopyFlags);
379 else
380 {
381 SetLastError(ERROR_PROC_NOT_FOUND);
382 }
383
384 TRACE("got %u with %u\n", res, GetLastError());
385 return (res == ROUTER_SUCCESS);
386 }
387
388 /******************************************************************
389 * DeleteMonitorW (spoolss.@)
390 *
391 * Delete a specific Printmonitor from a Printing-Environment
392 *
393 * PARAMS
394 * pName [I] Servername or NULL (local Computer)
395 * pEnvironment [I] Printing-Environment of the Monitor or NULL (Default)
396 * pMonitorName [I] Name of the Monitor, that should be deleted
397 *
398 * RETURNS
399 * Success: TRUE
400 * Failure: FALSE
401 *
402 */
403 BOOL WINAPI DeleteMonitorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName)
404 {
405 backend_t * pb;
406 DWORD res = ROUTER_UNKNOWN;
407
408 TRACE("(%s, %s, %s)\n", debugstr_w(pName), debugstr_w(pEnvironment), debugstr_w(pMonitorName));
409
410 pb = backend_first(pName);
411 if (pb && pb->fpDeleteMonitor)
412 res = pb->fpDeleteMonitor(pName, pEnvironment, pMonitorName);
413 else
414 {
415 SetLastError(ERROR_PROC_NOT_FOUND);
416 }
417
418 TRACE("got %u with %u\n", res, GetLastError());
419 return (res == ROUTER_SUCCESS);
420 }
421
422 /******************************************************************
423 * EnumMonitorsW (spoolss.@)
424 *
425 * Enumerate available Port-Monitors
426 *
427 * PARAMS
428 * pName [I] Servername or NULL (local Computer)
429 * Level [I] Structure-Level
430 * pMonitors [O] PTR to Buffer that receives the Result
431 * cbBuf [I] Size of Buffer at pMonitors
432 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors
433 * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors
434 *
435 * RETURNS
436 * Success: TRUE
437 * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small
438 *
439 */
440 BOOL WINAPI EnumMonitorsW(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf,
441 LPDWORD pcbNeeded, LPDWORD pcReturned)
442 {
443 backend_t * pb;
444 DWORD res = ROUTER_UNKNOWN;
445
446 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors,
447 cbBuf, pcbNeeded, pcReturned);
448
449 if (pcbNeeded) *pcbNeeded = 0;
450 if (pcReturned) *pcReturned = 0;
451
452 pb = backend_first(pName);
453 if (pb && pb->fpEnumMonitors)
454 res = pb->fpEnumMonitors(pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
455 else
456 {
457 SetLastError(ERROR_PROC_NOT_FOUND);
458 }
459
460 TRACE("got %u with %u (%u byte for %u entries)\n\n", res, GetLastError(),
461 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
462
463 return (res == ROUTER_SUCCESS);
464 }
465
466 /******************************************************************
467 * EnumPortsW (spoolss.@)
468 *
469 * Enumerate available Ports
470 *
471 * PARAMS
472 * pName [I] Servername or NULL (local Computer)
473 * Level [I] Structure-Level (1 or 2)
474 * pPorts [O] PTR to Buffer that receives the Result
475 * cbBuf [I] Size of Buffer at pPorts
476 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
477 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
478 *
479 * RETURNS
480 * Success: TRUE
481 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
482 *
483 */
484 BOOL WINAPI EnumPortsW(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf,
485 LPDWORD pcbNeeded, LPDWORD pcReturned)
486 {
487 backend_t * pb;
488 DWORD res = ROUTER_UNKNOWN;
489
490 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts, cbBuf,
491 pcbNeeded, pcReturned);
492
493 if (pcbNeeded) *pcbNeeded = 0;
494 if (pcReturned) *pcReturned = 0;
495
496 pb = backend_first(pName);
497 if (pb && pb->fpEnumPorts)
498 res = pb->fpEnumPorts(pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
499 else
500 {
501 SetLastError(ERROR_PROC_NOT_FOUND);
502 }
503
504 TRACE("got %u with %u (%u byte for %u entries)\n", res, GetLastError(),
505 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
506
507 return (res == ROUTER_SUCCESS);
508 }
509
510 /******************************************************************
511 * GetPrinterDriverDirectoryW (spoolss.@)
512 *
513 * Return the PATH for the Printer-Drivers
514 *
515 * PARAMS
516 * pName [I] Servername or NULL (local Computer)
517 * pEnvironment [I] Printing-Environment or NULL (Default)
518 * Level [I] Structure-Level (must be 1)
519 * pDriverDirectory [O] PTR to Buffer that receives the Result
520 * cbBuf [I] Size of Buffer at pDriverDirectory
521 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used /
522 * required for pDriverDirectory
523 *
524 * RETURNS
525 * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory
526 * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory,
527 * if cbBuf is too small
528 *
529 * Native Values returned in pDriverDirectory on Success:
530 *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86"
531 *| NT(Windows x64): "%winsysdir%\\spool\\DRIVERS\\x64"
532 *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40"
533 *| win9x(Windows 4.0): "%winsysdir%"
534 *
535 * "%winsysdir%" is the Value from GetSystemDirectoryW()
536 *
537 */
538 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
539 DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded)
540 {
541 backend_t * pb;
542 DWORD res = ROUTER_UNKNOWN;
543
544 TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName),
545 debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
546
547 if (pcbNeeded) *pcbNeeded = 0;
548
549 pb = backend_first(pName);
550 if (pb && pb->fpGetPrinterDriverDirectory)
551 res = pb->fpGetPrinterDriverDirectory(pName, pEnvironment, Level,
552 pDriverDirectory, cbBuf, pcbNeeded);
553 else
554 {
555 SetLastError(ERROR_PROC_NOT_FOUND);
556 }
557
558 TRACE("got %u with %u (%u byte)\n",
559 res, GetLastError(), pcbNeeded ? *pcbNeeded : 0);
560
561 return (res == ROUTER_SUCCESS);
562
563 }