4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
7 * Copyright 1999, 2000 Huw D M Davies
8 * Copyright 2001 Marcus Meissner
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "wine/port.h"
34 #ifdef HAVE_CUPS_CUPS_H
35 # include <cups/cups.h>
36 # ifndef SONAME_LIBCUPS
37 # define SONAME_LIBCUPS "libcups.so"
41 #define NONAMELESSUNION
42 #define NONAMELESSSTRUCT
43 #include "wine/library.h"
52 #include "wine/windef16.h"
53 #include "wine/unicode.h"
54 #include "wine/debug.h"
58 WINE_DEFAULT_DEBUG_CHANNEL(winspool
);
60 static LPWSTR
*printer_array
;
61 static int nb_printers
;
63 static DWORD (WINAPI
*GDI_CallDeviceCapabilities16
)( LPCSTR lpszDevice
, LPCSTR lpszPort
,
64 WORD fwCapability
, LPSTR lpszOutput
,
66 static INT (WINAPI
*GDI_CallExtDeviceMode16
)( HWND hwnd
, LPDEVMODEA lpdmOutput
,
67 LPSTR lpszDevice
, LPSTR lpszPort
,
68 LPDEVMODEA lpdmInput
, LPSTR lpszProfile
,
71 static char Printers
[] =
72 "System\\CurrentControlSet\\control\\Print\\Printers\\";
73 static char Drivers
[] =
74 "System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
76 static WCHAR DefaultEnvironmentW
[] = {'W','i','n','e',0};
78 static WCHAR Configuration_FileW
[] = {'C','o','n','f','i','g','u','r','a','t',
79 'i','o','n',' ','F','i','l','e',0};
80 static WCHAR DatatypeW
[] = {'D','a','t','a','t','y','p','e',0};
81 static WCHAR Data_FileW
[] = {'D','a','t','a',' ','F','i','l','e',0};
82 static WCHAR Default_DevModeW
[] = {'D','e','f','a','u','l','t',' ','D','e','v',
84 static WCHAR Dependent_FilesW
[] = {'D','e','p','e','n','d','e','n','t',' ','F',
86 static WCHAR DescriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
87 static WCHAR DriverW
[] = {'D','r','i','v','e','r',0};
88 static WCHAR Help_FileW
[] = {'H','e','l','p',' ','F','i','l','e',0};
89 static WCHAR LocationW
[] = {'L','o','c','a','t','i','o','n',0};
90 static WCHAR MonitorW
[] = {'M','o','n','i','t','o','r',0};
91 static WCHAR NameW
[] = {'N','a','m','e',0};
92 static WCHAR ParametersW
[] = {'P','a','r','a','m','e','t','e','r','s',0};
93 static WCHAR PortW
[] = {'P','o','r','t',0};
94 static WCHAR Print_ProcessorW
[] = {'P','r','i','n','t',' ','P','r','o','c','e',
96 static WCHAR Printer_DriverW
[] = {'P','r','i','n','t','e','r',' ','D','r','i',
98 static WCHAR PrinterDriverDataW
[] = {'P','r','i','n','t','e','r','D','r','i',
99 'v','e','r','D','a','t','a',0};
100 static WCHAR Separator_FileW
[] = {'S','e','p','a','r','a','t','o','r',' ','F',
102 static WCHAR Share_NameW
[] = {'S','h','a','r','e',' ','N','a','m','e',0};
103 static WCHAR WinPrintW
[] = {'W','i','n','P','r','i','n','t',0};
105 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
);
106 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
107 DWORD Level
, LPBYTE pDriverInfo
,
108 DWORD cbBuf
, LPDWORD pcbNeeded
,
111 /* RtlCreateUnicodeStringFromAsciiz will return an empty string in the buffer
112 if passed a NULL string. This returns NULLs to the result.
114 static inline PWSTR
asciitounicode( UNICODE_STRING
* usBufferPtr
, LPCSTR src
)
118 RtlCreateUnicodeStringFromAsciiz(usBufferPtr
, src
);
119 return usBufferPtr
->Buffer
;
121 usBufferPtr
->Buffer
= NULL
; /* so that RtlFreeUnicodeString won't barf */
126 WINSPOOL_SetDefaultPrinter(const char *devname
, const char *name
,BOOL force
) {
129 /* If forcing, or no profile string entry for device yet, set the entry
131 * The always change entry if not WINEPS yet is discussable.
134 !GetProfileStringA("windows","device","*",qbuf
,sizeof(qbuf
)) ||
136 !strstr(qbuf
,"WINEPS")
138 char *buf
= HeapAlloc(GetProcessHeap(),0,strlen(name
)+strlen(devname
)+strlen(",WINEPS,LPR:")+1);
140 sprintf(buf
,"%s,WINEPS,LPR:%s",devname
,name
);
141 WriteProfileStringA("windows","device",buf
);
142 HeapFree(GetProcessHeap(),0,buf
);
146 #ifdef HAVE_CUPS_CUPS_H
148 CUPS_LoadPrinters(void) {
149 typeof(cupsGetDests
) *pcupsGetDests
= NULL
;
150 typeof(cupsGetPPD
) *pcupsGetPPD
= NULL
;
152 BOOL hadprinter
= FALSE
;
154 PRINTER_INFO_2A pinfo2a
;
155 void *cupshandle
= NULL
;
158 UNICODE_STRING lpszNameW
;
160 HKEY hkeyPrinters
, hkeyPrinter
;
162 cupshandle
= wine_dlopen(SONAME_LIBCUPS
, RTLD_NOW
, NULL
, 0);
165 TRACE("loaded %s\n", SONAME_LIBCUPS
);
168 p##x = wine_dlsym(cupshandle, #x, NULL,0); \
169 if (!p##x) return FALSE;
172 DYNCUPS(cupsGetDests
);
176 nrofdests
= pcupsGetDests(&dests
);
177 TRACE("Found %d CUPS %s:\n", nrofdests
, (nrofdests
== 1) ? "printer" : "printers");
178 for (i
=0;i
<nrofdests
;i
++) {
179 /* First check that the printer doesn't exist already */
180 pwstrNameW
= asciitounicode(&lpszNameW
, dests
[i
].name
);
181 if (RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) ==
183 if (RegOpenKeyW(hkeyPrinters
, pwstrNameW
, &hkeyPrinter
) ==
185 /* We know this printer already */
186 RegCloseKey(hkeyPrinter
);
187 RegCloseKey(hkeyPrinters
);
188 RtlFreeUnicodeString(&lpszNameW
);
190 if(dests
[i
].is_default
)
191 WINSPOOL_SetDefaultPrinter(dests
[i
].name
, dests
[i
].name
, TRUE
);
192 TRACE("Printer %s already known. Skipping detection\n", dests
[i
].name
);
195 RegCloseKey(hkeyPrinters
);
197 RtlFreeUnicodeString(&lpszNameW
);
199 /* OK, we haven't seen this one yet. Request PPD for it */
200 ppd
= pcupsGetPPD(dests
[i
].name
);
202 WARN("No ppd file for %s.\n",dests
[i
].name
);
203 /* If this was going to be the default printer,
204 * forget it and use another one.
210 memset(&pinfo2a
,0,sizeof(pinfo2a
));
211 pinfo2a
.pPrinterName
= dests
[i
].name
;
212 pinfo2a
.pDatatype
= "RAW";
213 pinfo2a
.pPrintProcessor
= "WinPrint";
214 pinfo2a
.pDriverName
= "PS Driver";
215 pinfo2a
.pComment
= "WINEPS Printer using CUPS";
216 pinfo2a
.pLocation
= "<physical location of printer>";
217 port
= HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(dests
[i
].name
)+1);
218 sprintf(port
,"LPR:%s",dests
[i
].name
);
219 pinfo2a
.pPortName
= port
;
220 pinfo2a
.pParameters
= "<parameters?>";
221 pinfo2a
.pShareName
= "<share name?>";
222 pinfo2a
.pSepFile
= "<sep file?>";
224 devline
=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port
)+1);
225 sprintf(devline
,"WINEPS,%s",port
);
226 WriteProfileStringA("devices",dests
[i
].name
,devline
);
227 HeapFree(GetProcessHeap(),0,devline
);
229 if (!AddPrinterA(NULL
,2,(LPBYTE
)&pinfo2a
)) {
230 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS
)
231 ERR("printer '%s' not added by AddPrinterA (error %ld)\n",dests
[i
].name
,GetLastError());
233 HeapFree(GetProcessHeap(),0,port
);
236 if (dests
[i
].is_default
)
237 WINSPOOL_SetDefaultPrinter(dests
[i
].name
, dests
[i
].name
, TRUE
);
239 wine_dlclose(cupshandle
, NULL
, 0);
245 PRINTCAP_ParseEntry(char *pent
,BOOL isfirst
) {
246 PRINTER_INFO_2A pinfo2a
;
247 char *s
,*name
,*prettyname
,*devname
;
251 while (isspace(*pent
)) pent
++;
252 s
= strchr(pent
,':');
253 if (!s
) return FALSE
;
259 /* Determine whether this is a postscript printer. */
261 /* 1. Check if name or aliases contain trigger phrases like 'ps' */
262 if (strstr(name
,"ps") ||
263 strstr(name
,"pd") || /* postscript double page */
264 strstr(name
,"postscript") ||
265 strstr(name
,"PostScript")
267 TRACE("%s has 'ps' style name, assuming postscript.\n",name
);
270 /* 2. Check if this is a remote printer. These usually are postscript
273 if (strstr(pent
,":rm")) {
275 TRACE("%s is remote, assuming postscript.\n",name
);
277 /* 3. Check if we have an input filter program. If we have one, it
278 * most likely is one capable of converting postscript.
279 * (Could probably check for occurrence of 'gs' or 'ghostscript'
280 * in the if file itself.)
282 if (strstr(pent
,":if=/")) {
284 TRACE("%s has inputfilter program, assuming postscript.\n",name
);
287 /* If it is not a postscript printer, we cannot use it. */
292 /* Get longest name, usually the one at the right for later display. */
293 while ((s
=strchr(prettyname
,'|'))) prettyname
= s
+1;
294 s
=strchr(name
,'|');if (s
) *s
='\0';
296 /* prettyname must fit into the dmDeviceName member of DEVMODE struct,
297 * if it is too long, we use it as comment below. */
298 devname
= prettyname
;
299 if (strlen(devname
)>=CCHDEVICENAME
-1)
301 if (strlen(devname
)>=CCHDEVICENAME
-1)
304 if (isfirst
) /* set first entry as default */
305 WINSPOOL_SetDefaultPrinter(devname
,name
,TRUE
);
307 memset(&pinfo2a
,0,sizeof(pinfo2a
));
308 pinfo2a
.pPrinterName
= devname
;
309 pinfo2a
.pDatatype
= "RAW";
310 pinfo2a
.pPrintProcessor
= "WinPrint";
311 pinfo2a
.pDriverName
= "PS Driver";
312 pinfo2a
.pComment
= "WINEPS Printer using LPR";
313 pinfo2a
.pLocation
= prettyname
;
314 port
= HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(name
)+1);
315 sprintf(port
,"LPR:%s",name
);
316 pinfo2a
.pPortName
= port
;
317 pinfo2a
.pParameters
= "<parameters?>";
318 pinfo2a
.pShareName
= "<share name?>";
319 pinfo2a
.pSepFile
= "<sep file?>";
321 devline
=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port
)+1);
322 sprintf(devline
,"WINEPS,%s",port
);
323 WriteProfileStringA("devices",devname
,devline
);
324 HeapFree(GetProcessHeap(),0,devline
);
326 if (!AddPrinterA(NULL
,2,(LPBYTE
)&pinfo2a
)) {
327 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS
)
328 ERR("%s not added by AddPrinterA (%ld)\n",name
,GetLastError());
330 HeapFree(GetProcessHeap(),0,port
);
335 PRINTCAP_LoadPrinters(void) {
336 BOOL hadprinter
= FALSE
, isfirst
= TRUE
;
340 f
= fopen("/etc/printcap","r");
344 while (fgets(buf
,sizeof(buf
),f
)) {
348 s
=strchr(buf
,'\n'); if (s
) *s
='\0';
349 if ((buf
[0]=='#') || (buf
[0]=='\0'))
353 pent
=HeapReAlloc(GetProcessHeap(),0,pent
,strlen(pent
)+strlen(buf
)+2);
356 pent
=HeapAlloc(GetProcessHeap(),0,strlen(buf
)+1);
360 if (strlen(pent
) && (pent
[strlen(pent
)-1] == '\\'))
361 pent
[strlen(pent
)-1] = '\0';
364 } while (fgets(buf
,sizeof(buf
),f
));
366 hadprinter
|= PRINTCAP_ParseEntry(pent
,isfirst
);
368 if (pent
) HeapFree(GetProcessHeap(),0,pent
);
376 static inline DWORD
set_reg_szW(HKEY hkey
, WCHAR
*keyname
, WCHAR
*value
)
379 return RegSetValueExW(hkey
, keyname
, 0, REG_SZ
, (LPBYTE
)value
,
380 lstrlenW(value
) * sizeof(WCHAR
));
382 return ERROR_FILE_NOT_FOUND
;
386 WINSPOOL_LoadSystemPrinters() {
389 di3a
.cVersion
= 0x400;
390 di3a
.pName
= "PS Driver";
391 di3a
.pEnvironment
= NULL
; /* NULL means auto */
392 di3a
.pDriverPath
= "wineps16";
393 di3a
.pDataFile
= "<datafile?>";
394 di3a
.pConfigFile
= "wineps16";
395 di3a
.pHelpFile
= "<helpfile?>";
396 di3a
.pDependentFiles
= "<dependend files?>";
397 di3a
.pMonitorName
= "<monitor name?>";
398 di3a
.pDefaultDataType
= "RAW";
400 if (!AddPrinterDriverA(NULL
,3,(LPBYTE
)&di3a
)) {
401 ERR("Failed adding PS Driver (%ld)\n",GetLastError());
404 #ifdef HAVE_CUPS_CUPS_H
405 /* If we have any CUPS based printers, skip looking for printcap printers */
406 if (CUPS_LoadPrinters())
410 /* Check for [ppd] section in config file before parsing /etc/printcap */
412 if (RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\ppd",
413 &hkPPD
) == ERROR_SUCCESS
)
416 PRINTCAP_LoadPrinters();
421 /******************************************************************
422 * WINSPOOL_GetOpenedPrinterEntry
423 * Get the first place empty in the opened printer table
425 static HANDLE
WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name
)
429 for (i
= 0; i
< nb_printers
; i
++) if (!printer_array
[i
]) break;
431 if (i
>= nb_printers
)
433 LPWSTR
*new_array
= HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, printer_array
,
434 (nb_printers
+ 16) * sizeof(*new_array
) );
435 if (!new_array
) return 0;
436 printer_array
= new_array
;
440 if ((printer_array
[i
] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name
)+1)*sizeof(WCHAR
) )))
442 strcpyW( printer_array
[i
], name
);
443 return (HANDLE
)(i
+ 1);
448 /******************************************************************
449 * WINSPOOL_GetOpenedPrinter
450 * Get the pointer to the opened printer referred by the handle
452 static LPCWSTR
WINSPOOL_GetOpenedPrinter(HANDLE printerHandle
)
454 int idx
= (int)printerHandle
;
455 if ((idx
<= 0) || (idx
> nb_printers
))
457 SetLastError(ERROR_INVALID_HANDLE
);
460 return printer_array
[idx
- 1];
463 /******************************************************************
464 * WINSPOOL_GetOpenedPrinterRegKey
467 static DWORD
WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter
, HKEY
*phkey
)
469 LPCWSTR name
= WINSPOOL_GetOpenedPrinter(hPrinter
);
473 if(!name
) return ERROR_INVALID_HANDLE
;
475 if((ret
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
)) !=
479 if(RegOpenKeyW(hkeyPrinters
, name
, phkey
) != ERROR_SUCCESS
)
481 ERR("Can't find opened printer %s in registry\n",
483 RegCloseKey(hkeyPrinters
);
484 return ERROR_INVALID_PRINTER_NAME
; /* ? */
486 RegCloseKey(hkeyPrinters
);
487 return ERROR_SUCCESS
;
490 /***********************************************************
493 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
496 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
499 Formname
= (dmA
->dmSize
> off_formname
);
500 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
501 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
504 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
505 dmA
->dmSize
- CCHDEVICENAME
);
507 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
508 off_formname
- CCHDEVICENAME
);
509 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
511 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
512 (off_formname
+ CCHFORMNAME
));
515 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
520 /***********************************************************
522 * Creates an ascii copy of supplied devmode on heap
524 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
529 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
531 if(!dmW
) return NULL
;
532 Formname
= (dmW
->dmSize
> off_formname
);
533 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
534 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
535 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
536 CCHDEVICENAME
, NULL
, NULL
);
538 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
539 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
541 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
542 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
543 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
544 CCHFORMNAME
, NULL
, NULL
);
545 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
546 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
549 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
554 /***********************************************************
556 * Creates a unicode copy of PRINTER_INFO_2A on heap
558 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
560 LPPRINTER_INFO_2W piW
;
561 UNICODE_STRING usBuffer
;
563 if(!piA
) return NULL
;
564 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
565 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
567 piW
->pServerName
= asciitounicode(&usBuffer
,piA
->pServerName
);
568 piW
->pPrinterName
= asciitounicode(&usBuffer
,piA
->pPrinterName
);
569 piW
->pShareName
= asciitounicode(&usBuffer
,piA
->pShareName
);
570 piW
->pPortName
= asciitounicode(&usBuffer
,piA
->pPortName
);
571 piW
->pDriverName
= asciitounicode(&usBuffer
,piA
->pDriverName
);
572 piW
->pComment
= asciitounicode(&usBuffer
,piA
->pComment
);
573 piW
->pLocation
= asciitounicode(&usBuffer
,piA
->pLocation
);
574 piW
->pDevMode
= piA
->pDevMode
? GdiConvertToDevmodeW(piA
->pDevMode
) : NULL
;
575 piW
->pSepFile
= asciitounicode(&usBuffer
,piA
->pSepFile
);
576 piW
->pPrintProcessor
= asciitounicode(&usBuffer
,piA
->pPrintProcessor
);
577 piW
->pDatatype
= asciitounicode(&usBuffer
,piA
->pDatatype
);
578 piW
->pParameters
= asciitounicode(&usBuffer
,piA
->pParameters
);
582 /***********************************************************
583 * FREE_PRINTER_INFO_2W
584 * Free PRINTER_INFO_2W and all strings
586 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
590 HeapFree(heap
,0,piW
->pServerName
);
591 HeapFree(heap
,0,piW
->pPrinterName
);
592 HeapFree(heap
,0,piW
->pShareName
);
593 HeapFree(heap
,0,piW
->pPortName
);
594 HeapFree(heap
,0,piW
->pDriverName
);
595 HeapFree(heap
,0,piW
->pComment
);
596 HeapFree(heap
,0,piW
->pLocation
);
597 HeapFree(heap
,0,piW
->pDevMode
);
598 HeapFree(heap
,0,piW
->pSepFile
);
599 HeapFree(heap
,0,piW
->pPrintProcessor
);
600 HeapFree(heap
,0,piW
->pDatatype
);
601 HeapFree(heap
,0,piW
->pParameters
);
602 HeapFree(heap
,0,piW
);
606 /******************************************************************
607 * DeviceCapabilities [WINSPOOL.@]
608 * DeviceCapabilitiesA [WINSPOOL.@]
611 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
612 LPSTR pOutput
, LPDEVMODEA lpdm
)
616 if (!GDI_CallDeviceCapabilities16
)
618 GDI_CallDeviceCapabilities16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
620 if (!GDI_CallDeviceCapabilities16
) return -1;
622 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
624 /* If DC_PAPERSIZE map POINT16s to POINTs */
625 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
626 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
627 POINT
*pt
= (POINT
*)pOutput
;
629 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
630 for(i
= 0; i
< ret
; i
++, pt
++)
635 HeapFree( GetProcessHeap(), 0, tmp
);
641 /*****************************************************************************
642 * DeviceCapabilitiesW [WINSPOOL.@]
644 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
647 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
648 WORD fwCapability
, LPWSTR pOutput
,
649 const DEVMODEW
*pDevMode
)
651 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
652 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
653 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
656 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
657 fwCapability
== DC_FILEDEPENDENCIES
||
658 fwCapability
== DC_PAPERNAMES
)) {
659 /* These need A -> W translation */
662 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
666 switch(fwCapability
) {
671 case DC_FILEDEPENDENCIES
:
675 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
676 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
678 for(i
= 0; i
< ret
; i
++)
679 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
680 pOutput
+ (i
* size
), size
);
681 HeapFree(GetProcessHeap(), 0, pOutputA
);
683 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
684 (LPSTR
)pOutput
, dmA
);
686 HeapFree(GetProcessHeap(),0,pPortA
);
687 HeapFree(GetProcessHeap(),0,pDeviceA
);
688 HeapFree(GetProcessHeap(),0,dmA
);
692 /******************************************************************
693 * DocumentPropertiesA [WINSPOOL.@]
695 * FIXME: implement DocumentPropertiesA via DocumentPropertiesW, not vice versa
697 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
698 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
699 LPDEVMODEA pDevModeInput
,DWORD fMode
)
701 LPSTR lpName
= pDeviceName
;
704 TRACE("(%p,%p,%s,%p,%p,%ld)\n",
705 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
709 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
711 ERR("no name from hPrinter?\n");
714 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
717 if (!GDI_CallExtDeviceMode16
)
719 GDI_CallExtDeviceMode16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
721 if (!GDI_CallExtDeviceMode16
) {
722 ERR("No CallExtDeviceMode16?\n");
726 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
727 pDevModeInput
, NULL
, fMode
);
730 HeapFree(GetProcessHeap(),0,lpName
);
735 /*****************************************************************************
736 * DocumentPropertiesW (WINSPOOL.@)
738 * FIXME: implement DocumentPropertiesA via DocumentPropertiesW, not vice versa
740 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
742 LPDEVMODEW pDevModeOutput
,
743 LPDEVMODEW pDevModeInput
, DWORD fMode
)
746 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
747 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
748 LPDEVMODEA pDevModeOutputA
= NULL
;
751 TRACE("(%p,%p,%s,%p,%p,%ld)\n",
752 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
755 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
756 if(ret
< 0) return ret
;
757 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
759 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
760 pDevModeInputA
, fMode
);
762 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
763 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
765 if(fMode
== 0 && ret
> 0)
766 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
767 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
768 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
772 /******************************************************************
773 * OpenPrinterA [WINSPOOL.@]
776 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
777 LPPRINTER_DEFAULTSA pDefault
)
779 UNICODE_STRING lpPrinterNameW
;
780 UNICODE_STRING usBuffer
;
781 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
782 PWSTR pwstrPrinterNameW
;
785 pwstrPrinterNameW
= asciitounicode(&lpPrinterNameW
,lpPrinterName
);
788 DefaultW
.pDatatype
= asciitounicode(&usBuffer
,pDefault
->pDatatype
);
789 DefaultW
.pDevMode
= pDefault
->pDevMode
? GdiConvertToDevmodeW(pDefault
->pDevMode
) : NULL
;
790 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
791 pDefaultW
= &DefaultW
;
793 ret
= OpenPrinterW(pwstrPrinterNameW
, phPrinter
, pDefaultW
);
795 RtlFreeUnicodeString(&usBuffer
);
796 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
798 RtlFreeUnicodeString(&lpPrinterNameW
);
802 /******************************************************************
803 * OpenPrinterW [WINSPOOL.@]
806 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
807 LPPRINTER_DEFAULTSW pDefault
)
809 HKEY hkeyPrinters
, hkeyPrinter
;
811 if (!lpPrinterName
) {
812 FIXME("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
813 SetLastError(ERROR_INVALID_PARAMETER
);
817 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
820 /* Check Printer exists */
821 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
823 ERR("Can't create Printers key\n");
824 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
828 if(lpPrinterName
[0] == '\0' || /* explicitly exclude "" */
829 RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
831 TRACE("Can't find printer %s in registry\n",
832 debugstr_w(lpPrinterName
));
833 RegCloseKey(hkeyPrinters
);
834 SetLastError(ERROR_INVALID_PRINTER_NAME
);
837 RegCloseKey(hkeyPrinter
);
838 RegCloseKey(hkeyPrinters
);
840 if(!phPrinter
) /* This seems to be what win95 does anyway */
843 /* Get the unique handle of the printer*/
844 *phPrinter
= WINSPOOL_GetOpenedPrinterEntry( lpPrinterName
);
846 if (pDefault
!= NULL
)
847 FIXME("Not handling pDefault\n");
852 /******************************************************************
853 * AddMonitorA [WINSPOOL.@]
856 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
858 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
859 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
863 /******************************************************************
864 * DeletePrinterDriverA [WINSPOOL.@]
868 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
870 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
871 debugstr_a(pDriverName
));
872 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
877 /******************************************************************
878 * DeleteMonitorA [WINSPOOL.@]
882 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
884 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
885 debugstr_a(pMonitorName
));
886 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
891 /******************************************************************
892 * DeletePortA [WINSPOOL.@]
896 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
898 FIXME("(%s,%p,%s):stub\n",debugstr_a(pName
),hWnd
,
899 debugstr_a(pPortName
));
900 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
904 /******************************************************************************
905 * SetPrinterW [WINSPOOL.@]
915 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
919 /******************************************************************************
920 * WritePrinter [WINSPOOL.@]
930 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
934 /*****************************************************************************
935 * AddFormA [WINSPOOL.@]
937 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
939 FIXME("(%p,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
943 /*****************************************************************************
944 * AddFormW [WINSPOOL.@]
946 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
948 FIXME("(%p,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
952 /*****************************************************************************
953 * AddJobA [WINSPOOL.@]
955 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
956 DWORD cbBuf
, LPDWORD pcbNeeded
)
958 FIXME("(%p,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
963 /*****************************************************************************
964 * AddJobW [WINSPOOL.@]
966 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
969 FIXME("(%p,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
974 /*****************************************************************************
975 * GetPrintProcessorDirectoryA [WINSPOOL.@]
977 BOOL WINAPI
GetPrintProcessorDirectoryA(LPSTR server
, LPSTR environ
,
978 DWORD level
, LPBYTE Info
,
979 DWORD cbBuf
, LPDWORD needed
)
981 FIXME("(%s,%s,%ld,%p,0x%08lx): stub\n", server
, environ
, level
, Info
,
986 /*****************************************************************************
987 * WINSPOOL_OpenDriverReg [internal]
989 * opens the registry for the printer drivers depending on the given input
990 * variable pEnvironment
993 * the opened hkey on success
996 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
)
998 LPSTR lpKey
, p
= NULL
;
1001 (unicode
) ? debugstr_w(pEnvironment
) : debugstr_a(pEnvironment
));
1004 p
= (unicode
) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
) :
1008 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
1010 if(!GetVersionExA( &ver
))
1013 switch (ver
.dwPlatformId
) {
1014 case VER_PLATFORM_WIN32s
:
1015 ERR("win32 style printing used with 16 bits app, try specifying 'win95' Windows version\n");
1018 case VER_PLATFORM_WIN32_NT
:
1019 p
= "Windows NT x86";
1025 TRACE("set environment to %s\n", p
);
1028 lpKey
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1029 strlen(p
) + strlen(Drivers
));
1030 sprintf( lpKey
, Drivers
, p
);
1032 TRACE("%s\n", lpKey
);
1034 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, lpKey
, &retval
) !=
1038 if(pEnvironment
&& unicode
)
1039 HeapFree( GetProcessHeap(), 0, p
);
1040 HeapFree( GetProcessHeap(), 0, lpKey
);
1045 /*****************************************************************************
1046 * AddPrinterW [WINSPOOL.@]
1048 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1050 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
1054 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
1057 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
1060 ERR("pName = %s - unsupported\n", debugstr_w(pName
));
1061 SetLastError(ERROR_INVALID_PARAMETER
);
1065 ERR("Level = %ld, unsupported!\n", Level
);
1066 SetLastError(ERROR_INVALID_LEVEL
);
1069 if (strlenW(pi
->pPrinterName
) >= CCHDEVICENAME
) {
1070 ERR("Printername %s must not exceed length of DEVMODE.dmDeviceName !\n",
1071 debugstr_w(pi
->pPrinterName
)
1073 SetLastError(ERROR_INVALID_LEVEL
);
1077 SetLastError(ERROR_INVALID_PARAMETER
);
1080 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1082 ERR("Can't create Printers key\n");
1085 if(!RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
)) {
1086 if (!RegQueryValueA(hkeyPrinter
,"Attributes",NULL
,NULL
)) {
1087 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
1088 RegCloseKey(hkeyPrinter
);
1089 RegCloseKey(hkeyPrinters
);
1092 RegCloseKey(hkeyPrinter
);
1094 hkeyDrivers
= WINSPOOL_OpenDriverReg( NULL
, TRUE
);
1096 ERR("Can't create Drivers key\n");
1097 RegCloseKey(hkeyPrinters
);
1100 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
1102 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
1103 RegCloseKey(hkeyPrinters
);
1104 RegCloseKey(hkeyDrivers
);
1105 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
1108 RegCloseKey(hkeyDriver
);
1109 RegCloseKey(hkeyDrivers
);
1111 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
1112 FIXME("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
1113 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
1114 RegCloseKey(hkeyPrinters
);
1118 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
1120 FIXME("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
1121 SetLastError(ERROR_INVALID_PRINTER_NAME
);
1122 RegCloseKey(hkeyPrinters
);
1125 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
1126 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
1127 set_reg_szW(hkeyPrinter
, DatatypeW
, pi
->pDatatype
);
1129 /* See if we can load the driver. We may need the devmode structure anyway
1132 * Note that DocumentPropertiesW will briefly try to open the printer we
1133 * just create to find a DEVMODEA struct (it will use the WINEPS default
1134 * one in case it is not there, so we are ok).
1136 size
= DocumentPropertiesW(0, 0, pi
->pPrinterName
, NULL
, NULL
, 0);
1139 FIXME("DocumentPropertiesW on printer '%s' fails\n", debugstr_w(pi
->pPrinterName
));
1140 size
= sizeof(DEVMODEW
);
1146 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
1147 ZeroMemory(dmW
,size
);
1149 if (0>DocumentPropertiesW(0,0,pi
->pPrinterName
,dmW
,NULL
,DM_OUT_BUFFER
))
1151 WARN("DocumentPropertiesW on printer '%s' failed!\n", debugstr_w(pi
->pPrinterName
));
1152 HeapFree(GetProcessHeap(),0,dmW
);
1157 /* set devmode to printer name */
1158 strcpyW(dmW
->dmDeviceName
,pi
->pPrinterName
);
1162 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
1163 and we support these drivers. NT writes DEVMODEW so somehow
1164 we'll need to distinguish between these when we support NT
1168 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
1169 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
,
1170 (LPBYTE
)dmA
, dmA
->dmSize
+ dmA
->dmDriverExtra
);
1171 HeapFree(GetProcessHeap(), 0, dmA
);
1173 HeapFree(GetProcessHeap(), 0, dmW
);
1175 set_reg_szW(hkeyPrinter
, DescriptionW
, pi
->pComment
);
1176 set_reg_szW(hkeyPrinter
, LocationW
, pi
->pLocation
);
1177 set_reg_szW(hkeyPrinter
, NameW
, pi
->pPrinterName
);
1178 set_reg_szW(hkeyPrinter
, ParametersW
, pi
->pParameters
);
1180 set_reg_szW(hkeyPrinter
, PortW
, pi
->pPortName
);
1181 set_reg_szW(hkeyPrinter
, Print_ProcessorW
, pi
->pPrintProcessor
);
1182 set_reg_szW(hkeyPrinter
, Printer_DriverW
, pi
->pDriverName
);
1183 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
1184 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
1185 set_reg_szW(hkeyPrinter
, Separator_FileW
, pi
->pSepFile
);
1186 set_reg_szW(hkeyPrinter
, Share_NameW
, pi
->pShareName
);
1187 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
1188 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
1189 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
1190 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
1191 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
1192 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
1194 RegCloseKey(hkeyPrinter
);
1195 RegCloseKey(hkeyPrinters
);
1196 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
1197 ERR("OpenPrinter failing\n");
1203 /*****************************************************************************
1204 * AddPrinterA [WINSPOOL.@]
1206 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1208 UNICODE_STRING pNameW
;
1210 PRINTER_INFO_2W
*piW
;
1211 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
1214 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
1216 ERR("Level = %ld, unsupported!\n", Level
);
1217 SetLastError(ERROR_INVALID_LEVEL
);
1220 pwstrNameW
= asciitounicode(&pNameW
,pName
);
1221 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
1223 ret
= AddPrinterW(pwstrNameW
, Level
, (LPBYTE
)piW
);
1225 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
1226 RtlFreeUnicodeString(&pNameW
);
1231 /*****************************************************************************
1232 * ClosePrinter [WINSPOOL.@]
1234 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
1236 int i
= (int)hPrinter
;
1238 TRACE("Handle %p\n", hPrinter
);
1240 if ((i
<= 0) || (i
> nb_printers
)) return FALSE
;
1241 HeapFree( GetProcessHeap(), 0, printer_array
[i
- 1] );
1242 printer_array
[i
- 1] = NULL
;
1246 /*****************************************************************************
1247 * DeleteFormA [WINSPOOL.@]
1249 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
1251 FIXME("(%p,%s): stub\n", hPrinter
, pFormName
);
1255 /*****************************************************************************
1256 * DeleteFormW [WINSPOOL.@]
1258 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
1260 FIXME("(%p,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
1264 /*****************************************************************************
1265 * DeletePrinter [WINSPOOL.@]
1267 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
1269 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1272 if(!lpNameW
) return FALSE
;
1273 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1275 ERR("Can't open Printers key\n");
1279 /* This should use a recursive delete see Q142491 or SHDeleteKey */
1280 if(RegDeleteKeyW(hkeyPrinters
, lpNameW
) == ERROR_SUCCESS
) {
1281 SetLastError(ERROR_PRINTER_NOT_FOUND
); /* ?? */
1282 RegCloseKey(hkeyPrinters
);
1286 ClosePrinter(hPrinter
);
1290 /*****************************************************************************
1291 * SetPrinterA [WINSPOOL.@]
1293 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1296 FIXME("(%p,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
1300 /*****************************************************************************
1301 * SetJobA [WINSPOOL.@]
1303 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1304 LPBYTE pJob
, DWORD Command
)
1306 FIXME("(%p,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1311 /*****************************************************************************
1312 * SetJobW [WINSPOOL.@]
1314 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1315 LPBYTE pJob
, DWORD Command
)
1317 FIXME("(%p,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1322 /*****************************************************************************
1323 * EndDocPrinter [WINSPOOL.@]
1325 BOOL WINAPI
EndDocPrinter(HANDLE hPrinter
)
1327 FIXME("(hPrinter=%p): stub\n", hPrinter
);
1331 /*****************************************************************************
1332 * EndPagePrinter [WINSPOOL.@]
1334 BOOL WINAPI
EndPagePrinter(HANDLE hPrinter
)
1336 FIXME("(hPrinter=%p): stub\n", hPrinter
);
1340 /*****************************************************************************
1341 * StartDocPrinterA [WINSPOOL.@]
1343 DWORD WINAPI
StartDocPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pDocInfo
)
1345 FIXME("(hPrinter=%p, Level=0x%lx, pDocInfo=%p): stub\n", hPrinter
, Level
, pDocInfo
);
1349 /*****************************************************************************
1350 * StartDocPrinterW [WINSPOOL.@]
1352 DWORD WINAPI
StartDocPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pDocInfo
)
1354 FIXME("(hPrinter=%p, Level=0x%lx, pDocInfo=%p): stub\n", hPrinter
, Level
, pDocInfo
);
1358 /*****************************************************************************
1359 * StartPagePrinter [WINSPOOL.@]
1361 BOOL WINAPI
StartPagePrinter(HANDLE hPrinter
)
1363 FIXME("(hPrinter=%p): stub\n", hPrinter
);
1367 /*****************************************************************************
1368 * GetFormA [WINSPOOL.@]
1370 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1371 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1373 FIXME("(%p,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1374 Level
,pForm
,cbBuf
,pcbNeeded
);
1378 /*****************************************************************************
1379 * GetFormW [WINSPOOL.@]
1381 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1382 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1384 FIXME("(%p,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1385 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1389 /*****************************************************************************
1390 * SetFormA [WINSPOOL.@]
1392 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1395 FIXME("(%p,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1399 /*****************************************************************************
1400 * SetFormW [WINSPOOL.@]
1402 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1405 FIXME("(%p,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1409 /*****************************************************************************
1410 * ReadPrinter [WINSPOOL.@]
1412 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1413 LPDWORD pNoBytesRead
)
1415 FIXME("(%p,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1419 /*****************************************************************************
1420 * ResetPrinterA [WINSPOOL.@]
1422 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1424 FIXME("(%p, %p): stub\n", hPrinter
, pDefault
);
1428 /*****************************************************************************
1429 * ResetPrinterW [WINSPOOL.@]
1431 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1433 FIXME("(%p, %p): stub\n", hPrinter
, pDefault
);
1437 /*****************************************************************************
1438 * WINSPOOL_GetDWORDFromReg
1440 * Return DWORD associated with ValueName from hkey.
1442 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
1444 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
1447 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
1449 if(ret
!= ERROR_SUCCESS
) {
1450 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
1453 if(type
!= REG_DWORD
) {
1454 ERR("Got type %ld\n", type
);
1460 /*****************************************************************************
1461 * WINSPOOL_GetStringFromReg
1463 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1464 * String is stored either as unicode or ascii.
1465 * Bit of a hack here to get the ValueName if we want ascii.
1467 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1468 DWORD buflen
, DWORD
*needed
,
1471 DWORD sz
= buflen
, type
;
1475 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1477 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1478 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1479 HeapFree(GetProcessHeap(),0,ValueNameA
);
1481 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1482 WARN("Got ret = %ld\n", ret
);
1490 /*****************************************************************************
1491 * WINSPOOL_GetDefaultDevMode
1493 * Get a default DevMode values for wineps.
1497 static void WINSPOOL_GetDefaultDevMode(
1499 DWORD buflen
, DWORD
*needed
,
1504 /* fill default DEVMODE - should be read from ppd... */
1505 ZeroMemory( &dm
, sizeof(dm
) );
1506 strcpy(dm
.dmDeviceName
,"wineps");
1507 dm
.dmSpecVersion
= DM_SPECVERSION
;
1508 dm
.dmDriverVersion
= 1;
1509 dm
.dmSize
= sizeof(DEVMODEA
);
1510 dm
.dmDriverExtra
= 0;
1512 DM_ORIENTATION
| DM_PAPERSIZE
|
1513 DM_PAPERLENGTH
| DM_PAPERWIDTH
|
1516 DM_DEFAULTSOURCE
| DM_PRINTQUALITY
|
1517 DM_YRESOLUTION
| DM_TTOPTION
;
1519 dm
.u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1520 dm
.u1
.s1
.dmPaperSize
= DMPAPER_A4
;
1521 dm
.u1
.s1
.dmPaperLength
= 2970;
1522 dm
.u1
.s1
.dmPaperWidth
= 2100;
1526 dm
.dmDefaultSource
= DMBIN_AUTO
;
1527 dm
.dmPrintQuality
= DMRES_MEDIUM
;
1530 dm
.dmYResolution
= 300; /* 300dpi */
1531 dm
.dmTTOption
= DMTT_BITMAP
;
1534 /* dm.dmLogPixels */
1535 /* dm.dmBitsPerPel */
1536 /* dm.dmPelsWidth */
1537 /* dm.dmPelsHeight */
1538 /* dm.dmDisplayFlags */
1539 /* dm.dmDisplayFrequency */
1540 /* dm.dmICMMethod */
1541 /* dm.dmICMIntent */
1542 /* dm.dmMediaType */
1543 /* dm.dmDitherType */
1544 /* dm.dmReserved1 */
1545 /* dm.dmReserved2 */
1546 /* dm.dmPanningWidth */
1547 /* dm.dmPanningHeight */
1550 if(buflen
>= sizeof(DEVMODEW
)) {
1551 DEVMODEW
*pdmW
= GdiConvertToDevmodeW(&dm
);
1552 memcpy(ptr
, pdmW
, sizeof(DEVMODEW
));
1553 HeapFree(GetProcessHeap(),0,pdmW
);
1555 *needed
= sizeof(DEVMODEW
);
1559 if(buflen
>= sizeof(DEVMODEA
)) {
1560 memcpy(ptr
, &dm
, sizeof(DEVMODEA
));
1562 *needed
= sizeof(DEVMODEA
);
1566 /*****************************************************************************
1567 * WINSPOOL_GetDevModeFromReg
1569 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1570 * DevMode is stored either as unicode or ascii.
1572 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1574 DWORD buflen
, DWORD
*needed
,
1577 DWORD sz
= buflen
, type
;
1580 if (ptr
&& buflen
>=sizeof(DEVMODEA
)) memset(ptr
, 0, sizeof(DEVMODEA
));
1581 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1582 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1583 if (sz
< sizeof(DEVMODEA
))
1585 TRACE("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName
),sz
);
1588 /* ensures that dmSize is not erratically bogus if registry is invalid */
1589 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1590 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1592 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1594 DEVMODEW
*dmW
= GdiConvertToDevmodeW((DEVMODEA
*)ptr
);
1595 memcpy(ptr
, dmW
, sz
);
1596 HeapFree(GetProcessHeap(),0,dmW
);
1603 /*********************************************************************
1604 * WINSPOOL_GetPrinter_2
1606 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1607 * The strings are either stored as unicode or ascii.
1609 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1610 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1613 DWORD size
, left
= cbBuf
;
1614 BOOL space
= (cbBuf
> 0);
1619 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1621 if(space
&& size
<= left
) {
1622 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1629 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1631 if(space
&& size
<= left
) {
1632 pi2
->pShareName
= (LPWSTR
)ptr
;
1639 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1641 if(space
&& size
<= left
) {
1642 pi2
->pPortName
= (LPWSTR
)ptr
;
1649 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1651 if(space
&& size
<= left
) {
1652 pi2
->pDriverName
= (LPWSTR
)ptr
;
1659 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1661 if(space
&& size
<= left
) {
1662 pi2
->pComment
= (LPWSTR
)ptr
;
1669 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1671 if(space
&& size
<= left
) {
1672 pi2
->pLocation
= (LPWSTR
)ptr
;
1679 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1681 if(space
&& size
<= left
) {
1682 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1691 WINSPOOL_GetDefaultDevMode(ptr
, left
, &size
, unicode
);
1692 if(space
&& size
<= left
) {
1693 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1700 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1702 if(space
&& size
<= left
) {
1703 pi2
->pSepFile
= (LPWSTR
)ptr
;
1710 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1712 if(space
&& size
<= left
) {
1713 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1720 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1722 if(space
&& size
<= left
) {
1723 pi2
->pDatatype
= (LPWSTR
)ptr
;
1730 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1732 if(space
&& size
<= left
) {
1733 pi2
->pParameters
= (LPWSTR
)ptr
;
1741 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1742 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1743 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1744 "Default Priority");
1745 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1746 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1749 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1750 memset(pi2
, 0, sizeof(*pi2
));
1755 /*********************************************************************
1756 * WINSPOOL_GetPrinter_4
1758 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1760 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1761 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1764 DWORD size
, left
= cbBuf
;
1765 BOOL space
= (cbBuf
> 0);
1770 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1772 if(space
&& size
<= left
) {
1773 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1781 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1784 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1785 memset(pi4
, 0, sizeof(*pi4
));
1790 /*********************************************************************
1791 * WINSPOOL_GetPrinter_5
1793 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1795 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1796 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1799 DWORD size
, left
= cbBuf
;
1800 BOOL space
= (cbBuf
> 0);
1805 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1807 if(space
&& size
<= left
) {
1808 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1815 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1817 if(space
&& size
<= left
) {
1818 pi5
->pPortName
= (LPWSTR
)ptr
;
1826 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1827 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1829 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1833 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1834 memset(pi5
, 0, sizeof(*pi5
));
1839 /*****************************************************************************
1840 * WINSPOOL_GetPrinter
1842 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1843 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1844 * just a collection of pointers to strings.
1846 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1847 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1850 DWORD size
, needed
= 0;
1852 HKEY hkeyPrinter
, hkeyPrinters
;
1855 TRACE("(%p,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1857 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
1859 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1861 ERR("Can't create Printers key\n");
1864 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
) != ERROR_SUCCESS
)
1866 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
1867 RegCloseKey(hkeyPrinters
);
1868 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1875 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
1877 size
= sizeof(PRINTER_INFO_2W
);
1879 ptr
= pPrinter
+ size
;
1881 memset(pPrinter
, 0, size
);
1886 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
1894 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
1896 size
= sizeof(PRINTER_INFO_4W
);
1898 ptr
= pPrinter
+ size
;
1900 memset(pPrinter
, 0, size
);
1905 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
1914 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
1916 size
= sizeof(PRINTER_INFO_5W
);
1918 ptr
= pPrinter
+ size
;
1920 memset(pPrinter
, 0, size
);
1926 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
1933 FIXME("Unimplemented level %ld\n", Level
);
1934 SetLastError(ERROR_INVALID_LEVEL
);
1935 RegCloseKey(hkeyPrinters
);
1936 RegCloseKey(hkeyPrinter
);
1940 RegCloseKey(hkeyPrinter
);
1941 RegCloseKey(hkeyPrinters
);
1943 TRACE("returning %d needed = %ld\n", ret
, needed
);
1944 if(pcbNeeded
) *pcbNeeded
= needed
;
1946 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1950 /*****************************************************************************
1951 * GetPrinterW [WINSPOOL.@]
1953 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1954 DWORD cbBuf
, LPDWORD pcbNeeded
)
1956 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1960 /*****************************************************************************
1961 * GetPrinterA [WINSPOOL.@]
1963 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1964 DWORD cbBuf
, LPDWORD pcbNeeded
)
1966 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1970 /*****************************************************************************
1971 * WINSPOOL_EnumPrinters
1973 * Implementation of EnumPrintersA|W
1975 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
1976 DWORD dwLevel
, LPBYTE lpbPrinters
,
1977 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1978 LPDWORD lpdwReturned
, BOOL unicode
)
1981 HKEY hkeyPrinters
, hkeyPrinter
;
1982 WCHAR PrinterName
[255];
1983 DWORD needed
= 0, number
= 0;
1984 DWORD used
, i
, left
;
1988 memset(lpbPrinters
, 0, cbBuf
);
1994 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1995 if(dwType
== PRINTER_ENUM_DEFAULT
)
1998 if (dwType
& PRINTER_ENUM_CONNECTIONS
) {
1999 FIXME("We dont handle PRINTER_ENUM_CONNECTIONS\n");
2000 dwType
&= ~PRINTER_ENUM_CONNECTIONS
; /* we dont handle that */
2001 if(!dwType
) return TRUE
;
2004 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
2005 FIXME("dwType = %08lx\n", dwType
);
2006 SetLastError(ERROR_INVALID_FLAGS
);
2010 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
2012 ERR("Can't create Printers key\n");
2016 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2017 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2018 RegCloseKey(hkeyPrinters
);
2019 ERR("Can't query Printers key\n");
2022 TRACE("Found %ld printers\n", number
);
2026 RegCloseKey(hkeyPrinters
);
2028 *lpdwReturned
= number
;
2032 used
= number
* sizeof(PRINTER_INFO_2W
);
2035 used
= number
* sizeof(PRINTER_INFO_4W
);
2038 used
= number
* sizeof(PRINTER_INFO_5W
);
2042 SetLastError(ERROR_INVALID_LEVEL
);
2043 RegCloseKey(hkeyPrinters
);
2046 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
2048 for(i
= 0; i
< number
; i
++) {
2049 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
2051 ERR("Can't enum key number %ld\n", i
);
2052 RegCloseKey(hkeyPrinters
);
2055 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
2056 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
2058 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
2059 RegCloseKey(hkeyPrinters
);
2064 buf
= lpbPrinters
+ used
;
2065 left
= cbBuf
- used
;
2073 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
2074 left
, &needed
, unicode
);
2076 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
2079 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
2080 left
, &needed
, unicode
);
2082 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
2085 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
2086 left
, &needed
, unicode
);
2088 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
2091 ERR("Shouldn't be here!\n");
2092 RegCloseKey(hkeyPrinter
);
2093 RegCloseKey(hkeyPrinters
);
2096 RegCloseKey(hkeyPrinter
);
2098 RegCloseKey(hkeyPrinters
);
2105 memset(lpbPrinters
, 0, cbBuf
);
2106 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2110 *lpdwReturned
= number
;
2111 SetLastError(ERROR_SUCCESS
);
2116 /******************************************************************
2117 * EnumPrintersW [WINSPOOL.@]
2119 * Enumerates the available printers, print servers and print
2120 * providers, depending on the specified flags, name and level.
2124 * If level is set to 1:
2125 * Not implemented yet!
2126 * Returns TRUE with an empty list.
2128 * If level is set to 2:
2129 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2130 * Returns an array of PRINTER_INFO_2 data structures in the
2131 * lpbPrinters buffer. Note that according to MSDN also an
2132 * OpenPrinter should be performed on every remote printer.
2134 * If level is set to 4 (officially WinNT only):
2135 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2136 * Fast: Only the registry is queried to retrieve printer names,
2137 * no connection to the driver is made.
2138 * Returns an array of PRINTER_INFO_4 data structures in the
2139 * lpbPrinters buffer.
2141 * If level is set to 5 (officially WinNT4/Win9x only):
2142 * Fast: Only the registry is queried to retrieve printer names,
2143 * no connection to the driver is made.
2144 * Returns an array of PRINTER_INFO_5 data structures in the
2145 * lpbPrinters buffer.
2147 * If level set to 3 or 6+:
2148 * returns zero (failure!)
2150 * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
2154 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
2155 * - Only levels 2, 4 and 5 are implemented at the moment.
2156 * - 16-bit printer drivers are not enumerated.
2157 * - Returned amount of bytes used/needed does not match the real Windoze
2158 * implementation (as in this implementation, all strings are part
2159 * of the buffer, whereas Win32 keeps them somewhere else)
2160 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
2163 * - In a regular Wine installation, no registry settings for printers
2164 * exist, which makes this function return an empty list.
2166 BOOL WINAPI
EnumPrintersW(
2167 DWORD dwType
, /* [in] Types of print objects to enumerate */
2168 LPWSTR lpszName
, /* [in] name of objects to enumerate */
2169 DWORD dwLevel
, /* [in] type of printer info structure */
2170 LPBYTE lpbPrinters
, /* [out] buffer which receives info */
2171 DWORD cbBuf
, /* [in] max size of buffer in bytes */
2172 LPDWORD lpdwNeeded
, /* [out] pointer to var: # bytes used/needed */
2173 LPDWORD lpdwReturned
/* [out] number of entries returned */
2176 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
2177 lpdwNeeded
, lpdwReturned
, TRUE
);
2180 /******************************************************************
2181 * EnumPrintersA [WINSPOOL.@]
2184 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
2185 DWORD dwLevel
, LPBYTE lpbPrinters
,
2186 DWORD cbBuf
, LPDWORD lpdwNeeded
,
2187 LPDWORD lpdwReturned
)
2190 UNICODE_STRING lpszNameW
;
2193 pwstrNameW
= asciitounicode(&lpszNameW
,lpszName
);
2194 ret
= WINSPOOL_EnumPrinters(dwType
, pwstrNameW
, dwLevel
, lpbPrinters
, cbBuf
,
2195 lpdwNeeded
, lpdwReturned
, FALSE
);
2196 RtlFreeUnicodeString(&lpszNameW
);
2200 /*****************************************************************************
2201 * WINSPOOL_GetDriverInfoFromReg [internal]
2203 * Enters the information from the registry into the DRIVER_INFO struct
2206 * zero if the printer driver does not exist in the registry
2207 * (only if Level > 1) otherwise nonzero
2209 static BOOL
WINSPOOL_GetDriverInfoFromReg(
2212 LPWSTR pEnvironment
,
2214 LPBYTE ptr
, /* DRIVER_INFO */
2215 LPBYTE pDriverStrings
, /* strings buffer */
2216 DWORD cbBuf
, /* size of string buffer */
2217 LPDWORD pcbNeeded
, /* space needed for str. */
2218 BOOL unicode
) /* type of strings */
2219 { DWORD dw
, size
, tmp
, type
;
2221 LPBYTE strPtr
= pDriverStrings
;
2223 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
2224 debugstr_w(DriverName
), debugstr_w(pEnvironment
),
2225 Level
, ptr
, pDriverStrings
, cbBuf
, unicode
);
2228 *pcbNeeded
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
2229 if (*pcbNeeded
<= cbBuf
)
2230 strcpyW((LPWSTR
)strPtr
, DriverName
);
2232 *pcbNeeded
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0,
2234 if(*pcbNeeded
<= cbBuf
)
2235 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, strPtr
, *pcbNeeded
,
2240 ((PDRIVER_INFO_1W
) ptr
)->pName
= (LPWSTR
) strPtr
;
2244 ((PDRIVER_INFO_3W
) ptr
)->pName
= (LPWSTR
) strPtr
;
2245 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2248 if(!DriverName
[0] || RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
) != ERROR_SUCCESS
) {
2249 ERR("Can't find driver '%s' in registry\n", debugstr_w(DriverName
));
2250 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
2255 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
, &size
) !=
2257 WARN("Can't get Version\n");
2259 ((PDRIVER_INFO_3A
) ptr
)->cVersion
= dw
;
2262 pEnvironment
= DefaultEnvironmentW
;
2264 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
2266 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
2269 if(*pcbNeeded
<= cbBuf
) {
2271 strcpyW((LPWSTR
)strPtr
, pEnvironment
);
2273 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, strPtr
, size
,
2276 ((PDRIVER_INFO_3W
) ptr
)->pEnvironment
= (LPWSTR
)strPtr
;
2277 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2280 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, 0, &size
,
2283 if(*pcbNeeded
<= cbBuf
)
2284 WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, size
, &tmp
,
2287 ((PDRIVER_INFO_3W
) ptr
)->pDriverPath
= (LPWSTR
)strPtr
;
2288 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2291 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, 0, &size
,
2294 if(*pcbNeeded
<= cbBuf
)
2295 WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, size
,
2298 ((PDRIVER_INFO_3W
) ptr
)->pDataFile
= (LPWSTR
)strPtr
;
2299 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2302 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
2303 0, &size
, unicode
)) {
2305 if(*pcbNeeded
<= cbBuf
)
2306 WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
2307 size
, &tmp
, unicode
);
2309 ((PDRIVER_INFO_3W
) ptr
)->pConfigFile
= (LPWSTR
)strPtr
;
2310 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2314 RegCloseKey(hkeyDriver
);
2315 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2319 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
, 0, &size
,
2322 if(*pcbNeeded
<= cbBuf
)
2323 WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
,
2324 size
, &tmp
, unicode
);
2326 ((PDRIVER_INFO_3W
) ptr
)->pHelpFile
= (LPWSTR
)strPtr
;
2327 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2330 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
, 0,
2333 if(*pcbNeeded
<= cbBuf
)
2334 WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
,
2335 size
, &tmp
, unicode
);
2337 ((PDRIVER_INFO_3W
) ptr
)->pDependentFiles
= (LPWSTR
)strPtr
;
2338 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2341 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
, 0, &size
,
2344 if(*pcbNeeded
<= cbBuf
)
2345 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
2346 size
, &tmp
, unicode
);
2348 ((PDRIVER_INFO_3W
) ptr
)->pMonitorName
= (LPWSTR
)strPtr
;
2349 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2352 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, strPtr
, 0, &size
,
2355 if(*pcbNeeded
<= cbBuf
)
2356 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
2357 size
, &tmp
, unicode
);
2359 ((PDRIVER_INFO_3W
) ptr
)->pDefaultDataType
= (LPWSTR
)strPtr
;
2360 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2363 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2364 RegCloseKey(hkeyDriver
);
2368 /*****************************************************************************
2369 * WINSPOOL_GetPrinterDriver
2371 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
2372 DWORD Level
, LPBYTE pDriverInfo
,
2373 DWORD cbBuf
, LPDWORD pcbNeeded
,
2377 WCHAR DriverName
[100];
2378 DWORD ret
, type
, size
, needed
= 0;
2380 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDrivers
;
2382 TRACE("(%p,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
2383 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
2385 ZeroMemory(pDriverInfo
, cbBuf
);
2387 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
2389 if(Level
< 1 || Level
> 3) {
2390 SetLastError(ERROR_INVALID_LEVEL
);
2393 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
2395 ERR("Can't create Printers key\n");
2398 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
)
2400 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
2401 RegCloseKey(hkeyPrinters
);
2402 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
2405 size
= sizeof(DriverName
);
2407 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
2408 (LPBYTE
)DriverName
, &size
);
2409 RegCloseKey(hkeyPrinter
);
2410 RegCloseKey(hkeyPrinters
);
2411 if(ret
!= ERROR_SUCCESS
) {
2412 ERR("Can't get DriverName for printer %s\n", debugstr_w(name
));
2416 hkeyDrivers
= WINSPOOL_OpenDriverReg( pEnvironment
, TRUE
);
2418 ERR("Can't create Drivers key\n");
2424 size
= sizeof(DRIVER_INFO_1W
);
2427 size
= sizeof(DRIVER_INFO_2W
);
2430 size
= sizeof(DRIVER_INFO_3W
);
2433 ERR("Invalid level\n");
2438 ptr
= pDriverInfo
+ size
;
2440 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverName
,
2441 pEnvironment
, Level
, pDriverInfo
,
2442 (cbBuf
< size
) ? NULL
: ptr
,
2443 (cbBuf
< size
) ? 0 : cbBuf
- size
,
2444 &needed
, unicode
)) {
2445 RegCloseKey(hkeyDrivers
);
2449 RegCloseKey(hkeyDrivers
);
2451 if(pcbNeeded
) *pcbNeeded
= size
+ needed
;
2452 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2453 if(cbBuf
>= needed
) return TRUE
;
2454 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2458 /*****************************************************************************
2459 * GetPrinterDriverA [WINSPOOL.@]
2461 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
2462 DWORD Level
, LPBYTE pDriverInfo
,
2463 DWORD cbBuf
, LPDWORD pcbNeeded
)
2466 UNICODE_STRING pEnvW
;
2469 pwstrEnvW
= asciitounicode(&pEnvW
, pEnvironment
);
2470 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pwstrEnvW
, Level
, pDriverInfo
,
2471 cbBuf
, pcbNeeded
, FALSE
);
2472 RtlFreeUnicodeString(&pEnvW
);
2475 /*****************************************************************************
2476 * GetPrinterDriverW [WINSPOOL.@]
2478 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
2479 DWORD Level
, LPBYTE pDriverInfo
,
2480 DWORD cbBuf
, LPDWORD pcbNeeded
)
2482 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
2483 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
2486 /*****************************************************************************
2487 * GetPrinterDriverDirectoryW [WINSPOOL.@]
2489 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
2490 DWORD Level
, LPBYTE pDriverDirectory
,
2491 DWORD cbBuf
, LPDWORD pcbNeeded
)
2495 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", debugstr_w(pName
),
2496 debugstr_w(pEnvironment
), Level
, pDriverDirectory
, cbBuf
, pcbNeeded
);
2498 FIXME("pName = `%s' - unsupported\n", debugstr_w(pName
));
2499 SetLastError(ERROR_INVALID_PARAMETER
);
2502 if(pEnvironment
!= NULL
) {
2503 FIXME("pEnvironment = `%s' - unsupported\n", debugstr_w(pEnvironment
));
2504 SetLastError(ERROR_INVALID_ENVIRONMENT
);
2507 if(Level
!= 1) /* win95 ignores this so we just carry on */
2508 WARN("Level = %ld - assuming 1\n", Level
);
2510 /* FIXME should read from registry */
2511 needed
= GetSystemDirectoryW( (LPWSTR
)pDriverDirectory
, cbBuf
/sizeof(WCHAR
));
2512 /* GetSystemDirectoryW returns number of TCHAR without '\0'
2516 needed
*=sizeof(WCHAR
);
2519 *pcbNeeded
= needed
;
2520 TRACE("required <%08lx>\n", *pcbNeeded
);
2521 if(needed
> cbBuf
) {
2522 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2529 /*****************************************************************************
2530 * GetPrinterDriverDirectoryA [WINSPOOL.@]
2532 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
2533 DWORD Level
, LPBYTE pDriverDirectory
,
2534 DWORD cbBuf
, LPDWORD pcbNeeded
)
2536 UNICODE_STRING nameW
, environmentW
;
2539 INT len
= cbBuf
* sizeof(WCHAR
)/sizeof(CHAR
);
2540 WCHAR
*driverDirectoryW
= NULL
;
2542 if (len
) driverDirectoryW
= HeapAlloc( GetProcessHeap(), 0, len
);
2544 if(pName
) RtlCreateUnicodeStringFromAsciiz(&nameW
, pName
);
2545 else nameW
.Buffer
= NULL
;
2546 if(pEnvironment
) RtlCreateUnicodeStringFromAsciiz(&environmentW
, pEnvironment
);
2547 else environmentW
.Buffer
= NULL
;
2549 ret
= GetPrinterDriverDirectoryW( nameW
.Buffer
, environmentW
.Buffer
, Level
,
2550 (LPBYTE
)driverDirectoryW
, len
, &pcbNeededW
);
2553 needed
= 1 + WideCharToMultiByte( CP_ACP
, 0, driverDirectoryW
, -1,
2554 pDriverDirectory
, cbBuf
, NULL
, NULL
);
2556 *pcbNeeded
= needed
;
2557 ret
= (needed
<= cbBuf
) ? TRUE
: FALSE
;
2559 if(pcbNeeded
) *pcbNeeded
= pcbNeededW
* sizeof(CHAR
)/sizeof(WCHAR
);
2561 TRACE("provided<%ld> required <%ld>\n", cbBuf
, *pcbNeeded
);
2563 if(driverDirectoryW
)
2564 HeapFree( GetProcessHeap(), 0, driverDirectoryW
);
2565 RtlFreeUnicodeString(&environmentW
);
2566 RtlFreeUnicodeString(&nameW
);
2571 /*****************************************************************************
2572 * AddPrinterDriverA [WINSPOOL.@]
2574 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
2577 HKEY hkeyDrivers
, hkeyName
;
2579 TRACE("(%s,%ld,%p)\n",debugstr_a(pName
),level
,pDriverInfo
);
2581 if(level
!= 2 && level
!= 3) {
2582 SetLastError(ERROR_INVALID_LEVEL
);
2586 FIXME("pName= %s - unsupported\n", debugstr_a(pName
));
2587 SetLastError(ERROR_INVALID_PARAMETER
);
2591 WARN("pDriverInfo == NULL\n");
2592 SetLastError(ERROR_INVALID_PARAMETER
);
2597 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
2599 memset(&di3
, 0, sizeof(di3
));
2600 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
2603 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
2605 SetLastError(ERROR_INVALID_PARAMETER
);
2608 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
2609 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
2610 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
2611 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
2613 hkeyDrivers
= WINSPOOL_OpenDriverReg(di3
.pEnvironment
, FALSE
);
2616 ERR("Can't create Drivers key\n");
2620 if(level
== 2) { /* apparently can't overwrite with level2 */
2621 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2622 RegCloseKey(hkeyName
);
2623 RegCloseKey(hkeyDrivers
);
2624 WARN("Trying to create existing printer driver %s\n", debugstr_a(di3
.pName
));
2625 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2629 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2630 RegCloseKey(hkeyDrivers
);
2631 ERR("Can't create Name key\n");
2634 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2636 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2637 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2638 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2640 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2641 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2642 di3
.pDependentFiles
, 0);
2643 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2644 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2645 RegCloseKey(hkeyName
);
2646 RegCloseKey(hkeyDrivers
);
2650 /*****************************************************************************
2651 * AddPrinterDriverW [WINSPOOL.@]
2653 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2656 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2662 /*****************************************************************************
2663 * PrinterProperties [WINSPOOL.@]
2665 * Displays a dialog to set the properties of the printer.
2668 * nonzero on success or zero on failure
2671 * implemented as stub only
2673 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* [in] handle to parent window */
2674 HANDLE hPrinter
/* [in] handle to printer object */
2676 FIXME("(%p,%p): stub\n", hWnd
, hPrinter
);
2677 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2681 /*****************************************************************************
2682 * EnumJobsA [WINSPOOL.@]
2685 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2686 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2689 FIXME("(%p,first=%ld,no=%ld,level=%ld,job=%p,cb=%ld,%p,%p), stub!\n",
2690 hPrinter
, FirstJob
, NoJobs
, Level
, pJob
, cbBuf
, pcbNeeded
, pcReturned
2692 if(pcbNeeded
) *pcbNeeded
= 0;
2693 if(pcReturned
) *pcReturned
= 0;
2698 /*****************************************************************************
2699 * EnumJobsW [WINSPOOL.@]
2702 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2703 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2706 FIXME("(%p,first=%ld,no=%ld,level=%ld,job=%p,cb=%ld,%p,%p), stub!\n",
2707 hPrinter
, FirstJob
, NoJobs
, Level
, pJob
, cbBuf
, pcbNeeded
, pcReturned
2709 if(pcbNeeded
) *pcbNeeded
= 0;
2710 if(pcReturned
) *pcReturned
= 0;
2714 /*****************************************************************************
2715 * WINSPOOL_EnumPrinterDrivers [internal]
2717 * Delivers information about all printer drivers installed on the
2718 * localhost or a given server
2721 * nonzero on success or zero on failure. If the buffer for the returned
2722 * information is too small the function will return an error
2725 * - only implemented for localhost, foreign hosts will return an error
2727 static BOOL
WINSPOOL_EnumPrinterDrivers(LPWSTR pName
, LPWSTR pEnvironment
,
2728 DWORD Level
, LPBYTE pDriverInfo
,
2729 DWORD cbBuf
, LPDWORD pcbNeeded
,
2730 LPDWORD pcReturned
, BOOL unicode
)
2733 DWORD i
, needed
, number
= 0, size
= 0;
2734 WCHAR DriverNameW
[255];
2737 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2738 debugstr_w(pName
), debugstr_w(pEnvironment
),
2739 Level
, pDriverInfo
, cbBuf
, unicode
);
2741 /* check for local drivers */
2743 ERR("remote drivers unsupported! Current remote host is %s\n",
2748 /* check input parameter */
2749 if((Level
< 1) || (Level
> 3)) {
2750 ERR("unsupported level %ld \n", Level
);
2754 /* initialize return values */
2756 memset( pDriverInfo
, 0, cbBuf
);
2760 hkeyDrivers
= WINSPOOL_OpenDriverReg(pEnvironment
, TRUE
);
2762 ERR("Can't open Drivers key\n");
2766 if(RegQueryInfoKeyA(hkeyDrivers
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2767 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2768 RegCloseKey(hkeyDrivers
);
2769 ERR("Can't query Drivers key\n");
2772 TRACE("Found %ld Drivers\n", number
);
2774 /* get size of single struct
2775 * unicode and ascii structure have the same size
2779 size
= sizeof(DRIVER_INFO_1A
);
2782 size
= sizeof(DRIVER_INFO_2A
);
2785 size
= sizeof(DRIVER_INFO_3A
);
2789 /* calculate required buffer size */
2790 *pcbNeeded
= size
* number
;
2792 for( i
= 0, ptr
= (pDriverInfo
&& (cbBuf
>= size
)) ? pDriverInfo
: NULL
;
2794 i
++, ptr
= (ptr
&& (cbBuf
>= size
* i
)) ? ptr
+ size
: NULL
) {
2795 if(RegEnumKeyW(hkeyDrivers
, i
, DriverNameW
, sizeof(DriverNameW
))
2797 ERR("Can't enum key number %ld\n", i
);
2798 RegCloseKey(hkeyDrivers
);
2801 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverNameW
,
2802 pEnvironment
, Level
, ptr
,
2803 (cbBuf
< *pcbNeeded
) ? NULL
: pDriverInfo
+ *pcbNeeded
,
2804 (cbBuf
< *pcbNeeded
) ? 0 : cbBuf
- *pcbNeeded
,
2805 &needed
, unicode
)) {
2806 RegCloseKey(hkeyDrivers
);
2809 (*pcbNeeded
) += needed
;
2812 RegCloseKey(hkeyDrivers
);
2814 if(cbBuf
< *pcbNeeded
){
2815 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2822 /*****************************************************************************
2823 * EnumPrinterDriversW [WINSPOOL.@]
2825 * see function EnumPrinterDrivers for RETURNS, BUGS
2827 BOOL WINAPI
EnumPrinterDriversW(LPWSTR pName
, LPWSTR pEnvironment
, DWORD Level
,
2828 LPBYTE pDriverInfo
, DWORD cbBuf
,
2829 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2831 return WINSPOOL_EnumPrinterDrivers(pName
, pEnvironment
, Level
, pDriverInfo
,
2832 cbBuf
, pcbNeeded
, pcReturned
, TRUE
);
2835 /*****************************************************************************
2836 * EnumPrinterDriversA [WINSPOOL.@]
2838 * see function EnumPrinterDrivers for RETURNS, BUGS
2840 BOOL WINAPI
EnumPrinterDriversA(LPSTR pName
, LPSTR pEnvironment
, DWORD Level
,
2841 LPBYTE pDriverInfo
, DWORD cbBuf
,
2842 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2844 UNICODE_STRING pNameW
, pEnvironmentW
;
2845 PWSTR pwstrNameW
, pwstrEnvironmentW
;
2847 pwstrNameW
= asciitounicode(&pNameW
, pName
);
2848 pwstrEnvironmentW
= asciitounicode(&pEnvironmentW
, pEnvironment
);
2850 ret
= WINSPOOL_EnumPrinterDrivers(pwstrNameW
, pwstrEnvironmentW
,
2851 Level
, pDriverInfo
, cbBuf
, pcbNeeded
,
2853 RtlFreeUnicodeString(&pNameW
);
2854 RtlFreeUnicodeString(&pEnvironmentW
);
2859 static CHAR PortMonitor
[] = "Wine Port Monitor";
2860 static CHAR PortDescription
[] = "Wine Port";
2862 /******************************************************************************
2863 * EnumPortsA (WINSPOOL.@)
2865 BOOL WINAPI
EnumPortsA(LPSTR name
,DWORD level
,LPBYTE buffer
,DWORD bufsize
,
2866 LPDWORD bufneeded
,LPDWORD bufreturned
)
2869 DWORD info_size
, ofs
, i
, printer_count
, serial_count
, count
, n
, r
;
2870 const LPCSTR szSerialPortKey
= "Software\\Wine\\Wine\\Config\\serialports";
2871 const LPCSTR szPrinterPortKey
= "Software\\Wine\\Wine\\Config\\spooler";
2872 HKEY hkey_serial
, hkey_printer
;
2874 TRACE("(%s,%ld,%p,%ld,%p,%p)\n",
2875 name
,level
,buffer
,bufsize
,bufneeded
,bufreturned
);
2880 info_size
= sizeof (PORT_INFO_1A
);
2883 info_size
= sizeof (PORT_INFO_2A
);
2886 SetLastError(ERROR_INVALID_LEVEL
);
2890 /* see how many exist */
2896 r
= RegOpenKeyA( HKEY_LOCAL_MACHINE
, szSerialPortKey
, &hkey_serial
);
2897 if (r
== ERROR_SUCCESS
)
2899 RegQueryInfoKeyA ( hkey_serial
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
2900 &serial_count
, NULL
, NULL
, NULL
, NULL
);
2903 r
= RegOpenKeyA( HKEY_LOCAL_MACHINE
, szPrinterPortKey
, &hkey_printer
);
2904 if ( r
== ERROR_SUCCESS
)
2906 RegQueryInfoKeyA( hkey_printer
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
2907 &printer_count
, NULL
, NULL
, NULL
, NULL
);
2909 count
= serial_count
+ printer_count
;
2911 /* then fill in the structure info structure once
2912 we know the offset to the first string */
2914 memset( buffer
, 0, bufsize
);
2916 ofs
= info_size
*count
;
2917 for ( i
=0; i
<count
; i
++)
2919 DWORD vallen
= sizeof(portname
) - 1;
2921 /* get the serial port values, then the printer values */
2922 if ( i
< serial_count
)
2923 r
= RegEnumValueA( hkey_serial
, i
,
2924 portname
, &vallen
, NULL
, NULL
, NULL
, 0 );
2926 r
= RegEnumValueA( hkey_printer
, i
-serial_count
,
2927 portname
, &vallen
, NULL
, NULL
, NULL
, 0 );
2932 /* add a colon if necessary, and make it upper case */
2933 CharUpperBuffA(portname
,vallen
);
2934 if (strcasecmp(portname
,"nul")!=0)
2935 if (vallen
&& (portname
[vallen
-1] != ':') )
2936 lstrcatA(portname
,":");
2938 /* add the port info structure if we can fit it */
2939 if ( info_size
*(n
+1) < bufsize
)
2943 PORT_INFO_1A
*info
= (PORT_INFO_1A
*) &buffer
[info_size
*n
];
2944 info
->pName
= (LPSTR
) &buffer
[ofs
];
2946 else if ( level
== 2)
2948 PORT_INFO_2A
*info
= (PORT_INFO_2A
*) &buffer
[info_size
*n
];
2949 info
->pPortName
= (LPSTR
) &buffer
[ofs
];
2950 /* FIXME: fill in more stuff here */
2951 info
->pMonitorName
= PortMonitor
;
2952 info
->pDescription
= PortDescription
;
2953 info
->fPortType
= PORT_TYPE_WRITE
|PORT_TYPE_READ
;
2956 /* add the name of the port if we can fit it */
2957 if ( ofs
< bufsize
)
2958 lstrcpynA(&buffer
[ofs
],portname
,bufsize
- ofs
);
2961 ofs
+= lstrlenA(portname
)+1;
2965 RegCloseKey(hkey_serial
);
2966 RegCloseKey(hkey_printer
);
2972 *bufreturned
= count
;
2977 /******************************************************************************
2978 * GetDefaultPrinterA (WINSPOOL.@)
2980 * Based on PRINTDLG_GetDefaultPrinterName in dlls/commdlg/printdlg.c
2982 BOOL WINAPI
GetDefaultPrinterA(LPSTR name
, LPDWORD namesize
)
2988 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
2992 if (!GetProfileStringA ("windows", "device", "", name
, *namesize
))
2994 SetLastError (ERROR_FILE_NOT_FOUND
);
2998 if ((ptr
= strchr (name
, ',')) == NULL
)
3000 SetLastError (ERROR_FILE_NOT_FOUND
);
3005 *namesize
= strlen (name
) + 1;
3010 /******************************************************************************
3011 * GetDefaultPrinterW (WINSPOOL.@)
3013 BOOL WINAPI
GetDefaultPrinterW(LPWSTR name
, LPDWORD namesize
)
3020 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
3024 buf
= HeapAlloc (GetProcessHeap (), 0, *namesize
);
3025 ret
= GetDefaultPrinterA (buf
, namesize
);
3028 DWORD len
= MultiByteToWideChar (CP_ACP
, 0, buf
, -1, name
, *namesize
);
3031 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
3034 else *namesize
= len
;
3037 HeapFree (GetProcessHeap (), 0, buf
);
3042 /******************************************************************************
3043 * SetPrinterDataExA (WINSPOOL.@)
3045 DWORD WINAPI
SetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
3046 LPSTR pValueName
, DWORD Type
,
3047 LPBYTE pData
, DWORD cbData
)
3049 HKEY hkeyPrinter
, hkeySubkey
;
3052 TRACE("(%p, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_a(pKeyName
),
3053 debugstr_a(pValueName
), Type
, pData
, cbData
);
3055 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
3059 if((ret
= RegCreateKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
3061 ERR("Can't create subkey %s\n", debugstr_a(pKeyName
));
3062 RegCloseKey(hkeyPrinter
);
3065 ret
= RegSetValueExA(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
3066 RegCloseKey(hkeySubkey
);
3067 RegCloseKey(hkeyPrinter
);
3071 /******************************************************************************
3072 * SetPrinterDataExW (WINSPOOL.@)
3074 DWORD WINAPI
SetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
3075 LPWSTR pValueName
, DWORD Type
,
3076 LPBYTE pData
, DWORD cbData
)
3078 HKEY hkeyPrinter
, hkeySubkey
;
3081 TRACE("(%p, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_w(pKeyName
),
3082 debugstr_w(pValueName
), Type
, pData
, cbData
);
3084 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
3088 if((ret
= RegCreateKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
3090 ERR("Can't create subkey %s\n", debugstr_w(pKeyName
));
3091 RegCloseKey(hkeyPrinter
);
3094 ret
= RegSetValueExW(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
3095 RegCloseKey(hkeySubkey
);
3096 RegCloseKey(hkeyPrinter
);
3100 /******************************************************************************
3101 * SetPrinterDataA (WINSPOOL.@)
3103 DWORD WINAPI
SetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, DWORD Type
,
3104 LPBYTE pData
, DWORD cbData
)
3106 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
,
3110 /******************************************************************************
3111 * SetPrinterDataW (WINSPOOL.@)
3113 DWORD WINAPI
SetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, DWORD Type
,
3114 LPBYTE pData
, DWORD cbData
)
3116 return SetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, Type
,
3120 /******************************************************************************
3121 * GetPrinterDataExA (WINSPOOL.@)
3123 DWORD WINAPI
GetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
3124 LPSTR pValueName
, LPDWORD pType
,
3125 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3127 HKEY hkeyPrinter
, hkeySubkey
;
3130 TRACE("(%p, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
3131 debugstr_a(pKeyName
), debugstr_a(pValueName
), pType
, pData
, nSize
,
3134 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
3138 if((ret
= RegOpenKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
3140 WARN("Can't open subkey %s\n", debugstr_a(pKeyName
));
3141 RegCloseKey(hkeyPrinter
);
3145 ret
= RegQueryValueExA(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
3146 RegCloseKey(hkeySubkey
);
3147 RegCloseKey(hkeyPrinter
);
3151 /******************************************************************************
3152 * GetPrinterDataExW (WINSPOOL.@)
3154 DWORD WINAPI
GetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
3155 LPWSTR pValueName
, LPDWORD pType
,
3156 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3158 HKEY hkeyPrinter
, hkeySubkey
;
3161 TRACE("(%p, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
3162 debugstr_w(pKeyName
), debugstr_w(pValueName
), pType
, pData
, nSize
,
3165 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
3169 if((ret
= RegOpenKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
3171 WARN("Can't open subkey %s\n", debugstr_w(pKeyName
));
3172 RegCloseKey(hkeyPrinter
);
3176 ret
= RegQueryValueExW(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
3177 RegCloseKey(hkeySubkey
);
3178 RegCloseKey(hkeyPrinter
);
3182 /******************************************************************************
3183 * GetPrinterDataA (WINSPOOL.@)
3185 DWORD WINAPI
GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
,
3186 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3188 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
,
3189 pData
, nSize
, pcbNeeded
);
3192 /******************************************************************************
3193 * GetPrinterDataW (WINSPOOL.@)
3195 DWORD WINAPI
GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
,
3196 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3198 return GetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, pType
,
3199 pData
, nSize
, pcbNeeded
);
3202 /*******************************************************************************
3203 * EnumPrinterDataExW [WINSPOOL.@]
3205 DWORD WINAPI
EnumPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
,
3206 LPBYTE pEnumValues
, DWORD cbEnumValues
,
3207 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
3209 HKEY hkPrinter
, hkSubKey
;
3210 DWORD r
, ret
, dwIndex
, cValues
, cbMaxValueNameLen
,
3211 cbValueNameLen
, cbMaxValueLen
, cbValueLen
,
3216 PPRINTER_ENUM_VALUESW ppev
;
3218 TRACE ("%p %s\n", hPrinter
, debugstr_w (pKeyName
));
3220 if (pKeyName
== NULL
|| *pKeyName
== 0)
3221 return ERROR_INVALID_PARAMETER
;
3223 ret
= WINSPOOL_GetOpenedPrinterRegKey (hPrinter
, &hkPrinter
);
3224 if (ret
!= ERROR_SUCCESS
)
3226 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%p) returned %li\n",
3231 ret
= RegOpenKeyExW (hkPrinter
, pKeyName
, 0, KEY_READ
, &hkSubKey
);
3232 if (ret
!= ERROR_SUCCESS
)
3234 r
= RegCloseKey (hkPrinter
);
3235 if (r
!= ERROR_SUCCESS
)
3236 WARN ("RegCloseKey returned %li\n", r
);
3237 TRACE ("RegOpenKeyExW (%p, %s) returned %li\n", hPrinter
,
3238 debugstr_w (pKeyName
), ret
);
3242 ret
= RegCloseKey (hkPrinter
);
3243 if (ret
!= ERROR_SUCCESS
)
3245 ERR ("RegCloseKey returned %li\n", ret
);
3246 r
= RegCloseKey (hkSubKey
);
3247 if (r
!= ERROR_SUCCESS
)
3248 WARN ("RegCloseKey returned %li\n", r
);
3252 ret
= RegQueryInfoKeyW (hkSubKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
3253 &cValues
, &cbMaxValueNameLen
, &cbMaxValueLen
, NULL
, NULL
);
3254 if (ret
!= ERROR_SUCCESS
)
3256 r
= RegCloseKey (hkSubKey
);
3257 if (r
!= ERROR_SUCCESS
)
3258 WARN ("RegCloseKey returned %li\n", r
);
3259 TRACE ("RegQueryInfoKeyW (%p) returned %li\n", hkSubKey
, ret
);
3263 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
3264 "cbMaxValueLen = %li\n", cValues
, cbMaxValueNameLen
, cbMaxValueLen
);
3266 if (cValues
== 0) /* empty key */
3268 r
= RegCloseKey (hkSubKey
);
3269 if (r
!= ERROR_SUCCESS
)
3270 WARN ("RegCloseKey returned %li\n", r
);
3271 *pcbEnumValues
= *pnEnumValues
= 0;
3272 return ERROR_SUCCESS
;
3275 ++cbMaxValueNameLen
; /* allow for trailing '\0' */
3277 hHeap
= GetProcessHeap ();
3280 ERR ("GetProcessHeap failed\n");
3281 r
= RegCloseKey (hkSubKey
);
3282 if (r
!= ERROR_SUCCESS
)
3283 WARN ("RegCloseKey returned %li\n", r
);
3284 return ERROR_OUTOFMEMORY
;
3287 lpValueName
= HeapAlloc (hHeap
, 0, cbMaxValueNameLen
* sizeof (WCHAR
));
3288 if (lpValueName
== NULL
)
3290 ERR ("Failed to allocate %li bytes from process heap\n",
3291 cbMaxValueNameLen
* sizeof (WCHAR
));
3292 r
= RegCloseKey (hkSubKey
);
3293 if (r
!= ERROR_SUCCESS
)
3294 WARN ("RegCloseKey returned %li\n", r
);
3295 return ERROR_OUTOFMEMORY
;
3298 lpValue
= HeapAlloc (hHeap
, 0, cbMaxValueLen
);
3299 if (lpValue
== NULL
)
3301 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen
);
3302 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3303 WARN ("HeapFree failed with code %li\n", GetLastError ());
3304 r
= RegCloseKey (hkSubKey
);
3305 if (r
!= ERROR_SUCCESS
)
3306 WARN ("RegCloseKey returned %li\n", r
);
3307 return ERROR_OUTOFMEMORY
;
3310 TRACE ("pass 1: calculating buffer required for all names and values\n");
3312 cbBufSize
= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
3314 TRACE ("%li bytes required for %li headers\n", cbBufSize
, cValues
);
3316 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
3318 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
3319 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
3320 NULL
, NULL
, lpValue
, &cbValueLen
);
3321 if (ret
!= ERROR_SUCCESS
)
3323 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3324 WARN ("HeapFree failed with code %li\n", GetLastError ());
3325 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3326 WARN ("HeapFree failed with code %li\n", GetLastError ());
3327 r
= RegCloseKey (hkSubKey
);
3328 if (r
!= ERROR_SUCCESS
)
3329 WARN ("RegCloseKey returned %li\n", r
);
3330 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
3334 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
3335 debugstr_w (lpValueName
), dwIndex
,
3336 (cbValueNameLen
+ 1) * sizeof (WCHAR
), cbValueLen
);
3338 cbBufSize
+= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
3339 cbBufSize
+= cbValueLen
;
3342 TRACE ("%li bytes required for all %li values\n", cbBufSize
, cValues
);
3344 *pcbEnumValues
= cbBufSize
;
3345 *pnEnumValues
= cValues
;
3347 if (cbEnumValues
< cbBufSize
) /* buffer too small */
3349 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3350 WARN ("HeapFree failed with code %li\n", GetLastError ());
3351 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3352 WARN ("HeapFree failed with code %li\n", GetLastError ());
3353 r
= RegCloseKey (hkSubKey
);
3354 if (r
!= ERROR_SUCCESS
)
3355 WARN ("RegCloseKey returned %li\n", r
);
3356 TRACE ("%li byte buffer is not large enough\n", cbEnumValues
);
3357 return ERROR_MORE_DATA
;
3360 TRACE ("pass 2: copying all names and values to buffer\n");
3362 ppev
= (PPRINTER_ENUM_VALUESW
) pEnumValues
; /* array of structs */
3363 pEnumValues
+= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
3365 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
3367 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
3368 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
3369 NULL
, &dwType
, lpValue
, &cbValueLen
);
3370 if (ret
!= ERROR_SUCCESS
)
3372 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3373 WARN ("HeapFree failed with code %li\n", GetLastError ());
3374 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3375 WARN ("HeapFree failed with code %li\n", GetLastError ());
3376 r
= RegCloseKey (hkSubKey
);
3377 if (r
!= ERROR_SUCCESS
)
3378 WARN ("RegCloseKey returned %li\n", r
);
3379 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
3383 cbValueNameLen
= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
3384 memcpy (pEnumValues
, lpValueName
, cbValueNameLen
);
3385 ppev
[dwIndex
].pValueName
= (LPWSTR
) pEnumValues
;
3386 pEnumValues
+= cbValueNameLen
;
3388 /* return # of *bytes* (including trailing \0), not # of chars */
3389 ppev
[dwIndex
].cbValueName
= cbValueNameLen
;
3391 ppev
[dwIndex
].dwType
= dwType
;
3393 memcpy (pEnumValues
, lpValue
, cbValueLen
);
3394 ppev
[dwIndex
].pData
= pEnumValues
;
3395 pEnumValues
+= cbValueLen
;
3397 ppev
[dwIndex
].cbData
= cbValueLen
;
3399 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
3400 debugstr_w (lpValueName
), dwIndex
, cbValueNameLen
, cbValueLen
);
3403 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3405 ret
= GetLastError ();
3406 ERR ("HeapFree failed with code %li\n", ret
);
3407 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3408 WARN ("HeapFree failed with code %li\n", GetLastError ());
3409 r
= RegCloseKey (hkSubKey
);
3410 if (r
!= ERROR_SUCCESS
)
3411 WARN ("RegCloseKey returned %li\n", r
);
3415 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3417 ret
= GetLastError ();
3418 ERR ("HeapFree failed with code %li\n", ret
);
3419 r
= RegCloseKey (hkSubKey
);
3420 if (r
!= ERROR_SUCCESS
)
3421 WARN ("RegCloseKey returned %li\n", r
);
3425 ret
= RegCloseKey (hkSubKey
);
3426 if (ret
!= ERROR_SUCCESS
)
3428 ERR ("RegCloseKey returned %li\n", ret
);
3432 return ERROR_SUCCESS
;
3435 /*******************************************************************************
3436 * EnumPrinterDataExA [WINSPOOL.@]
3438 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
3439 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
3440 * what Windows 2000 SP1 does.
3443 DWORD WINAPI
EnumPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
,
3444 LPBYTE pEnumValues
, DWORD cbEnumValues
,
3445 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
3449 DWORD ret
, dwIndex
, dwBufSize
;
3453 TRACE ("%p %s\n", hPrinter
, pKeyName
);
3455 if (pKeyName
== NULL
|| *pKeyName
== 0)
3456 return ERROR_INVALID_PARAMETER
;
3458 len
= MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, NULL
, 0);
3461 ret
= GetLastError ();
3462 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
3466 hHeap
= GetProcessHeap ();
3469 ERR ("GetProcessHeap failed\n");
3470 return ERROR_OUTOFMEMORY
;
3473 pKeyNameW
= HeapAlloc (hHeap
, 0, len
* sizeof (WCHAR
));
3474 if (pKeyNameW
== NULL
)
3476 ERR ("Failed to allocate %li bytes from process heap\n",
3477 (LONG
) len
* sizeof (WCHAR
));
3478 return ERROR_OUTOFMEMORY
;
3481 if (MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, pKeyNameW
, len
) == 0)
3483 ret
= GetLastError ();
3484 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
3485 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3486 WARN ("HeapFree failed with code %li\n", GetLastError ());
3490 ret
= EnumPrinterDataExW (hPrinter
, pKeyNameW
, pEnumValues
, cbEnumValues
,
3491 pcbEnumValues
, pnEnumValues
);
3492 if (ret
!= ERROR_SUCCESS
)
3494 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3495 WARN ("HeapFree failed with code %li\n", GetLastError ());
3496 TRACE ("EnumPrinterDataExW returned %li\n", ret
);
3500 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3502 ret
= GetLastError ();
3503 ERR ("HeapFree failed with code %li\n", ret
);
3507 if (*pnEnumValues
== 0) /* empty key */
3508 return ERROR_SUCCESS
;
3511 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
3513 PPRINTER_ENUM_VALUESW ppev
=
3514 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
3516 if (dwBufSize
< ppev
->cbValueName
)
3517 dwBufSize
= ppev
->cbValueName
;
3519 if (dwBufSize
< ppev
->cbData
&& (ppev
->dwType
== REG_SZ
||
3520 ppev
->dwType
== REG_EXPAND_SZ
|| ppev
->dwType
== REG_MULTI_SZ
))
3521 dwBufSize
= ppev
->cbData
;
3524 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize
);
3526 pBuffer
= HeapAlloc (hHeap
, 0, dwBufSize
);
3527 if (pBuffer
== NULL
)
3529 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize
);
3530 return ERROR_OUTOFMEMORY
;
3533 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
3535 PPRINTER_ENUM_VALUESW ppev
=
3536 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
3538 len
= WideCharToMultiByte (CP_ACP
, 0, ppev
->pValueName
,
3539 ppev
->cbValueName
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
,
3543 ret
= GetLastError ();
3544 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
3545 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3546 WARN ("HeapFree failed with code %li\n", GetLastError ());
3550 memcpy (ppev
->pValueName
, pBuffer
, len
);
3552 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
3554 if (ppev
->dwType
!= REG_SZ
&& ppev
->dwType
!= REG_EXPAND_SZ
&&
3555 ppev
->dwType
!= REG_MULTI_SZ
)
3558 len
= WideCharToMultiByte (CP_ACP
, 0, (LPWSTR
) ppev
->pData
,
3559 ppev
->cbData
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
, NULL
);
3562 ret
= GetLastError ();
3563 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
3564 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3565 WARN ("HeapFree failed with code %li\n", GetLastError ());
3569 memcpy (ppev
->pData
, pBuffer
, len
);
3571 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
3572 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
3575 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3577 ret
= GetLastError ();
3578 ERR ("HeapFree failed with code %li\n", ret
);
3582 return ERROR_SUCCESS
;
3585 /******************************************************************************
3586 * AddPortA (WINSPOOL.@)
3588 BOOL WINAPI
AddPortA(LPSTR pName
,HWND hWnd
, LPSTR pMonitorName
)
3590 FIXME("(%s, %p, %s\n), stub!\n",pName
,hWnd
,pMonitorName
);
3594 /******************************************************************************
3595 * AddPrinterDriverExW (WINSPOOL.@)
3597 BOOL WINAPI
AddPrinterDriverExW( LPWSTR pName
, DWORD Level
,
3598 LPBYTE pDriverInfo
, DWORD dwFileCopyFlags
)
3600 FIXME("%s %ld %p %ld\n", debugstr_w(pName
),
3601 Level
, pDriverInfo
, dwFileCopyFlags
);
3602 SetLastError(ERROR_PRINTER_DRIVER_BLOCKED
);
3606 /******************************************************************************
3607 * AddPrinterDriverExA (WINSPOOL.@)
3609 BOOL WINAPI
AddPrinterDriverExA( LPSTR pName
, DWORD Level
,
3610 LPBYTE pDriverInfo
, DWORD dwFileCopyFlags
)
3612 FIXME("%s %ld %p %ld\n", debugstr_a(pName
),
3613 Level
, pDriverInfo
, dwFileCopyFlags
);
3614 SetLastError(ERROR_PRINTER_DRIVER_BLOCKED
);
3618 /******************************************************************************
3619 * DeletePrinterDriverExW (WINSPOOL.@)
3621 BOOL WINAPI
DeletePrinterDriverExW( LPWSTR pName
, LPWSTR pEnvironment
,
3622 LPWSTR pDriverName
, DWORD dwDeleteFlag
, DWORD dwVersionFlag
)
3624 FIXME("%s %s %s %lx %lx\n", debugstr_w(pName
), debugstr_w(pEnvironment
),
3625 debugstr_w(pDriverName
), dwDeleteFlag
, dwVersionFlag
);
3629 /******************************************************************************
3630 * DeletePrinterDriverExA (WINSPOOL.@)
3632 BOOL WINAPI
DeletePrinterDriverExA( LPSTR pName
, LPSTR pEnvironment
,
3633 LPSTR pDriverName
, DWORD dwDeleteFlag
, DWORD dwVersionFlag
)
3635 FIXME("%s %s %s %lx %lx\n", debugstr_a(pName
), debugstr_a(pEnvironment
),
3636 debugstr_a(pDriverName
), dwDeleteFlag
, dwVersionFlag
);
3640 /******************************************************************************
3641 * DeletePrinterDataExW (WINSPOOL.@)
3643 DWORD WINAPI
DeletePrinterDataExW( HANDLE hPrinter
, LPCWSTR pKeyName
,
3646 FIXME("%p %s %s\n", hPrinter
,
3647 debugstr_w(pKeyName
), debugstr_w(pValueName
));
3648 return ERROR_INVALID_PARAMETER
;
3651 /******************************************************************************
3652 * DeletePrinterDataExA (WINSPOOL.@)
3654 DWORD WINAPI
DeletePrinterDataExA( HANDLE hPrinter
, LPCSTR pKeyName
,
3657 FIXME("%p %s %s\n", hPrinter
,
3658 debugstr_a(pKeyName
), debugstr_a(pValueName
));
3659 return ERROR_INVALID_PARAMETER
;
3662 /******************************************************************************
3663 * XcvDataW (WINSPOOL.@)
3666 * There doesn't seem to be an A version...
3668 BOOL WINAPI
XcvDataW( HANDLE hXcv
, LPCWSTR pszDataName
, PBYTE pInputData
,
3669 DWORD cbInputData
, PBYTE pOutputData
, DWORD cbOutputData
,
3670 PDWORD pcbOutputNeeded
, PDWORD pdwStatus
)
3672 FIXME("%p %s %p %ld %p %ld %p %p\n", hXcv
, debugstr_w(pszDataName
),
3673 pInputData
, cbInputData
, pOutputData
,
3674 cbOutputData
, pcbOutputNeeded
, pdwStatus
);