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"
33 #ifdef HAVE_CUPS_CUPS_H
34 # include <cups/cups.h>
36 # define CUPS_SONAME "libcups.so"
40 #define NONAMELESSUNION
41 #define NONAMELESSSTRUCT
42 #include "wine/library.h"
49 #include "wine/windef16.h"
50 #include "wine/unicode.h"
51 #include "wine/debug.h"
55 WINE_DEFAULT_DEBUG_CHANNEL(winspool
);
57 static LPWSTR
*printer_array
;
58 static int nb_printers
;
60 static DWORD (WINAPI
*GDI_CallDeviceCapabilities16
)( LPCSTR lpszDevice
, LPCSTR lpszPort
,
61 WORD fwCapability
, LPSTR lpszOutput
,
63 static INT (WINAPI
*GDI_CallExtDeviceMode16
)( HWND hwnd
, LPDEVMODEA lpdmOutput
,
64 LPSTR lpszDevice
, LPSTR lpszPort
,
65 LPDEVMODEA lpdmInput
, LPSTR lpszProfile
,
68 static char Printers
[] =
69 "System\\CurrentControlSet\\control\\Print\\Printers\\";
70 static char Drivers
[] =
71 "System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
73 static WCHAR DefaultEnvironmentW
[] = {'W','i','n','e',0};
75 static WCHAR Configuration_FileW
[] = {'C','o','n','f','i','g','u','r','a','t',
76 'i','o','n',' ','F','i','l','e',0};
77 static WCHAR DatatypeW
[] = {'D','a','t','a','t','y','p','e',0};
78 static WCHAR Data_FileW
[] = {'D','a','t','a',' ','F','i','l','e',0};
79 static WCHAR Default_DevModeW
[] = {'D','e','f','a','u','l','t',' ','D','e','v',
81 static WCHAR Dependent_FilesW
[] = {'D','e','p','e','n','d','e','n','t',' ','F',
83 static WCHAR DescriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
84 static WCHAR DriverW
[] = {'D','r','i','v','e','r',0};
85 static WCHAR Help_FileW
[] = {'H','e','l','p',' ','F','i','l','e',0};
86 static WCHAR LocationW
[] = {'L','o','c','a','t','i','o','n',0};
87 static WCHAR MonitorW
[] = {'M','o','n','i','t','o','r',0};
88 static WCHAR NameW
[] = {'N','a','m','e',0};
89 static WCHAR ParametersW
[] = {'P','a','r','a','m','e','t','e','r','s',0};
90 static WCHAR PortW
[] = {'P','o','r','t',0};
91 static WCHAR Print_ProcessorW
[] = {'P','r','i','n','t',' ','P','r','o','c','e',
93 static WCHAR Printer_DriverW
[] = {'P','r','i','n','t','e','r',' ','D','r','i',
95 static WCHAR PrinterDriverDataW
[] = {'P','r','i','n','t','e','r','D','r','i',
96 'v','e','r','D','a','t','a',0};
97 static WCHAR Separator_FileW
[] = {'S','e','p','a','r','a','t','o','r',' ','F',
99 static WCHAR Share_NameW
[] = {'S','h','a','r','e',' ','N','a','m','e',0};
100 static WCHAR WinPrintW
[] = {'W','i','n','P','r','i','n','t',0};
102 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
);
103 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
104 DWORD Level
, LPBYTE pDriverInfo
,
105 DWORD cbBuf
, LPDWORD pcbNeeded
,
108 WINSPOOL_SetDefaultPrinter(const char *devname
, const char *name
,BOOL force
) {
111 /* If forcing, or no profile string entry for device yet, set the entry
113 * The always change entry if not WINEPS yet is discussable.
116 !GetProfileStringA("windows","device","*",qbuf
,sizeof(qbuf
)) ||
118 !strstr(qbuf
,"WINEPS")
120 char *buf
= HeapAlloc(GetProcessHeap(),0,strlen(name
)+strlen(devname
)+strlen(",WINEPS,LPR:")+1);
122 sprintf(buf
,"%s,WINEPS,LPR:%s",devname
,name
);
123 WriteProfileStringA("windows","device",buf
);
124 HeapFree(GetProcessHeap(),0,buf
);
128 #ifdef HAVE_CUPS_CUPS_H
130 CUPS_LoadPrinters(void) {
131 typeof(cupsGetPrinters
) *pcupsGetPrinters
= NULL
;
132 typeof(cupsGetDefault
) *pcupsGetDefault
= NULL
;
133 typeof(cupsGetPPD
) *pcupsGetPPD
= NULL
;
135 int i
,nrofdests
,hadprinter
= FALSE
;
136 PRINTER_INFO_2A pinfo2a
;
138 void *cupshandle
= NULL
;
140 cupshandle
= wine_dlopen(CUPS_SONAME
, RTLD_NOW
, NULL
, 0);
145 p##x = wine_dlsym(cupshandle, #x, NULL,0); \
146 if (!p##x) return FALSE;
148 DYNCUPS(cupsGetDefault
);
150 DYNCUPS(cupsGetPrinters
);
153 def
= pcupsGetDefault();
155 if (def
&& !strcmp(def
,"none")) /* CUPS has "none" for no default printer */
158 nrofdests
= pcupsGetPrinters(&printers
);
159 for (i
=0;i
<nrofdests
;i
++) {
160 const char *ppd
= pcupsGetPPD(printers
[i
]);
164 WARN("No ppd file for %s.\n",printers
[i
]);
165 /* If this was going to be the default printer,
166 * forget it and use another one.
168 if (def
&& !strcmp(def
,printers
[i
]))
176 if (def
&& !strcmp(def
,printers
[i
]))
177 WINSPOOL_SetDefaultPrinter(printers
[i
],printers
[i
],FALSE
);
179 /* The default printer has no PPD file, just use the first one
183 WINSPOOL_SetDefaultPrinter(printers
[i
],printers
[i
],FALSE
);
186 memset(&pinfo2a
,0,sizeof(pinfo2a
));
187 pinfo2a
.pPrinterName
= printers
[i
];
188 pinfo2a
.pDatatype
= "RAW";
189 pinfo2a
.pPrintProcessor
= "WinPrint";
190 pinfo2a
.pDriverName
= "PS Driver";
191 pinfo2a
.pComment
= "WINEPS Printer using CUPS";
192 pinfo2a
.pLocation
= "<physical location of printer>";
193 port
= HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(printers
[i
])+1);
194 sprintf(port
,"LPR:%s",printers
[i
]);
195 pinfo2a
.pPortName
= port
;
196 pinfo2a
.pParameters
= "<parameters?>";
197 pinfo2a
.pShareName
= "<share name?>";
198 pinfo2a
.pSepFile
= "<sep file?>";
200 devline
=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port
)+1);
201 sprintf(devline
,"WINEPS,%s",port
);
202 WriteProfileStringA("devices",printers
[i
],devline
);
203 HeapFree(GetProcessHeap(),0,devline
);
205 if (!AddPrinterA(NULL
,2,(LPBYTE
)&pinfo2a
)) {
206 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS
)
207 ERR("printer '%s' not added by AddPrinterA (error %ld)\n",printers
[i
],GetLastError());
209 HeapFree(GetProcessHeap(),0,port
);
211 wine_dlclose(cupshandle
, NULL
, 0);
217 PRINTCAP_ParseEntry(char *pent
,BOOL isfirst
) {
218 PRINTER_INFO_2A pinfo2a
;
219 char *s
,*name
,*prettyname
,*devname
;
223 while (isspace(*pent
)) pent
++;
224 s
= strchr(pent
,':');
225 if (!s
) return FALSE
;
231 /* Determine whether this is a postscript printer. */
233 /* 1. Check if name or aliases contain trigger phrases like 'ps' */
234 if (strstr(name
,"ps") ||
235 strstr(name
,"pd") || /* postscript double page */
236 strstr(name
,"postscript") ||
237 strstr(name
,"PostScript")
239 TRACE("%s has 'ps' style name, assuming postscript.\n",name
);
242 /* 2. Check if this is a remote printer. These usually are postscript
245 if (strstr(pent
,":rm")) {
247 TRACE("%s is remote, assuming postscript.\n",name
);
249 /* 3. Check if we have an input filter program. If we have one, it
250 * most likely is one capable of converting postscript.
251 * (Could probably check for occurrence of 'gs' or 'ghostscript'
252 * in the if file itself.)
254 if (strstr(pent
,":if=/")) {
256 TRACE("%s has inputfilter program, assuming postscript.\n",name
);
259 /* If it is not a postscript printer, we cannot use it. */
264 /* Get longest name, usually the one at the right for later display. */
265 while ((s
=strchr(prettyname
,'|'))) prettyname
= s
+1;
266 s
=strchr(name
,'|');if (s
) *s
='\0';
268 /* prettyname must fit into the dmDeviceName member of DEVMODE struct,
269 * if it is too long, we use it as comment below. */
270 devname
= prettyname
;
271 if (strlen(devname
)>=CCHDEVICENAME
-1)
273 if (strlen(devname
)>=CCHDEVICENAME
-1)
276 if (isfirst
) /* set first entry as default */
277 WINSPOOL_SetDefaultPrinter(devname
,name
,FALSE
);
279 memset(&pinfo2a
,0,sizeof(pinfo2a
));
280 pinfo2a
.pPrinterName
= devname
;
281 pinfo2a
.pDatatype
= "RAW";
282 pinfo2a
.pPrintProcessor
= "WinPrint";
283 pinfo2a
.pDriverName
= "PS Driver";
284 pinfo2a
.pComment
= "WINEPS Printer using LPR";
285 pinfo2a
.pLocation
= prettyname
;
286 port
= HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(name
)+1);
287 sprintf(port
,"LPR:%s",name
);
288 pinfo2a
.pPortName
= port
;
289 pinfo2a
.pParameters
= "<parameters?>";
290 pinfo2a
.pShareName
= "<share name?>";
291 pinfo2a
.pSepFile
= "<sep file?>";
293 devline
=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port
)+1);
294 sprintf(devline
,"WINEPS,%s",port
);
295 WriteProfileStringA("devices",devname
,devline
);
296 HeapFree(GetProcessHeap(),0,devline
);
298 if (!AddPrinterA(NULL
,2,(LPBYTE
)&pinfo2a
)) {
299 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS
)
300 ERR("%s not added by AddPrinterA (%ld)\n",name
,GetLastError());
302 HeapFree(GetProcessHeap(),0,port
);
307 PRINTCAP_LoadPrinters(void) {
308 BOOL hadprinter
= FALSE
, isfirst
= TRUE
;
312 f
= fopen("/etc/printcap","r");
316 while (fgets(buf
,sizeof(buf
),f
)) {
320 s
=strchr(buf
,'\n'); if (s
) *s
='\0';
321 if ((buf
[0]=='#') || (buf
[0]=='\0'))
325 pent
=HeapReAlloc(GetProcessHeap(),0,pent
,strlen(pent
)+strlen(buf
)+2);
328 pent
=HeapAlloc(GetProcessHeap(),0,strlen(buf
)+1);
332 if (strlen(pent
) && (pent
[strlen(pent
)-1] == '\\'))
333 pent
[strlen(pent
)-1] = '\0';
336 } while (fgets(buf
,sizeof(buf
),f
));
338 hadprinter
|= PRINTCAP_ParseEntry(pent
,isfirst
);
340 if (pent
) HeapFree(GetProcessHeap(),0,pent
);
348 static inline DWORD
set_reg_szW(HKEY hkey
, WCHAR
*keyname
, WCHAR
*value
)
350 return RegSetValueExW(hkey
, keyname
, 0, REG_SZ
, (LPBYTE
)value
,
351 lstrlenW(value
) * sizeof(WCHAR
));
355 WINSPOOL_LoadSystemPrinters() {
358 di3a
.cVersion
= 0x400;
359 di3a
.pName
= "PS Driver";
360 di3a
.pEnvironment
= NULL
; /* NULL means auto */
361 di3a
.pDriverPath
= "wineps16";
362 di3a
.pDataFile
= "<datafile?>";
363 di3a
.pConfigFile
= "wineps16";
364 di3a
.pHelpFile
= "<helpfile?>";
365 di3a
.pDependentFiles
= "<dependend files?>";
366 di3a
.pMonitorName
= "<monitor name?>";
367 di3a
.pDefaultDataType
= "RAW";
369 if (!AddPrinterDriverA(NULL
,3,(LPBYTE
)&di3a
)) {
370 ERR("Failed adding PS Driver (%ld)\n",GetLastError());
373 #ifdef HAVE_CUPS_CUPS_H
374 /* If we have any CUPS based printers, skip looking for printcap printers */
375 if (CUPS_LoadPrinters())
379 /* Check for [ppd] section in config file before parsing /etc/printcap */
381 if (RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\ppd",
382 &hkPPD
) == ERROR_SUCCESS
)
385 PRINTCAP_LoadPrinters();
390 /******************************************************************
391 * WINSPOOL_GetOpenedPrinterEntry
392 * Get the first place empty in the opened printer table
394 static HANDLE
WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name
)
398 for (i
= 0; i
< nb_printers
; i
++) if (!printer_array
[i
]) break;
400 if (i
>= nb_printers
)
402 LPWSTR
*new_array
= HeapReAlloc( GetProcessHeap(), 0, printer_array
,
403 (nb_printers
+ 16) * sizeof(*new_array
) );
404 if (!new_array
) return 0;
405 printer_array
= new_array
;
409 if ((printer_array
[i
] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name
)+1)*sizeof(WCHAR
) )))
411 strcpyW( printer_array
[i
], name
);
412 return (HANDLE
)(i
+ 1);
417 /******************************************************************
418 * WINSPOOL_GetOpenedPrinter
419 * Get the pointer to the opened printer referred by the handle
421 static LPCWSTR
WINSPOOL_GetOpenedPrinter(HANDLE printerHandle
)
423 int idx
= (int)printerHandle
;
424 if ((idx
<= 0) || (idx
> nb_printers
))
426 SetLastError(ERROR_INVALID_HANDLE
);
429 return printer_array
[idx
- 1];
432 /******************************************************************
433 * WINSPOOL_GetOpenedPrinterRegKey
436 static DWORD
WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter
, HKEY
*phkey
)
438 LPCWSTR name
= WINSPOOL_GetOpenedPrinter(hPrinter
);
442 if(!name
) return ERROR_INVALID_HANDLE
;
444 if((ret
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
)) !=
448 if(RegOpenKeyW(hkeyPrinters
, name
, phkey
) != ERROR_SUCCESS
)
450 ERR("Can't find opened printer %s in registry\n",
452 RegCloseKey(hkeyPrinters
);
453 return ERROR_INVALID_PRINTER_NAME
; /* ? */
455 RegCloseKey(hkeyPrinters
);
456 return ERROR_SUCCESS
;
459 /***********************************************************
462 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
465 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
468 Formname
= (dmA
->dmSize
> off_formname
);
469 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
470 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
473 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
474 dmA
->dmSize
- CCHDEVICENAME
);
476 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
477 off_formname
- CCHDEVICENAME
);
478 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
480 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
481 (off_formname
+ CCHFORMNAME
));
484 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
489 /***********************************************************
491 * Creates a unicode copy of supplied devmode on heap
493 static LPDEVMODEW
DEVMODEdupAtoW(HANDLE heap
, const DEVMODEA
*dmA
)
498 ptrdiff_t off_formname
;
501 if(!dmA
) return NULL
;
503 off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
504 Formname
= (dmA
->dmSize
> off_formname
);
505 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
506 dmW
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmA
->dmDriverExtra
);
507 return DEVMODEcpyAtoW(dmW
, dmA
);
510 /***********************************************************
512 * Creates an ascii copy of supplied devmode on heap
514 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
519 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
521 if(!dmW
) return NULL
;
522 Formname
= (dmW
->dmSize
> off_formname
);
523 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
524 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
525 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
526 CCHDEVICENAME
, NULL
, NULL
);
528 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
529 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
531 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
532 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
533 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
534 CCHFORMNAME
, NULL
, NULL
);
535 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
536 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
539 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
544 /***********************************************************
546 * Creates a unicode copy of PRINTER_INFO_2A on heap
548 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
550 LPPRINTER_INFO_2W piW
;
551 if(!piA
) return NULL
;
552 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
553 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
554 piW
->pServerName
= HEAP_strdupAtoW(heap
, 0, piA
->pServerName
);
555 piW
->pPrinterName
= HEAP_strdupAtoW(heap
, 0, piA
->pPrinterName
);
556 piW
->pShareName
= HEAP_strdupAtoW(heap
, 0, piA
->pShareName
);
557 piW
->pPortName
= HEAP_strdupAtoW(heap
, 0, piA
->pPortName
);
558 piW
->pDriverName
= HEAP_strdupAtoW(heap
, 0, piA
->pDriverName
);
559 piW
->pComment
= HEAP_strdupAtoW(heap
, 0, piA
->pComment
);
560 piW
->pLocation
= HEAP_strdupAtoW(heap
, 0, piA
->pLocation
);
561 piW
->pDevMode
= DEVMODEdupAtoW(heap
, piA
->pDevMode
);
562 piW
->pSepFile
= HEAP_strdupAtoW(heap
, 0, piA
->pSepFile
);
563 piW
->pPrintProcessor
= HEAP_strdupAtoW(heap
, 0, piA
->pPrintProcessor
);
564 piW
->pDatatype
= HEAP_strdupAtoW(heap
, 0, piA
->pDatatype
);
565 piW
->pParameters
= HEAP_strdupAtoW(heap
, 0, piA
->pParameters
);
569 /***********************************************************
570 * FREE_PRINTER_INFO_2W
571 * Free PRINTER_INFO_2W and all strings
573 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
577 HeapFree(heap
,0,piW
->pServerName
);
578 HeapFree(heap
,0,piW
->pPrinterName
);
579 HeapFree(heap
,0,piW
->pShareName
);
580 HeapFree(heap
,0,piW
->pPortName
);
581 HeapFree(heap
,0,piW
->pDriverName
);
582 HeapFree(heap
,0,piW
->pComment
);
583 HeapFree(heap
,0,piW
->pLocation
);
584 HeapFree(heap
,0,piW
->pDevMode
);
585 HeapFree(heap
,0,piW
->pSepFile
);
586 HeapFree(heap
,0,piW
->pPrintProcessor
);
587 HeapFree(heap
,0,piW
->pDatatype
);
588 HeapFree(heap
,0,piW
->pParameters
);
589 HeapFree(heap
,0,piW
);
593 /******************************************************************
594 * DeviceCapabilities [WINSPOOL.@]
595 * DeviceCapabilitiesA [WINSPOOL.@]
598 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
599 LPSTR pOutput
, LPDEVMODEA lpdm
)
603 if (!GDI_CallDeviceCapabilities16
)
605 GDI_CallDeviceCapabilities16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
607 if (!GDI_CallDeviceCapabilities16
) return -1;
609 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
611 /* If DC_PAPERSIZE map POINT16s to POINTs */
612 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
613 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
614 POINT
*pt
= (POINT
*)pOutput
;
616 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
617 for(i
= 0; i
< ret
; i
++, pt
++)
622 HeapFree( GetProcessHeap(), 0, tmp
);
628 /*****************************************************************************
629 * DeviceCapabilitiesW [WINSPOOL.@]
631 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
634 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
635 WORD fwCapability
, LPWSTR pOutput
,
636 const DEVMODEW
*pDevMode
)
638 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
639 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
640 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
643 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
644 fwCapability
== DC_FILEDEPENDENCIES
||
645 fwCapability
== DC_PAPERNAMES
)) {
646 /* These need A -> W translation */
649 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
653 switch(fwCapability
) {
658 case DC_FILEDEPENDENCIES
:
662 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
663 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
665 for(i
= 0; i
< ret
; i
++)
666 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
667 pOutput
+ (i
* size
), size
);
668 HeapFree(GetProcessHeap(), 0, pOutputA
);
670 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
671 (LPSTR
)pOutput
, dmA
);
673 HeapFree(GetProcessHeap(),0,pPortA
);
674 HeapFree(GetProcessHeap(),0,pDeviceA
);
675 HeapFree(GetProcessHeap(),0,dmA
);
679 /******************************************************************
680 * DocumentPropertiesA [WINSPOOL.@]
683 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
684 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
685 LPDEVMODEA pDevModeInput
,DWORD fMode
)
687 LPSTR lpName
= pDeviceName
;
690 TRACE("(%p,%p,%s,%p,%p,%ld)\n",
691 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
695 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
697 ERR("no name from hPrinter?\n");
700 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
703 if (!GDI_CallExtDeviceMode16
)
705 GDI_CallExtDeviceMode16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
707 if (!GDI_CallExtDeviceMode16
) {
708 ERR("No CallExtDeviceMode16?\n");
712 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
713 pDevModeInput
, NULL
, fMode
);
716 HeapFree(GetProcessHeap(),0,lpName
);
721 /*****************************************************************************
722 * DocumentPropertiesW (WINSPOOL.@)
724 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
726 LPDEVMODEW pDevModeOutput
,
727 LPDEVMODEW pDevModeInput
, DWORD fMode
)
730 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
731 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
732 LPDEVMODEA pDevModeOutputA
= NULL
;
735 TRACE("(%p,%p,%s,%p,%p,%ld)\n",
736 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
739 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
740 if(ret
< 0) return ret
;
741 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
743 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
744 pDevModeInputA
, fMode
);
746 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
747 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
749 if(fMode
== 0 && ret
> 0)
750 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
751 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
752 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
756 /******************************************************************
757 * OpenPrinterA [WINSPOOL.@]
760 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
761 LPPRINTER_DEFAULTSA pDefault
)
763 LPWSTR lpPrinterNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName
);
764 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
768 DefaultW
.pDatatype
= HEAP_strdupAtoW(GetProcessHeap(), 0,
769 pDefault
->pDatatype
);
770 DefaultW
.pDevMode
= DEVMODEdupAtoW(GetProcessHeap(),
772 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
773 pDefaultW
= &DefaultW
;
775 ret
= OpenPrinterW(lpPrinterNameW
, phPrinter
, pDefaultW
);
777 HeapFree(GetProcessHeap(), 0, DefaultW
.pDatatype
);
778 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
780 HeapFree(GetProcessHeap(), 0, lpPrinterNameW
);
784 /******************************************************************
785 * OpenPrinterW [WINSPOOL.@]
788 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
789 LPPRINTER_DEFAULTSW pDefault
)
791 HKEY hkeyPrinters
, hkeyPrinter
;
793 if (!lpPrinterName
) {
794 FIXME("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
795 SetLastError(ERROR_INVALID_PARAMETER
);
799 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
802 /* Check Printer exists */
803 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
805 ERR("Can't create Printers key\n");
806 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
810 if(lpPrinterName
[0] == '\0' || /* explicitly exclude "" */
811 RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
813 TRACE("Can't find printer %s in registry\n",
814 debugstr_w(lpPrinterName
));
815 RegCloseKey(hkeyPrinters
);
816 SetLastError(ERROR_INVALID_PRINTER_NAME
);
819 RegCloseKey(hkeyPrinter
);
820 RegCloseKey(hkeyPrinters
);
822 if(!phPrinter
) /* This seems to be what win95 does anyway */
825 /* Get the unique handle of the printer*/
826 *phPrinter
= WINSPOOL_GetOpenedPrinterEntry( lpPrinterName
);
828 if (pDefault
!= NULL
)
829 FIXME("Not handling pDefault\n");
834 /******************************************************************
835 * AddMonitorA [WINSPOOL.@]
838 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
840 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
841 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
845 /******************************************************************
846 * DeletePrinterDriverA [WINSPOOL.@]
850 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
852 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
853 debugstr_a(pDriverName
));
854 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
859 /******************************************************************
860 * DeleteMonitorA [WINSPOOL.@]
864 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
866 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
867 debugstr_a(pMonitorName
));
868 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
873 /******************************************************************
874 * DeletePortA [WINSPOOL.@]
878 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
880 FIXME("(%s,%p,%s):stub\n",debugstr_a(pName
),hWnd
,
881 debugstr_a(pPortName
));
882 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
886 /******************************************************************************
887 * SetPrinterW [WINSPOOL.@]
897 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
901 /******************************************************************************
902 * WritePrinter [WINSPOOL.@]
912 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
916 /*****************************************************************************
917 * AddFormA [WINSPOOL.@]
919 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
921 FIXME("(%p,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
925 /*****************************************************************************
926 * AddFormW [WINSPOOL.@]
928 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
930 FIXME("(%p,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
934 /*****************************************************************************
935 * AddJobA [WINSPOOL.@]
937 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
938 DWORD cbBuf
, LPDWORD pcbNeeded
)
940 FIXME("(%p,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
945 /*****************************************************************************
946 * AddJobW [WINSPOOL.@]
948 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
951 FIXME("(%p,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
956 /*****************************************************************************
957 * WINSPOOL_OpenDriverReg [internal]
959 * opens the registry for the printer drivers depending on the given input
960 * variable pEnvironment
963 * the opened hkey on success
966 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
)
968 LPSTR lpKey
, p
= NULL
;
971 (unicode
) ? debugstr_w(pEnvironment
) : debugstr_a(pEnvironment
));
974 p
= (unicode
) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
) :
978 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
980 if(!GetVersionExA( &ver
))
983 switch (ver
.dwPlatformId
) {
984 case VER_PLATFORM_WIN32s
:
985 ERR("win32 style printing used with 16 bits app, try specifying 'win95' Windows version\n");
988 case VER_PLATFORM_WIN32_NT
:
989 p
= "Windows NT x86";
995 TRACE("set environment to %s\n", p
);
998 lpKey
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
999 strlen(p
) + strlen(Drivers
));
1000 sprintf( lpKey
, Drivers
, p
);
1002 TRACE("%s\n", lpKey
);
1004 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, lpKey
, &retval
) !=
1008 if(pEnvironment
&& unicode
)
1009 HeapFree( GetProcessHeap(), 0, p
);
1010 HeapFree( GetProcessHeap(), 0, lpKey
);
1015 /*****************************************************************************
1016 * AddPrinterW [WINSPOOL.@]
1018 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1020 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
1024 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
1027 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
1030 ERR("pName = %s - unsupported\n", debugstr_w(pName
));
1031 SetLastError(ERROR_INVALID_PARAMETER
);
1035 ERR("Level = %ld, unsupported!\n", Level
);
1036 SetLastError(ERROR_INVALID_LEVEL
);
1039 if (strlenW(pi
->pPrinterName
) >= CCHDEVICENAME
) {
1040 ERR("Printername %s must not exceed length of DEVMODE.dmDeviceName !\n",
1041 debugstr_w(pi
->pPrinterName
)
1043 SetLastError(ERROR_INVALID_LEVEL
);
1047 SetLastError(ERROR_INVALID_PARAMETER
);
1050 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1052 ERR("Can't create Printers key\n");
1055 if(!RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
)) {
1056 if (!RegQueryValueA(hkeyPrinter
,"Attributes",NULL
,NULL
)) {
1057 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
1058 RegCloseKey(hkeyPrinter
);
1059 RegCloseKey(hkeyPrinters
);
1062 RegCloseKey(hkeyPrinter
);
1064 hkeyDrivers
= WINSPOOL_OpenDriverReg( NULL
, TRUE
);
1066 ERR("Can't create Drivers key\n");
1067 RegCloseKey(hkeyPrinters
);
1070 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
1072 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
1073 RegCloseKey(hkeyPrinters
);
1074 RegCloseKey(hkeyDrivers
);
1075 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
1078 RegCloseKey(hkeyDriver
);
1079 RegCloseKey(hkeyDrivers
);
1081 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
1082 FIXME("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
1083 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
1084 RegCloseKey(hkeyPrinters
);
1088 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
1090 FIXME("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
1091 SetLastError(ERROR_INVALID_PRINTER_NAME
);
1092 RegCloseKey(hkeyPrinters
);
1095 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
1096 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
1097 set_reg_szW(hkeyPrinter
, DatatypeW
, pi
->pDatatype
);
1099 /* See if we can load the driver. We may need the devmode structure anyway
1102 * Note that DocumentPropertiesW will briefly try to open the printer we
1103 * just create to find a DEVMODEA struct (it will use the WINEPS default
1104 * one in case it is not there, so we are ok).
1106 size
= DocumentPropertiesW(0, 0, pi
->pPrinterName
, NULL
, NULL
, 0);
1108 FIXME("DocumentPropertiesW on printer '%s' fails\n", debugstr_w(pi
->pPrinterName
));
1109 size
= sizeof(DEVMODEW
);
1114 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
1116 if (0>DocumentPropertiesW(0,0,pi
->pPrinterName
,dmW
,NULL
,DM_OUT_BUFFER
)) {
1117 ERR("DocumentPropertiesW on printer '%s' failed!\n", debugstr_w(pi
->pPrinterName
));
1118 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
1121 /* set devmode to printer name */
1122 strcpyW(dmW
->dmDeviceName
,pi
->pPrinterName
);
1125 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
1126 and we support these drivers. NT writes DEVMODEW so somehow
1127 we'll need to distinguish between these when we support NT
1129 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
1130 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
, (LPBYTE
)dmA
,
1131 dmA
->dmSize
+ dmA
->dmDriverExtra
);
1132 HeapFree(GetProcessHeap(), 0, dmA
);
1134 HeapFree(GetProcessHeap(), 0, dmW
);
1135 set_reg_szW(hkeyPrinter
, DescriptionW
, pi
->pComment
);
1136 set_reg_szW(hkeyPrinter
, LocationW
, pi
->pLocation
);
1137 set_reg_szW(hkeyPrinter
, NameW
, pi
->pPrinterName
);
1138 set_reg_szW(hkeyPrinter
, ParametersW
, pi
->pParameters
);
1140 set_reg_szW(hkeyPrinter
, PortW
, pi
->pPortName
);
1141 set_reg_szW(hkeyPrinter
, Print_ProcessorW
, pi
->pPrintProcessor
);
1142 set_reg_szW(hkeyPrinter
, Printer_DriverW
, pi
->pDriverName
);
1143 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
1144 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
1145 set_reg_szW(hkeyPrinter
, Separator_FileW
, pi
->pSepFile
);
1146 set_reg_szW(hkeyPrinter
, Share_NameW
, pi
->pShareName
);
1147 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
1148 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
1149 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
1150 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
1151 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
1152 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
1154 RegCloseKey(hkeyPrinter
);
1155 RegCloseKey(hkeyPrinters
);
1156 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
1157 ERR("OpenPrinter failing\n");
1163 /*****************************************************************************
1164 * AddPrinterA [WINSPOOL.@]
1166 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1169 PRINTER_INFO_2W
*piW
;
1170 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
1173 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
1175 ERR("Level = %ld, unsupported!\n", Level
);
1176 SetLastError(ERROR_INVALID_LEVEL
);
1179 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
1180 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
1182 ret
= AddPrinterW(pNameW
, Level
, (LPBYTE
)piW
);
1184 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
1185 HeapFree(GetProcessHeap(),0,pNameW
);
1190 /*****************************************************************************
1191 * ClosePrinter [WINSPOOL.@]
1193 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
1195 int i
= (int)hPrinter
;
1197 TRACE("Handle %p\n", hPrinter
);
1199 if ((i
<= 0) || (i
> nb_printers
)) return FALSE
;
1200 HeapFree( GetProcessHeap(), 0, printer_array
[i
- 1] );
1201 printer_array
[i
- 1] = NULL
;
1205 /*****************************************************************************
1206 * DeleteFormA [WINSPOOL.@]
1208 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
1210 FIXME("(%p,%s): stub\n", hPrinter
, pFormName
);
1214 /*****************************************************************************
1215 * DeleteFormW [WINSPOOL.@]
1217 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
1219 FIXME("(%p,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
1223 /*****************************************************************************
1224 * DeletePrinter [WINSPOOL.@]
1226 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
1228 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1231 if(!lpNameW
) return FALSE
;
1232 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1234 ERR("Can't open Printers key\n");
1238 /* This should use a recursive delete see Q142491 or SHDeleteKey */
1239 if(RegDeleteKeyW(hkeyPrinters
, lpNameW
) == ERROR_SUCCESS
) {
1240 SetLastError(ERROR_PRINTER_NOT_FOUND
); /* ?? */
1241 RegCloseKey(hkeyPrinters
);
1245 ClosePrinter(hPrinter
);
1249 /*****************************************************************************
1250 * SetPrinterA [WINSPOOL.@]
1252 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1255 FIXME("(%p,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
1259 /*****************************************************************************
1260 * SetJobA [WINSPOOL.@]
1262 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1263 LPBYTE pJob
, DWORD Command
)
1265 FIXME("(%p,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1270 /*****************************************************************************
1271 * SetJobW [WINSPOOL.@]
1273 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1274 LPBYTE pJob
, DWORD Command
)
1276 FIXME("(%p,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1281 /*****************************************************************************
1282 * EndDocPrinter [WINSPOOL.@]
1284 BOOL WINAPI
EndDocPrinter(HANDLE hPrinter
)
1286 FIXME("(hPrinter=%p): stub\n", hPrinter
);
1290 /*****************************************************************************
1291 * EndPagePrinter [WINSPOOL.@]
1293 BOOL WINAPI
EndPagePrinter(HANDLE hPrinter
)
1295 FIXME("(hPrinter=%p): stub\n", hPrinter
);
1299 /*****************************************************************************
1300 * StartDocPrinterA [WINSPOOL.@]
1302 DWORD WINAPI
StartDocPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pDocInfo
)
1304 FIXME("(hPrinter=%p, Level=0x%lx, pDocInfo=%p): stub\n", hPrinter
, Level
, pDocInfo
);
1308 /*****************************************************************************
1309 * StartDocPrinterW [WINSPOOL.@]
1311 DWORD WINAPI
StartDocPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pDocInfo
)
1313 FIXME("(hPrinter=%p, Level=0x%lx, pDocInfo=%p): stub\n", hPrinter
, Level
, pDocInfo
);
1317 /*****************************************************************************
1318 * StartPagePrinter [WINSPOOL.@]
1320 BOOL WINAPI
StartPagePrinter(HANDLE hPrinter
)
1322 FIXME("(hPrinter=%p): stub\n", hPrinter
);
1326 /*****************************************************************************
1327 * GetFormA [WINSPOOL.@]
1329 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1330 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1332 FIXME("(%p,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1333 Level
,pForm
,cbBuf
,pcbNeeded
);
1337 /*****************************************************************************
1338 * GetFormW [WINSPOOL.@]
1340 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1341 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1343 FIXME("(%p,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1344 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1348 /*****************************************************************************
1349 * SetFormA [WINSPOOL.@]
1351 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1354 FIXME("(%p,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1358 /*****************************************************************************
1359 * SetFormW [WINSPOOL.@]
1361 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1364 FIXME("(%p,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1368 /*****************************************************************************
1369 * ReadPrinter [WINSPOOL.@]
1371 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1372 LPDWORD pNoBytesRead
)
1374 FIXME("(%p,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1378 /*****************************************************************************
1379 * ResetPrinterA [WINSPOOL.@]
1381 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1383 FIXME("(%p, %p): stub\n", hPrinter
, pDefault
);
1387 /*****************************************************************************
1388 * ResetPrinterW [WINSPOOL.@]
1390 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1392 FIXME("(%p, %p): stub\n", hPrinter
, pDefault
);
1396 /*****************************************************************************
1397 * WINSPOOL_GetDWORDFromReg
1399 * Return DWORD associated with ValueName from hkey.
1401 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
1403 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
1406 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
1408 if(ret
!= ERROR_SUCCESS
) {
1409 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
1412 if(type
!= REG_DWORD
) {
1413 ERR("Got type %ld\n", type
);
1419 /*****************************************************************************
1420 * WINSPOOL_GetStringFromReg
1422 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1423 * String is stored either as unicode or ascii.
1424 * Bit of a hack here to get the ValueName if we want ascii.
1426 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1427 DWORD buflen
, DWORD
*needed
,
1430 DWORD sz
= buflen
, type
;
1434 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1436 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1437 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1438 HeapFree(GetProcessHeap(),0,ValueNameA
);
1440 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1441 WARN("Got ret = %ld\n", ret
);
1449 /*****************************************************************************
1450 * WINSPOOL_GetDefaultDevMode
1452 * Get a default DevMode values for wineps.
1456 static void WINSPOOL_GetDefaultDevMode(
1458 DWORD buflen
, DWORD
*needed
,
1463 /* fill default DEVMODE - should be read from ppd... */
1464 ZeroMemory( &dm
, sizeof(dm
) );
1465 strcpy(dm
.dmDeviceName
,"wineps");
1466 dm
.dmSpecVersion
= DM_SPECVERSION
;
1467 dm
.dmDriverVersion
= 1;
1468 dm
.dmSize
= sizeof(DEVMODEA
);
1469 dm
.dmDriverExtra
= 0;
1471 DM_ORIENTATION
| DM_PAPERSIZE
|
1472 DM_PAPERLENGTH
| DM_PAPERWIDTH
|
1475 DM_DEFAULTSOURCE
| DM_PRINTQUALITY
|
1476 DM_YRESOLUTION
| DM_TTOPTION
;
1478 dm
.u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1479 dm
.u1
.s1
.dmPaperSize
= DMPAPER_A4
;
1480 dm
.u1
.s1
.dmPaperLength
= 2970;
1481 dm
.u1
.s1
.dmPaperWidth
= 2100;
1485 dm
.dmDefaultSource
= DMBIN_AUTO
;
1486 dm
.dmPrintQuality
= DMRES_MEDIUM
;
1489 dm
.dmYResolution
= 300; /* 300dpi */
1490 dm
.dmTTOption
= DMTT_BITMAP
;
1493 /* dm.dmLogPixels */
1494 /* dm.dmBitsPerPel */
1495 /* dm.dmPelsWidth */
1496 /* dm.dmPelsHeight */
1497 /* dm.dmDisplayFlags */
1498 /* dm.dmDisplayFrequency */
1499 /* dm.dmICMMethod */
1500 /* dm.dmICMIntent */
1501 /* dm.dmMediaType */
1502 /* dm.dmDitherType */
1503 /* dm.dmReserved1 */
1504 /* dm.dmReserved2 */
1505 /* dm.dmPanningWidth */
1506 /* dm.dmPanningHeight */
1509 if(buflen
>= sizeof(DEVMODEW
)) {
1510 DEVMODEW
*pdmW
= DEVMODEdupAtoW(GetProcessHeap(), &dm
);
1511 memcpy(ptr
, pdmW
, sizeof(DEVMODEW
));
1512 HeapFree(GetProcessHeap(),0,pdmW
);
1514 *needed
= sizeof(DEVMODEW
);
1518 if(buflen
>= sizeof(DEVMODEA
)) {
1519 memcpy(ptr
, &dm
, sizeof(DEVMODEA
));
1521 *needed
= sizeof(DEVMODEA
);
1525 /*****************************************************************************
1526 * WINSPOOL_GetDevModeFromReg
1528 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1529 * DevMode is stored either as unicode or ascii.
1531 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1533 DWORD buflen
, DWORD
*needed
,
1536 DWORD sz
= buflen
, type
;
1539 if (ptr
&& buflen
>=sizeof(DEVMODEA
)) memset(ptr
, 0, sizeof(DEVMODEA
));
1540 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1541 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1542 if (sz
< sizeof(DEVMODEA
))
1544 ERR("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName
),sz
);
1547 /* ensures that dmSize is not erratically bogus if registry is invalid */
1548 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1549 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1551 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1553 DEVMODEW
*dmW
= DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA
*)ptr
);
1554 memcpy(ptr
, dmW
, sz
);
1555 HeapFree(GetProcessHeap(),0,dmW
);
1562 /*********************************************************************
1563 * WINSPOOL_GetPrinter_2
1565 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1566 * The strings are either stored as unicode or ascii.
1568 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1569 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1572 DWORD size
, left
= cbBuf
;
1573 BOOL space
= (cbBuf
> 0);
1578 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1580 if(space
&& size
<= left
) {
1581 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1588 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1590 if(space
&& size
<= left
) {
1591 pi2
->pShareName
= (LPWSTR
)ptr
;
1598 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1600 if(space
&& size
<= left
) {
1601 pi2
->pPortName
= (LPWSTR
)ptr
;
1608 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1610 if(space
&& size
<= left
) {
1611 pi2
->pDriverName
= (LPWSTR
)ptr
;
1618 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1620 if(space
&& size
<= left
) {
1621 pi2
->pComment
= (LPWSTR
)ptr
;
1628 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1630 if(space
&& size
<= left
) {
1631 pi2
->pLocation
= (LPWSTR
)ptr
;
1638 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1640 if(space
&& size
<= left
) {
1641 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1650 MESSAGE( "no DevMode in registry. please setup your printer again.\n"
1651 "use the default hard-coded DevMode(wineps/A4/300dpi).\n" );
1652 WINSPOOL_GetDefaultDevMode(ptr
, left
, &size
, unicode
);
1653 if(space
&& size
<= left
) {
1654 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1661 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1663 if(space
&& size
<= left
) {
1664 pi2
->pSepFile
= (LPWSTR
)ptr
;
1671 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1673 if(space
&& size
<= left
) {
1674 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1681 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1683 if(space
&& size
<= left
) {
1684 pi2
->pDatatype
= (LPWSTR
)ptr
;
1691 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1693 if(space
&& size
<= left
) {
1694 pi2
->pParameters
= (LPWSTR
)ptr
;
1702 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1703 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1704 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1705 "Default Priority");
1706 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1707 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1710 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1711 memset(pi2
, 0, sizeof(*pi2
));
1716 /*********************************************************************
1717 * WINSPOOL_GetPrinter_4
1719 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1721 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1722 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1725 DWORD size
, left
= cbBuf
;
1726 BOOL space
= (cbBuf
> 0);
1731 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1733 if(space
&& size
<= left
) {
1734 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1742 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1745 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1746 memset(pi4
, 0, sizeof(*pi4
));
1751 /*********************************************************************
1752 * WINSPOOL_GetPrinter_5
1754 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1756 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1757 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1760 DWORD size
, left
= cbBuf
;
1761 BOOL space
= (cbBuf
> 0);
1766 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1768 if(space
&& size
<= left
) {
1769 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1776 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1778 if(space
&& size
<= left
) {
1779 pi5
->pPortName
= (LPWSTR
)ptr
;
1787 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1788 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1790 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1794 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1795 memset(pi5
, 0, sizeof(*pi5
));
1800 /*****************************************************************************
1801 * WINSPOOL_GetPrinter
1803 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1804 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1805 * just a collection of pointers to strings.
1807 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1808 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1811 DWORD size
, needed
= 0;
1813 HKEY hkeyPrinter
, hkeyPrinters
;
1816 TRACE("(%p,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1818 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
1820 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1822 ERR("Can't create Printers key\n");
1825 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
) != ERROR_SUCCESS
)
1827 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
1828 RegCloseKey(hkeyPrinters
);
1829 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1836 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
1838 size
= sizeof(PRINTER_INFO_2W
);
1840 ptr
= pPrinter
+ size
;
1842 memset(pPrinter
, 0, size
);
1847 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
1855 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
1857 size
= sizeof(PRINTER_INFO_4W
);
1859 ptr
= pPrinter
+ size
;
1861 memset(pPrinter
, 0, size
);
1866 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
1875 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
1877 size
= sizeof(PRINTER_INFO_5W
);
1879 ptr
= pPrinter
+ size
;
1881 memset(pPrinter
, 0, size
);
1887 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
1894 FIXME("Unimplemented level %ld\n", Level
);
1895 SetLastError(ERROR_INVALID_LEVEL
);
1896 RegCloseKey(hkeyPrinters
);
1897 RegCloseKey(hkeyPrinter
);
1901 RegCloseKey(hkeyPrinter
);
1902 RegCloseKey(hkeyPrinters
);
1904 TRACE("returning %d needed = %ld\n", ret
, needed
);
1905 if(pcbNeeded
) *pcbNeeded
= needed
;
1907 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1911 /*****************************************************************************
1912 * GetPrinterW [WINSPOOL.@]
1914 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1915 DWORD cbBuf
, LPDWORD pcbNeeded
)
1917 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1921 /*****************************************************************************
1922 * GetPrinterA [WINSPOOL.@]
1924 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1925 DWORD cbBuf
, LPDWORD pcbNeeded
)
1927 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1931 /*****************************************************************************
1932 * WINSPOOL_EnumPrinters
1934 * Implementation of EnumPrintersA|W
1936 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
1937 DWORD dwLevel
, LPBYTE lpbPrinters
,
1938 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1939 LPDWORD lpdwReturned
, BOOL unicode
)
1942 HKEY hkeyPrinters
, hkeyPrinter
;
1943 WCHAR PrinterName
[255];
1944 DWORD needed
= 0, number
= 0;
1945 DWORD used
, i
, left
;
1949 memset(lpbPrinters
, 0, cbBuf
);
1955 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1956 if(dwType
== PRINTER_ENUM_DEFAULT
)
1959 if (dwType
& PRINTER_ENUM_CONNECTIONS
) {
1960 FIXME("We dont handle PRINTER_ENUM_CONNECTIONS\n");
1961 dwType
&= ~PRINTER_ENUM_CONNECTIONS
; /* we dont handle that */
1962 dwType
|= PRINTER_ENUM_LOCAL
;
1965 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
1966 FIXME("dwType = %08lx\n", dwType
);
1967 SetLastError(ERROR_INVALID_FLAGS
);
1971 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1973 ERR("Can't create Printers key\n");
1977 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
1978 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
1979 RegCloseKey(hkeyPrinters
);
1980 ERR("Can't query Printers key\n");
1983 TRACE("Found %ld printers\n", number
);
1987 RegCloseKey(hkeyPrinters
);
1989 *lpdwReturned
= number
;
1993 used
= number
* sizeof(PRINTER_INFO_2W
);
1996 used
= number
* sizeof(PRINTER_INFO_4W
);
1999 used
= number
* sizeof(PRINTER_INFO_5W
);
2003 SetLastError(ERROR_INVALID_LEVEL
);
2004 RegCloseKey(hkeyPrinters
);
2007 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
2009 for(i
= 0; i
< number
; i
++) {
2010 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
2012 ERR("Can't enum key number %ld\n", i
);
2013 RegCloseKey(hkeyPrinters
);
2016 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
2017 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
2019 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
2020 RegCloseKey(hkeyPrinters
);
2025 buf
= lpbPrinters
+ used
;
2026 left
= cbBuf
- used
;
2034 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
2035 left
, &needed
, unicode
);
2037 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
2040 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
2041 left
, &needed
, unicode
);
2043 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
2046 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
2047 left
, &needed
, unicode
);
2049 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
2052 ERR("Shouldn't be here!\n");
2053 RegCloseKey(hkeyPrinter
);
2054 RegCloseKey(hkeyPrinters
);
2057 RegCloseKey(hkeyPrinter
);
2059 RegCloseKey(hkeyPrinters
);
2066 memset(lpbPrinters
, 0, cbBuf
);
2067 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2071 *lpdwReturned
= number
;
2072 SetLastError(ERROR_SUCCESS
);
2077 /******************************************************************
2078 * EnumPrintersW [WINSPOOL.@]
2080 * Enumerates the available printers, print servers and print
2081 * providers, depending on the specified flags, name and level.
2085 * If level is set to 1:
2086 * Not implemented yet!
2087 * Returns TRUE with an empty list.
2089 * If level is set to 2:
2090 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2091 * Returns an array of PRINTER_INFO_2 data structures in the
2092 * lpbPrinters buffer. Note that according to MSDN also an
2093 * OpenPrinter should be performed on every remote printer.
2095 * If level is set to 4 (officially WinNT only):
2096 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2097 * Fast: Only the registry is queried to retrieve printer names,
2098 * no connection to the driver is made.
2099 * Returns an array of PRINTER_INFO_4 data structures in the
2100 * lpbPrinters buffer.
2102 * If level is set to 5 (officially WinNT4/Win9x only):
2103 * Fast: Only the registry is queried to retrieve printer names,
2104 * no connection to the driver is made.
2105 * Returns an array of PRINTER_INFO_5 data structures in the
2106 * lpbPrinters buffer.
2108 * If level set to 3 or 6+:
2109 * returns zero (failure!)
2111 * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
2115 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
2116 * - Only levels 2, 4 and 5 are implemented at the moment.
2117 * - 16-bit printer drivers are not enumerated.
2118 * - Returned amount of bytes used/needed does not match the real Windoze
2119 * implementation (as in this implementation, all strings are part
2120 * of the buffer, whereas Win32 keeps them somewhere else)
2121 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
2124 * - In a regular Wine installation, no registry settings for printers
2125 * exist, which makes this function return an empty list.
2127 BOOL WINAPI
EnumPrintersW(
2128 DWORD dwType
, /* [in] Types of print objects to enumerate */
2129 LPWSTR lpszName
, /* [in] name of objects to enumerate */
2130 DWORD dwLevel
, /* [in] type of printer info structure */
2131 LPBYTE lpbPrinters
, /* [out] buffer which receives info */
2132 DWORD cbBuf
, /* [in] max size of buffer in bytes */
2133 LPDWORD lpdwNeeded
, /* [out] pointer to var: # bytes used/needed */
2134 LPDWORD lpdwReturned
/* [out] number of entries returned */
2137 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
2138 lpdwNeeded
, lpdwReturned
, TRUE
);
2141 /******************************************************************
2142 * EnumPrintersA [WINSPOOL.@]
2145 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
2146 DWORD dwLevel
, LPBYTE lpbPrinters
,
2147 DWORD cbBuf
, LPDWORD lpdwNeeded
,
2148 LPDWORD lpdwReturned
)
2151 LPWSTR lpszNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpszName
);
2153 ret
= WINSPOOL_EnumPrinters(dwType
, lpszNameW
, dwLevel
, lpbPrinters
, cbBuf
,
2154 lpdwNeeded
, lpdwReturned
, FALSE
);
2155 HeapFree(GetProcessHeap(),0,lpszNameW
);
2159 /*****************************************************************************
2160 * WINSPOOL_GetDriverInfoFromReg [internal]
2162 * Enters the information from the registry into the DRIVER_INFO struct
2165 * zero if the printer driver does not exist in the registry
2166 * (only if Level > 1) otherwise nonzero
2168 static BOOL
WINSPOOL_GetDriverInfoFromReg(
2171 LPWSTR pEnvironment
,
2173 LPBYTE ptr
, /* DRIVER_INFO */
2174 LPBYTE pDriverStrings
, /* strings buffer */
2175 DWORD cbBuf
, /* size of string buffer */
2176 LPDWORD pcbNeeded
, /* space needed for str. */
2177 BOOL unicode
) /* type of strings */
2178 { DWORD dw
, size
, tmp
, type
;
2180 LPBYTE strPtr
= pDriverStrings
;
2182 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
2183 debugstr_w(DriverName
), debugstr_w(pEnvironment
),
2184 Level
, ptr
, pDriverStrings
, cbBuf
, unicode
);
2187 *pcbNeeded
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
2188 if (*pcbNeeded
<= cbBuf
)
2189 strcpyW((LPWSTR
)strPtr
, DriverName
);
2191 *pcbNeeded
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0,
2193 if(*pcbNeeded
<= cbBuf
)
2194 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, strPtr
, *pcbNeeded
,
2199 ((PDRIVER_INFO_1W
) ptr
)->pName
= (LPWSTR
) strPtr
;
2203 ((PDRIVER_INFO_3W
) ptr
)->pName
= (LPWSTR
) strPtr
;
2204 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2207 if(!DriverName
[0] || RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
) != ERROR_SUCCESS
) {
2208 ERR("Can't find driver '%s' in registry\n", debugstr_w(DriverName
));
2209 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
2214 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
, &size
) !=
2216 WARN("Can't get Version\n");
2218 ((PDRIVER_INFO_3A
) ptr
)->cVersion
= dw
;
2221 pEnvironment
= DefaultEnvironmentW
;
2223 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
2225 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
2228 if(*pcbNeeded
<= cbBuf
) {
2230 strcpyW((LPWSTR
)strPtr
, pEnvironment
);
2232 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, strPtr
, size
,
2235 ((PDRIVER_INFO_3W
) ptr
)->pEnvironment
= (LPWSTR
)strPtr
;
2236 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2239 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, 0, &size
,
2242 if(*pcbNeeded
<= cbBuf
)
2243 WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, size
, &tmp
,
2246 ((PDRIVER_INFO_3W
) ptr
)->pDriverPath
= (LPWSTR
)strPtr
;
2247 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2250 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, 0, &size
,
2253 if(*pcbNeeded
<= cbBuf
)
2254 WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, size
,
2257 ((PDRIVER_INFO_3W
) ptr
)->pDataFile
= (LPWSTR
)strPtr
;
2258 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2261 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
2262 0, &size
, unicode
)) {
2264 if(*pcbNeeded
<= cbBuf
)
2265 WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
2266 size
, &tmp
, unicode
);
2268 ((PDRIVER_INFO_3W
) ptr
)->pConfigFile
= (LPWSTR
)strPtr
;
2269 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2273 RegCloseKey(hkeyDriver
);
2274 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2278 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
, 0, &size
,
2281 if(*pcbNeeded
<= cbBuf
)
2282 WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
,
2283 size
, &tmp
, unicode
);
2285 ((PDRIVER_INFO_3W
) ptr
)->pHelpFile
= (LPWSTR
)strPtr
;
2286 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2289 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
, 0,
2292 if(*pcbNeeded
<= cbBuf
)
2293 WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
,
2294 size
, &tmp
, unicode
);
2296 ((PDRIVER_INFO_3W
) ptr
)->pDependentFiles
= (LPWSTR
)strPtr
;
2297 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2300 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
, 0, &size
,
2303 if(*pcbNeeded
<= cbBuf
)
2304 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
2305 size
, &tmp
, unicode
);
2307 ((PDRIVER_INFO_3W
) ptr
)->pMonitorName
= (LPWSTR
)strPtr
;
2308 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2311 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, strPtr
, 0, &size
,
2314 if(*pcbNeeded
<= cbBuf
)
2315 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
2316 size
, &tmp
, unicode
);
2318 ((PDRIVER_INFO_3W
) ptr
)->pDefaultDataType
= (LPWSTR
)strPtr
;
2319 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2322 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2323 RegCloseKey(hkeyDriver
);
2327 /*****************************************************************************
2328 * WINSPOOL_GetPrinterDriver
2330 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
2331 DWORD Level
, LPBYTE pDriverInfo
,
2332 DWORD cbBuf
, LPDWORD pcbNeeded
,
2336 WCHAR DriverName
[100];
2337 DWORD ret
, type
, size
, needed
= 0;
2339 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDrivers
;
2341 TRACE("(%p,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
2342 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
2344 ZeroMemory(pDriverInfo
, cbBuf
);
2346 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
2348 if(Level
< 1 || Level
> 3) {
2349 SetLastError(ERROR_INVALID_LEVEL
);
2352 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
2354 ERR("Can't create Printers key\n");
2357 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
)
2359 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
2360 RegCloseKey(hkeyPrinters
);
2361 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
2364 size
= sizeof(DriverName
);
2366 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
2367 (LPBYTE
)DriverName
, &size
);
2368 RegCloseKey(hkeyPrinter
);
2369 RegCloseKey(hkeyPrinters
);
2370 if(ret
!= ERROR_SUCCESS
) {
2371 ERR("Can't get DriverName for printer %s\n", debugstr_w(name
));
2375 hkeyDrivers
= WINSPOOL_OpenDriverReg( pEnvironment
, TRUE
);
2377 ERR("Can't create Drivers key\n");
2383 size
= sizeof(DRIVER_INFO_1W
);
2386 size
= sizeof(DRIVER_INFO_2W
);
2389 size
= sizeof(DRIVER_INFO_3W
);
2392 ERR("Invalid level\n");
2397 ptr
= pDriverInfo
+ size
;
2399 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverName
,
2400 pEnvironment
, Level
, pDriverInfo
,
2401 (cbBuf
< size
) ? NULL
: ptr
,
2402 (cbBuf
< size
) ? 0 : cbBuf
- size
,
2403 &needed
, unicode
)) {
2404 RegCloseKey(hkeyDrivers
);
2408 RegCloseKey(hkeyDrivers
);
2410 if(pcbNeeded
) *pcbNeeded
= size
+ needed
;
2411 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2412 if(cbBuf
>= needed
) return TRUE
;
2413 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2417 /*****************************************************************************
2418 * GetPrinterDriverA [WINSPOOL.@]
2420 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
2421 DWORD Level
, LPBYTE pDriverInfo
,
2422 DWORD cbBuf
, LPDWORD pcbNeeded
)
2425 LPWSTR pEnvW
= HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment
);
2426 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pEnvW
, Level
, pDriverInfo
,
2427 cbBuf
, pcbNeeded
, FALSE
);
2428 HeapFree(GetProcessHeap(),0,pEnvW
);
2431 /*****************************************************************************
2432 * GetPrinterDriverW [WINSPOOL.@]
2434 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
2435 DWORD Level
, LPBYTE pDriverInfo
,
2436 DWORD cbBuf
, LPDWORD pcbNeeded
)
2438 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
2439 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
2442 /*****************************************************************************
2443 * GetPrinterDriverDirectoryW [WINSPOOL.@]
2445 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
2446 DWORD Level
, LPBYTE pDriverDirectory
,
2447 DWORD cbBuf
, LPDWORD pcbNeeded
)
2451 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", debugstr_w(pName
),
2452 debugstr_w(pEnvironment
), Level
, pDriverDirectory
, cbBuf
, pcbNeeded
);
2454 FIXME("pName = `%s' - unsupported\n", debugstr_w(pName
));
2455 SetLastError(ERROR_INVALID_PARAMETER
);
2458 if(pEnvironment
!= NULL
) {
2459 FIXME("pEnvironment = `%s' - unsupported\n", debugstr_w(pEnvironment
));
2460 SetLastError(ERROR_INVALID_ENVIRONMENT
);
2463 if(Level
!= 1) /* win95 ignores this so we just carry on */
2464 WARN("Level = %ld - assuming 1\n", Level
);
2466 /* FIXME should read from registry */
2467 needed
= GetSystemDirectoryW( (LPWSTR
)pDriverDirectory
, cbBuf
/sizeof(WCHAR
));
2468 /* GetSystemDirectoryW returns number of TCHAR without '\0'
2472 needed
*=sizeof(WCHAR
);
2475 *pcbNeeded
= needed
;
2476 TRACE("required <%08lx>\n", *pcbNeeded
);
2477 if(needed
> cbBuf
) {
2478 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2485 /*****************************************************************************
2486 * GetPrinterDriverDirectoryA [WINSPOOL.@]
2488 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
2489 DWORD Level
, LPBYTE pDriverDirectory
,
2490 DWORD cbBuf
, LPDWORD pcbNeeded
)
2492 UNICODE_STRING nameW
, environmentW
;
2495 INT len
= cbBuf
* sizeof(WCHAR
)/sizeof(CHAR
);
2496 WCHAR
*driverDirectoryW
= NULL
;
2498 if (len
) driverDirectoryW
= HeapAlloc( GetProcessHeap(), 0, len
);
2500 if(pName
) RtlCreateUnicodeStringFromAsciiz(&nameW
, pName
);
2501 else nameW
.Buffer
= NULL
;
2502 if(pEnvironment
) RtlCreateUnicodeStringFromAsciiz(&environmentW
, pEnvironment
);
2503 else environmentW
.Buffer
= NULL
;
2505 ret
= GetPrinterDriverDirectoryW( nameW
.Buffer
, environmentW
.Buffer
, Level
,
2506 (LPBYTE
)driverDirectoryW
, len
, &pcbNeededW
);
2509 needed
= 1 + WideCharToMultiByte( CP_ACP
, 0, driverDirectoryW
, -1,
2510 pDriverDirectory
, cbBuf
, NULL
, NULL
);
2512 *pcbNeeded
= needed
;
2513 ret
= (needed
<= cbBuf
) ? TRUE
: FALSE
;
2515 if(pcbNeeded
) *pcbNeeded
= pcbNeededW
* sizeof(CHAR
)/sizeof(WCHAR
);
2517 TRACE("provided<%ld> required <%ld>\n", cbBuf
, *pcbNeeded
);
2519 if(driverDirectoryW
)
2520 HeapFree( GetProcessHeap(), 0, driverDirectoryW
);
2521 RtlFreeUnicodeString(&environmentW
);
2522 RtlFreeUnicodeString(&nameW
);
2527 /*****************************************************************************
2528 * AddPrinterDriverA [WINSPOOL.@]
2530 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
2533 HKEY hkeyDrivers
, hkeyName
;
2535 TRACE("(%s,%ld,%p)\n",debugstr_a(pName
),level
,pDriverInfo
);
2537 if(level
!= 2 && level
!= 3) {
2538 SetLastError(ERROR_INVALID_LEVEL
);
2542 FIXME("pName= %s - unsupported\n", debugstr_a(pName
));
2543 SetLastError(ERROR_INVALID_PARAMETER
);
2547 WARN("pDriverInfo == NULL\n");
2548 SetLastError(ERROR_INVALID_PARAMETER
);
2553 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
2555 memset(&di3
, 0, sizeof(di3
));
2556 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
2559 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
2561 SetLastError(ERROR_INVALID_PARAMETER
);
2564 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
2565 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
2566 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
2567 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
2569 hkeyDrivers
= WINSPOOL_OpenDriverReg(di3
.pEnvironment
, FALSE
);
2572 ERR("Can't create Drivers key\n");
2576 if(level
== 2) { /* apparently can't overwrite with level2 */
2577 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2578 RegCloseKey(hkeyName
);
2579 RegCloseKey(hkeyDrivers
);
2580 WARN("Trying to create existing printer driver %s\n", debugstr_a(di3
.pName
));
2581 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2585 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2586 RegCloseKey(hkeyDrivers
);
2587 ERR("Can't create Name key\n");
2590 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2592 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2593 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2594 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2596 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2597 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2598 di3
.pDependentFiles
, 0);
2599 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2600 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2601 RegCloseKey(hkeyName
);
2602 RegCloseKey(hkeyDrivers
);
2606 /*****************************************************************************
2607 * AddPrinterDriverW [WINSPOOL.@]
2609 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2612 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2618 /*****************************************************************************
2619 * PrinterProperties [WINSPOOL.@]
2621 * Displays a dialog to set the properties of the printer.
2624 * nonzero on success or zero on failure
2627 * implemented as stub only
2629 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* [in] handle to parent window */
2630 HANDLE hPrinter
/* [in] handle to printer object */
2632 FIXME("(%p,%p): stub\n", hWnd
, hPrinter
);
2633 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2637 /*****************************************************************************
2638 * EnumJobsA [WINSPOOL.@]
2641 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2642 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2645 FIXME("(%p,first=%ld,no=%ld,level=%ld,job=%p,cb=%ld,%p,%p), stub!\n",
2646 hPrinter
, FirstJob
, NoJobs
, Level
, pJob
, cbBuf
, pcbNeeded
, pcReturned
2648 if(pcbNeeded
) *pcbNeeded
= 0;
2649 if(pcReturned
) *pcReturned
= 0;
2654 /*****************************************************************************
2655 * EnumJobsW [WINSPOOL.@]
2658 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2659 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2662 FIXME("(%p,first=%ld,no=%ld,level=%ld,job=%p,cb=%ld,%p,%p), stub!\n",
2663 hPrinter
, FirstJob
, NoJobs
, Level
, pJob
, cbBuf
, pcbNeeded
, pcReturned
2665 if(pcbNeeded
) *pcbNeeded
= 0;
2666 if(pcReturned
) *pcReturned
= 0;
2670 /*****************************************************************************
2671 * WINSPOOL_EnumPrinterDrivers [internal]
2673 * Delivers information about all printer drivers installed on the
2674 * localhost or a given server
2677 * nonzero on success or zero on failure. If the buffer for the returned
2678 * information is too small the function will return an error
2681 * - only implemented for localhost, foreign hosts will return an error
2683 static BOOL
WINSPOOL_EnumPrinterDrivers(LPWSTR pName
, LPWSTR pEnvironment
,
2684 DWORD Level
, LPBYTE pDriverInfo
,
2685 DWORD cbBuf
, LPDWORD pcbNeeded
,
2686 LPDWORD pcReturned
, BOOL unicode
)
2689 DWORD i
, needed
, number
= 0, size
= 0;
2690 WCHAR DriverNameW
[255];
2693 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2694 debugstr_w(pName
), debugstr_w(pEnvironment
),
2695 Level
, pDriverInfo
, cbBuf
, unicode
);
2697 /* check for local drivers */
2699 ERR("remote drivers unsupported! Current remote host is %s\n",
2704 /* check input parameter */
2705 if((Level
< 1) || (Level
> 3)) {
2706 ERR("unsupported level %ld \n", Level
);
2710 /* initialize return values */
2712 memset( pDriverInfo
, 0, cbBuf
);
2716 hkeyDrivers
= WINSPOOL_OpenDriverReg(pEnvironment
, TRUE
);
2718 ERR("Can't open Drivers key\n");
2722 if(RegQueryInfoKeyA(hkeyDrivers
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2723 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2724 RegCloseKey(hkeyDrivers
);
2725 ERR("Can't query Drivers key\n");
2728 TRACE("Found %ld Drivers\n", number
);
2730 /* get size of single struct
2731 * unicode and ascii structure have the same size
2735 size
= sizeof(DRIVER_INFO_1A
);
2738 size
= sizeof(DRIVER_INFO_2A
);
2741 size
= sizeof(DRIVER_INFO_3A
);
2745 /* calculate required buffer size */
2746 *pcbNeeded
= size
* number
;
2748 for( i
= 0, ptr
= (pDriverInfo
&& (cbBuf
>= size
)) ? pDriverInfo
: NULL
;
2750 i
++, ptr
= (ptr
&& (cbBuf
>= size
* i
)) ? ptr
+ size
: NULL
) {
2751 if(RegEnumKeyW(hkeyDrivers
, i
, DriverNameW
, sizeof(DriverNameW
))
2753 ERR("Can't enum key number %ld\n", i
);
2754 RegCloseKey(hkeyDrivers
);
2757 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverNameW
,
2758 pEnvironment
, Level
, ptr
,
2759 (cbBuf
< *pcbNeeded
) ? NULL
: pDriverInfo
+ *pcbNeeded
,
2760 (cbBuf
< *pcbNeeded
) ? 0 : cbBuf
- *pcbNeeded
,
2761 &needed
, unicode
)) {
2762 RegCloseKey(hkeyDrivers
);
2765 (*pcbNeeded
) += needed
;
2768 RegCloseKey(hkeyDrivers
);
2770 if(cbBuf
< *pcbNeeded
){
2771 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2778 /*****************************************************************************
2779 * EnumPrinterDriversW [WINSPOOL.@]
2781 * see function EnumPrinterDrivers for RETURNS, BUGS
2783 BOOL WINAPI
EnumPrinterDriversW(LPWSTR pName
, LPWSTR pEnvironment
, DWORD Level
,
2784 LPBYTE pDriverInfo
, DWORD cbBuf
,
2785 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2787 return WINSPOOL_EnumPrinterDrivers(pName
, pEnvironment
, Level
, pDriverInfo
,
2788 cbBuf
, pcbNeeded
, pcReturned
, TRUE
);
2791 /*****************************************************************************
2792 * EnumPrinterDriversA [WINSPOOL.@]
2794 * see function EnumPrinterDrivers for RETURNS, BUGS
2796 BOOL WINAPI
EnumPrinterDriversA(LPSTR pName
, LPSTR pEnvironment
, DWORD Level
,
2797 LPBYTE pDriverInfo
, DWORD cbBuf
,
2798 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2800 WCHAR
*pNameW
= NULL
, *pEnvironmentW
= NULL
;
2803 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
2805 pEnvironmentW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment
);
2807 ret
= WINSPOOL_EnumPrinterDrivers(pNameW
, pEnvironmentW
, Level
, pDriverInfo
,
2808 cbBuf
, pcbNeeded
, pcReturned
, FALSE
);
2810 HeapFree(GetProcessHeap(), 0, pNameW
);
2812 HeapFree(GetProcessHeap(), 0, pEnvironmentW
);
2818 /******************************************************************************
2819 * EnumPortsA (WINSPOOL.@)
2821 BOOL WINAPI
EnumPortsA(LPSTR name
,DWORD level
,LPBYTE ports
,DWORD bufsize
,
2822 LPDWORD bufneeded
,LPDWORD bufreturned
)
2824 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name
,level
,ports
,bufsize
,bufneeded
,bufreturned
);
2828 /******************************************************************************
2829 * GetDefaultPrinterA (WINSPOOL.@)
2831 * Based on PRINTDLG_GetDefaultPrinterName in dlls/commdlg/printdlg.c
2833 BOOL WINAPI
GetDefaultPrinterA(LPSTR name
, LPDWORD namesize
)
2839 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
2843 if (!GetProfileStringA ("windows", "device", "", name
, *namesize
))
2845 SetLastError (ERROR_FILE_NOT_FOUND
);
2849 if ((ptr
= strchr (name
, ',')) == NULL
)
2851 SetLastError (ERROR_FILE_NOT_FOUND
);
2856 *namesize
= strlen (name
) + 1;
2861 /******************************************************************************
2862 * GetDefaultPrinterW (WINSPOOL.@)
2864 BOOL WINAPI
GetDefaultPrinterW(LPWSTR name
, LPDWORD namesize
)
2871 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
2875 buf
= HeapAlloc (GetProcessHeap (), 0, *namesize
);
2876 ret
= GetDefaultPrinterA (buf
, namesize
);
2879 DWORD len
= MultiByteToWideChar (CP_ACP
, 0, buf
, -1, name
, *namesize
);
2882 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
2885 else *namesize
= len
;
2888 HeapFree (GetProcessHeap (), 0, buf
);
2893 /******************************************************************************
2894 * SetPrinterDataExA (WINSPOOL.@)
2896 DWORD WINAPI
SetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2897 LPSTR pValueName
, DWORD Type
,
2898 LPBYTE pData
, DWORD cbData
)
2900 HKEY hkeyPrinter
, hkeySubkey
;
2903 TRACE("(%p, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_a(pKeyName
),
2904 debugstr_a(pValueName
), Type
, pData
, cbData
);
2906 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2910 if((ret
= RegCreateKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2912 ERR("Can't create subkey %s\n", debugstr_a(pKeyName
));
2913 RegCloseKey(hkeyPrinter
);
2916 ret
= RegSetValueExA(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2917 RegCloseKey(hkeySubkey
);
2918 RegCloseKey(hkeyPrinter
);
2922 /******************************************************************************
2923 * SetPrinterDataExW (WINSPOOL.@)
2925 DWORD WINAPI
SetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
2926 LPWSTR pValueName
, DWORD Type
,
2927 LPBYTE pData
, DWORD cbData
)
2929 HKEY hkeyPrinter
, hkeySubkey
;
2932 TRACE("(%p, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_w(pKeyName
),
2933 debugstr_w(pValueName
), Type
, pData
, cbData
);
2935 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2939 if((ret
= RegCreateKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2941 ERR("Can't create subkey %s\n", debugstr_w(pKeyName
));
2942 RegCloseKey(hkeyPrinter
);
2945 ret
= RegSetValueExW(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2946 RegCloseKey(hkeySubkey
);
2947 RegCloseKey(hkeyPrinter
);
2951 /******************************************************************************
2952 * SetPrinterDataA (WINSPOOL.@)
2954 DWORD WINAPI
SetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, DWORD Type
,
2955 LPBYTE pData
, DWORD cbData
)
2957 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
,
2961 /******************************************************************************
2962 * SetPrinterDataW (WINSPOOL.@)
2964 DWORD WINAPI
SetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, DWORD Type
,
2965 LPBYTE pData
, DWORD cbData
)
2967 return SetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, Type
,
2971 /******************************************************************************
2972 * GetPrinterDataExA (WINSPOOL.@)
2974 DWORD WINAPI
GetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2975 LPSTR pValueName
, LPDWORD pType
,
2976 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2978 HKEY hkeyPrinter
, hkeySubkey
;
2981 TRACE("(%p, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
2982 debugstr_a(pKeyName
), debugstr_a(pValueName
), pType
, pData
, nSize
,
2985 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2989 if((ret
= RegOpenKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2991 WARN("Can't open subkey %s\n", debugstr_a(pKeyName
));
2992 RegCloseKey(hkeyPrinter
);
2996 ret
= RegQueryValueExA(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
2997 RegCloseKey(hkeySubkey
);
2998 RegCloseKey(hkeyPrinter
);
3002 /******************************************************************************
3003 * GetPrinterDataExW (WINSPOOL.@)
3005 DWORD WINAPI
GetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
3006 LPWSTR pValueName
, LPDWORD pType
,
3007 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3009 HKEY hkeyPrinter
, hkeySubkey
;
3012 TRACE("(%p, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
3013 debugstr_w(pKeyName
), debugstr_w(pValueName
), pType
, pData
, nSize
,
3016 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
3020 if((ret
= RegOpenKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
3022 WARN("Can't open subkey %s\n", debugstr_w(pKeyName
));
3023 RegCloseKey(hkeyPrinter
);
3027 ret
= RegQueryValueExW(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
3028 RegCloseKey(hkeySubkey
);
3029 RegCloseKey(hkeyPrinter
);
3033 /******************************************************************************
3034 * GetPrinterDataA (WINSPOOL.@)
3036 DWORD WINAPI
GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
,
3037 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3039 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
,
3040 pData
, nSize
, pcbNeeded
);
3043 /******************************************************************************
3044 * GetPrinterDataW (WINSPOOL.@)
3046 DWORD WINAPI
GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
,
3047 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3049 return GetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, pType
,
3050 pData
, nSize
, pcbNeeded
);
3053 /*******************************************************************************
3054 * EnumPrinterDataExW [WINSPOOL.@]
3056 DWORD WINAPI
EnumPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
,
3057 LPBYTE pEnumValues
, DWORD cbEnumValues
,
3058 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
3060 HKEY hkPrinter
, hkSubKey
;
3061 DWORD r
, ret
, dwIndex
, cValues
, cbMaxValueNameLen
,
3062 cbValueNameLen
, cbMaxValueLen
, cbValueLen
,
3067 PPRINTER_ENUM_VALUESW ppev
;
3069 TRACE ("%p %s\n", hPrinter
, debugstr_w (pKeyName
));
3071 if (pKeyName
== NULL
|| *pKeyName
== 0)
3072 return ERROR_INVALID_PARAMETER
;
3074 ret
= WINSPOOL_GetOpenedPrinterRegKey (hPrinter
, &hkPrinter
);
3075 if (ret
!= ERROR_SUCCESS
)
3077 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%p) returned %li\n",
3082 ret
= RegOpenKeyExW (hkPrinter
, pKeyName
, 0, KEY_READ
, &hkSubKey
);
3083 if (ret
!= ERROR_SUCCESS
)
3085 r
= RegCloseKey (hkPrinter
);
3086 if (r
!= ERROR_SUCCESS
)
3087 WARN ("RegCloseKey returned %li\n", r
);
3088 TRACE ("RegOpenKeyExW (%p, %s) returned %li\n", hPrinter
,
3089 debugstr_w (pKeyName
), ret
);
3093 ret
= RegCloseKey (hkPrinter
);
3094 if (ret
!= ERROR_SUCCESS
)
3096 ERR ("RegCloseKey returned %li\n", ret
);
3097 r
= RegCloseKey (hkSubKey
);
3098 if (r
!= ERROR_SUCCESS
)
3099 WARN ("RegCloseKey returned %li\n", r
);
3103 ret
= RegQueryInfoKeyW (hkSubKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
3104 &cValues
, &cbMaxValueNameLen
, &cbMaxValueLen
, NULL
, NULL
);
3105 if (ret
!= ERROR_SUCCESS
)
3107 r
= RegCloseKey (hkSubKey
);
3108 if (r
!= ERROR_SUCCESS
)
3109 WARN ("RegCloseKey returned %li\n", r
);
3110 TRACE ("RegQueryInfoKeyW (%p) returned %li\n", hkSubKey
, ret
);
3114 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
3115 "cbMaxValueLen = %li\n", cValues
, cbMaxValueNameLen
, cbMaxValueLen
);
3117 if (cValues
== 0) /* empty key */
3119 r
= RegCloseKey (hkSubKey
);
3120 if (r
!= ERROR_SUCCESS
)
3121 WARN ("RegCloseKey returned %li\n", r
);
3122 *pcbEnumValues
= *pnEnumValues
= 0;
3123 return ERROR_SUCCESS
;
3126 ++cbMaxValueNameLen
; /* allow for trailing '\0' */
3128 hHeap
= GetProcessHeap ();
3131 ERR ("GetProcessHeap failed\n");
3132 r
= RegCloseKey (hkSubKey
);
3133 if (r
!= ERROR_SUCCESS
)
3134 WARN ("RegCloseKey returned %li\n", r
);
3135 return ERROR_OUTOFMEMORY
;
3138 lpValueName
= HeapAlloc (hHeap
, 0, cbMaxValueNameLen
* sizeof (WCHAR
));
3139 if (lpValueName
== NULL
)
3141 ERR ("Failed to allocate %li bytes from process heap\n",
3142 cbMaxValueNameLen
* sizeof (WCHAR
));
3143 r
= RegCloseKey (hkSubKey
);
3144 if (r
!= ERROR_SUCCESS
)
3145 WARN ("RegCloseKey returned %li\n", r
);
3146 return ERROR_OUTOFMEMORY
;
3149 lpValue
= HeapAlloc (hHeap
, 0, cbMaxValueLen
);
3150 if (lpValue
== NULL
)
3152 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen
);
3153 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3154 WARN ("HeapFree failed with code %li\n", GetLastError ());
3155 r
= RegCloseKey (hkSubKey
);
3156 if (r
!= ERROR_SUCCESS
)
3157 WARN ("RegCloseKey returned %li\n", r
);
3158 return ERROR_OUTOFMEMORY
;
3161 TRACE ("pass 1: calculating buffer required for all names and values\n");
3163 cbBufSize
= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
3165 TRACE ("%li bytes required for %li headers\n", cbBufSize
, cValues
);
3167 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
3169 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
3170 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
3171 NULL
, NULL
, lpValue
, &cbValueLen
);
3172 if (ret
!= ERROR_SUCCESS
)
3174 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3175 WARN ("HeapFree failed with code %li\n", GetLastError ());
3176 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3177 WARN ("HeapFree failed with code %li\n", GetLastError ());
3178 r
= RegCloseKey (hkSubKey
);
3179 if (r
!= ERROR_SUCCESS
)
3180 WARN ("RegCloseKey returned %li\n", r
);
3181 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
3185 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
3186 debugstr_w (lpValueName
), dwIndex
,
3187 (cbValueNameLen
+ 1) * sizeof (WCHAR
), cbValueLen
);
3189 cbBufSize
+= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
3190 cbBufSize
+= cbValueLen
;
3193 TRACE ("%li bytes required for all %li values\n", cbBufSize
, cValues
);
3195 *pcbEnumValues
= cbBufSize
;
3196 *pnEnumValues
= cValues
;
3198 if (cbEnumValues
< cbBufSize
) /* buffer too small */
3200 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3201 WARN ("HeapFree failed with code %li\n", GetLastError ());
3202 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3203 WARN ("HeapFree failed with code %li\n", GetLastError ());
3204 r
= RegCloseKey (hkSubKey
);
3205 if (r
!= ERROR_SUCCESS
)
3206 WARN ("RegCloseKey returned %li\n", r
);
3207 TRACE ("%li byte buffer is not large enough\n", cbEnumValues
);
3208 return ERROR_MORE_DATA
;
3211 TRACE ("pass 2: copying all names and values to buffer\n");
3213 ppev
= (PPRINTER_ENUM_VALUESW
) pEnumValues
; /* array of structs */
3214 pEnumValues
+= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
3216 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
3218 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
3219 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
3220 NULL
, &dwType
, lpValue
, &cbValueLen
);
3221 if (ret
!= ERROR_SUCCESS
)
3223 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3224 WARN ("HeapFree failed with code %li\n", GetLastError ());
3225 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3226 WARN ("HeapFree failed with code %li\n", GetLastError ());
3227 r
= RegCloseKey (hkSubKey
);
3228 if (r
!= ERROR_SUCCESS
)
3229 WARN ("RegCloseKey returned %li\n", r
);
3230 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
3234 cbValueNameLen
= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
3235 memcpy (pEnumValues
, lpValueName
, cbValueNameLen
);
3236 ppev
[dwIndex
].pValueName
= (LPWSTR
) pEnumValues
;
3237 pEnumValues
+= cbValueNameLen
;
3239 /* return # of *bytes* (including trailing \0), not # of chars */
3240 ppev
[dwIndex
].cbValueName
= cbValueNameLen
;
3242 ppev
[dwIndex
].dwType
= dwType
;
3244 memcpy (pEnumValues
, lpValue
, cbValueLen
);
3245 ppev
[dwIndex
].pData
= pEnumValues
;
3246 pEnumValues
+= cbValueLen
;
3248 ppev
[dwIndex
].cbData
= cbValueLen
;
3250 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
3251 debugstr_w (lpValueName
), dwIndex
, cbValueNameLen
, cbValueLen
);
3254 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3256 ret
= GetLastError ();
3257 ERR ("HeapFree failed with code %li\n", ret
);
3258 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3259 WARN ("HeapFree failed with code %li\n", GetLastError ());
3260 r
= RegCloseKey (hkSubKey
);
3261 if (r
!= ERROR_SUCCESS
)
3262 WARN ("RegCloseKey returned %li\n", r
);
3266 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3268 ret
= GetLastError ();
3269 ERR ("HeapFree failed with code %li\n", ret
);
3270 r
= RegCloseKey (hkSubKey
);
3271 if (r
!= ERROR_SUCCESS
)
3272 WARN ("RegCloseKey returned %li\n", r
);
3276 ret
= RegCloseKey (hkSubKey
);
3277 if (ret
!= ERROR_SUCCESS
)
3279 ERR ("RegCloseKey returned %li\n", ret
);
3283 return ERROR_SUCCESS
;
3286 /*******************************************************************************
3287 * EnumPrinterDataExA [WINSPOOL.@]
3289 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
3290 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
3291 * what Windows 2000 SP1 does.
3294 DWORD WINAPI
EnumPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
,
3295 LPBYTE pEnumValues
, DWORD cbEnumValues
,
3296 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
3300 DWORD ret
, dwIndex
, dwBufSize
;
3304 TRACE ("%p %s\n", hPrinter
, pKeyName
);
3306 if (pKeyName
== NULL
|| *pKeyName
== 0)
3307 return ERROR_INVALID_PARAMETER
;
3309 len
= MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, NULL
, 0);
3312 ret
= GetLastError ();
3313 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
3317 hHeap
= GetProcessHeap ();
3320 ERR ("GetProcessHeap failed\n");
3321 return ERROR_OUTOFMEMORY
;
3324 pKeyNameW
= HeapAlloc (hHeap
, 0, len
* sizeof (WCHAR
));
3325 if (pKeyNameW
== NULL
)
3327 ERR ("Failed to allocate %li bytes from process heap\n",
3328 (LONG
) len
* sizeof (WCHAR
));
3329 return ERROR_OUTOFMEMORY
;
3332 if (MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, pKeyNameW
, len
) == 0)
3334 ret
= GetLastError ();
3335 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
3336 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3337 WARN ("HeapFree failed with code %li\n", GetLastError ());
3341 ret
= EnumPrinterDataExW (hPrinter
, pKeyNameW
, pEnumValues
, cbEnumValues
,
3342 pcbEnumValues
, pnEnumValues
);
3343 if (ret
!= ERROR_SUCCESS
)
3345 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3346 WARN ("HeapFree failed with code %li\n", GetLastError ());
3347 TRACE ("EnumPrinterDataExW returned %li\n", ret
);
3351 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3353 ret
= GetLastError ();
3354 ERR ("HeapFree failed with code %li\n", ret
);
3358 if (*pnEnumValues
== 0) /* empty key */
3359 return ERROR_SUCCESS
;
3362 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
3364 PPRINTER_ENUM_VALUESW ppev
=
3365 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
3367 if (dwBufSize
< ppev
->cbValueName
)
3368 dwBufSize
= ppev
->cbValueName
;
3370 if (dwBufSize
< ppev
->cbData
&& (ppev
->dwType
== REG_SZ
||
3371 ppev
->dwType
== REG_EXPAND_SZ
|| ppev
->dwType
== REG_MULTI_SZ
))
3372 dwBufSize
= ppev
->cbData
;
3375 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize
);
3377 pBuffer
= HeapAlloc (hHeap
, 0, dwBufSize
);
3378 if (pBuffer
== NULL
)
3380 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize
);
3381 return ERROR_OUTOFMEMORY
;
3384 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
3386 PPRINTER_ENUM_VALUESW ppev
=
3387 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
3389 len
= WideCharToMultiByte (CP_ACP
, 0, ppev
->pValueName
,
3390 ppev
->cbValueName
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
,
3394 ret
= GetLastError ();
3395 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
3396 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3397 WARN ("HeapFree failed with code %li\n", GetLastError ());
3401 memcpy (ppev
->pValueName
, pBuffer
, len
);
3403 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
3405 if (ppev
->dwType
!= REG_SZ
&& ppev
->dwType
!= REG_EXPAND_SZ
&&
3406 ppev
->dwType
!= REG_MULTI_SZ
)
3409 len
= WideCharToMultiByte (CP_ACP
, 0, (LPWSTR
) ppev
->pData
,
3410 ppev
->cbData
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
, NULL
);
3413 ret
= GetLastError ();
3414 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
3415 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3416 WARN ("HeapFree failed with code %li\n", GetLastError ());
3420 memcpy (ppev
->pData
, pBuffer
, len
);
3422 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
3423 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
3426 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3428 ret
= GetLastError ();
3429 ERR ("HeapFree failed with code %li\n", ret
);
3433 return ERROR_SUCCESS
;