[SPOOLSS]
[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 <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "winreg.h"
27
28 #include "wingdi.h"
29 #include "winspool.h"
30 #include "ddk/winsplp.h"
31 #include "spoolss.h"
32
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
36
37 /* ################################ */
38
39 #define MAX_BACKEND 3
40
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;
136
137 /* ################################ */
138
139 static backend_t *backend[MAX_BACKEND];
140 static DWORD used_backends = 0;
141
142 static CRITICAL_SECTION backend_cs;
143 static CRITICAL_SECTION_DEBUG backend_cs_debug =
144 {
145 0, 0, &backend_cs,
146 { &backend_cs_debug.ProcessLocksList, &backend_cs_debug.ProcessLocksList },
147 0, 0, { (DWORD_PTR)(__FILE__ ": backend_cs") }
148 };
149 static CRITICAL_SECTION backend_cs = { &backend_cs_debug, -1, 0, 0, 0, 0 };
150
151 /* ################################ */
152
153 static WCHAR localsplW[] = {'l','o','c','a','l','s','p','l','.','d','l','l',0};
154
155 /******************************************************************
156 * strdupW [internal]
157 *
158 * create a copy of a unicode-string
159 *
160 */
161
162 static LPWSTR strdupW(LPCWSTR p)
163 {
164 LPWSTR ret;
165 DWORD len;
166
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;
172 }
173
174 /******************************************************************
175 * backend_unload_all [internal]
176 *
177 * unload all backends
178 */
179 void backend_unload_all(void)
180 {
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;
190 }
191 LeaveCriticalSection(&backend_cs);
192 }
193
194 /******************************************************************************
195 * backend_load [internal]
196 *
197 * load and init a backend
198 *
199 * PARAMS
200 * name [I] Printprovider to use for the backend. NULL for the local print provider
201 *
202 * RETURNS
203 * Success: PTR to the backend
204 * Failure: NULL
205 *
206 */
207 static backend_t * backend_load(LPWSTR dllname, LPWSTR name, LPWSTR regroot)
208 {
209
210 BOOL (WINAPI *pInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
211 DWORD id;
212 DWORD res;
213
214 TRACE("(%s, %s, %s)\n", debugstr_w(dllname), debugstr_w(name), debugstr_w(regroot));
215
216 EnterCriticalSection(&backend_cs);
217 id = used_backends;
218
219 backend[id] = heap_alloc_zero(sizeof(backend_t));
220 if (!backend[id]) {
221 LeaveCriticalSection(&backend_cs);
222 return NULL;
223 }
224
225 backend[id]->dllname = strdupW(dllname);
226 backend[id]->name = strdupW(name);
227 backend[id]->regroot = strdupW(regroot);
228
229 backend[id]->dll = LoadLibraryW(dllname);
230 if (backend[id]->dll) {
231 pInitializePrintProvidor = (void *) GetProcAddress(backend[id]->dll, "InitializePrintProvidor");
232 if (pInitializePrintProvidor) {
233
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];
242 }
243 }
244 FreeLibrary(backend[id]->dll);
245 }
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;
254 }
255
256 /******************************************************************************
257 * backend_load_all [internal]
258 *
259 * load and init all backends
260 *
261 * RETURNS
262 * Success: TRUE
263 * Failure: FALSE
264 *
265 */
266 BOOL backend_load_all(void)
267 {
268 static BOOL failed = FALSE;
269
270 EnterCriticalSection(&backend_cs);
271
272 /* if we failed before, don't try again */
273 if (!failed && (used_backends == 0)) {
274 backend_load(localsplW, NULL, NULL);
275
276 /* ToDo: parse the registry and load all other backends */
277
278 failed = (used_backends == 0);
279 }
280 LeaveCriticalSection(&backend_cs);
281 TRACE("-> %d\n", !failed);
282 return (!failed);
283 }
284
285 /******************************************************************************
286 * backend_first [internal]
287 *
288 * find the first usable backend
289 *
290 * RETURNS
291 * Success: PTR to the backend
292 * Failure: NULL
293 *
294 */
295 static backend_t * backend_first(LPWSTR name)
296 {
297
298 EnterCriticalSection(&backend_cs);
299 /* Load all backends, when not done yet */
300 if (used_backends || backend_load_all()) {
301
302 /* test for the local system first */
303 if (!name || !name[0]) {
304 LeaveCriticalSection(&backend_cs);
305 return backend[0];
306 }
307 }
308
309 FIXME("server %s not supported in %d backends\n", debugstr_w(name), used_backends);
310 LeaveCriticalSection(&backend_cs);
311 return NULL;
312 }
313
314 /******************************************************************
315 * AddMonitorW (spoolss.@)
316 *
317 * Install a Printmonitor
318 *
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
323 *
324 * RETURNS
325 * Success: TRUE
326 * Failure: FALSE
327 *
328 * NOTES
329 * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32")
330 *
331 */
332 BOOL WINAPI AddMonitorW(LPWSTR pName, DWORD Level, LPBYTE pMonitors)
333 {
334 backend_t * pb;
335 DWORD res = ROUTER_UNKNOWN;
336
337 TRACE("(%s, %d, %p)\n", debugstr_w(pName), Level, pMonitors);
338
339 if (Level != 2) {
340 SetLastError(ERROR_INVALID_LEVEL);
341 return FALSE;
342 }
343
344 pb = backend_first(pName);
345 if (pb && pb->fpAddMonitor)
346 res = pb->fpAddMonitor(pName, Level, pMonitors);
347 else
348 {
349 SetLastError(ERROR_PROC_NOT_FOUND);
350 }
351
352 TRACE("got %u with %u\n", res, GetLastError());
353 return (res == ROUTER_SUCCESS);
354 }
355
356 /******************************************************************
357 * AddPrinterDriverExW (spoolss.@)
358 *
359 * Install a Printer Driver with the Option to upgrade / downgrade the Files
360 *
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
366 *
367 * RESULTS
368 * Success: TRUE
369 * Failure: FALSE
370 *
371 */
372 BOOL WINAPI AddPrinterDriverExW(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
373 {
374 backend_t * pb;
375 DWORD res = ROUTER_UNKNOWN;
376
377 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags);
378
379 if (!pDriverInfo) {
380 SetLastError(ERROR_INVALID_PARAMETER);
381 return FALSE;
382 }
383
384 pb = backend_first(pName);
385 if (pb && pb->fpAddPrinterDriverEx)
386 res = pb->fpAddPrinterDriverEx(pName, level, pDriverInfo, dwFileCopyFlags);
387 else
388 {
389 SetLastError(ERROR_PROC_NOT_FOUND);
390 }
391
392 TRACE("got %u with %u\n", res, GetLastError());
393 return (res == ROUTER_SUCCESS);
394 }
395
396 /******************************************************************
397 * DeleteMonitorW (spoolss.@)
398 *
399 * Delete a specific Printmonitor from a Printing-Environment
400 *
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
405 *
406 * RETURNS
407 * Success: TRUE
408 * Failure: FALSE
409 *
410 */
411 BOOL WINAPI DeleteMonitorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName)
412 {
413 backend_t * pb;
414 DWORD res = ROUTER_UNKNOWN;
415
416 TRACE("(%s, %s, %s)\n", debugstr_w(pName), debugstr_w(pEnvironment), debugstr_w(pMonitorName));
417
418 pb = backend_first(pName);
419 if (pb && pb->fpDeleteMonitor)
420 res = pb->fpDeleteMonitor(pName, pEnvironment, pMonitorName);
421 else
422 {
423 SetLastError(ERROR_PROC_NOT_FOUND);
424 }
425
426 TRACE("got %u with %u\n", res, GetLastError());
427 return (res == ROUTER_SUCCESS);
428 }
429
430 /******************************************************************
431 * EnumMonitorsW (spoolss.@)
432 *
433 * Enumerate available Port-Monitors
434 *
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
442 *
443 * RETURNS
444 * Success: TRUE
445 * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small
446 *
447 */
448 BOOL WINAPI EnumMonitorsW(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf,
449 LPDWORD pcbNeeded, LPDWORD pcReturned)
450 {
451 backend_t * pb;
452 DWORD res = ROUTER_UNKNOWN;
453
454 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors,
455 cbBuf, pcbNeeded, pcReturned);
456
457 if (pcbNeeded) *pcbNeeded = 0;
458 if (pcReturned) *pcReturned = 0;
459
460 pb = backend_first(pName);
461 if (pb && pb->fpEnumMonitors)
462 res = pb->fpEnumMonitors(pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
463 else
464 {
465 SetLastError(ERROR_PROC_NOT_FOUND);
466 }
467
468 TRACE("got %u with %u (%u byte for %u entries)\n\n", res, GetLastError(),
469 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
470
471 return (res == ROUTER_SUCCESS);
472 }
473
474 /******************************************************************
475 * EnumPortsW (spoolss.@)
476 *
477 * Enumerate available Ports
478 *
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
486 *
487 * RETURNS
488 * Success: TRUE
489 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
490 *
491 */
492 BOOL WINAPI EnumPortsW(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf,
493 LPDWORD pcbNeeded, LPDWORD pcReturned)
494 {
495 backend_t * pb;
496 DWORD res = ROUTER_UNKNOWN;
497
498 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts, cbBuf,
499 pcbNeeded, pcReturned);
500
501 if (pcbNeeded) *pcbNeeded = 0;
502 if (pcReturned) *pcReturned = 0;
503
504 pb = backend_first(pName);
505 if (pb && pb->fpEnumPorts)
506 res = pb->fpEnumPorts(pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
507 else
508 {
509 SetLastError(ERROR_PROC_NOT_FOUND);
510 }
511
512 TRACE("got %u with %u (%u byte for %u entries)\n", res, GetLastError(),
513 pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0);
514
515 return (res == ROUTER_SUCCESS);
516 }
517
518 /******************************************************************
519 * GetPrinterDriverDirectoryW (spoolss.@)
520 *
521 * Return the PATH for the Printer-Drivers
522 *
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
531 *
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
536 *
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%"
542 *
543 * "%winsysdir%" is the Value from GetSystemDirectoryW()
544 *
545 */
546 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
547 DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded)
548 {
549 backend_t * pb;
550 DWORD res = ROUTER_UNKNOWN;
551
552 TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName),
553 debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
554
555 if (pcbNeeded) *pcbNeeded = 0;
556
557 pb = backend_first(pName);
558 if (pb && pb->fpGetPrinterDriverDirectory)
559 res = pb->fpGetPrinterDriverDirectory(pName, pEnvironment, Level,
560 pDriverDirectory, cbBuf, pcbNeeded);
561 else
562 {
563 SetLastError(ERROR_PROC_NOT_FOUND);
564 }
565
566 TRACE("got %u with %u (%u byte)\n",
567 res, GetLastError(), pcbNeeded ? *pcbNeeded : 0);
568
569 return (res == ROUTER_SUCCESS);
570
571 }