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 const char Printers
[] =
72 "System\\CurrentControlSet\\control\\Print\\Printers\\";
73 static const char Drivers
[] =
74 "System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
76 static const WCHAR DefaultEnvironmentW
[] = {'W','i','n','e',0};
78 static const WCHAR Configuration_FileW
[] = {'C','o','n','f','i','g','u','r','a','t',
79 'i','o','n',' ','F','i','l','e',0};
80 static const WCHAR DatatypeW
[] = {'D','a','t','a','t','y','p','e',0};
81 static const WCHAR Data_FileW
[] = {'D','a','t','a',' ','F','i','l','e',0};
82 static const WCHAR Default_DevModeW
[] = {'D','e','f','a','u','l','t',' ','D','e','v',
84 static const WCHAR Dependent_FilesW
[] = {'D','e','p','e','n','d','e','n','t',' ','F',
86 static const WCHAR DescriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
87 static const WCHAR DriverW
[] = {'D','r','i','v','e','r',0};
88 static const WCHAR Help_FileW
[] = {'H','e','l','p',' ','F','i','l','e',0};
89 static const WCHAR LocationW
[] = {'L','o','c','a','t','i','o','n',0};
90 static const WCHAR MonitorW
[] = {'M','o','n','i','t','o','r',0};
91 static const WCHAR NameW
[] = {'N','a','m','e',0};
92 static const WCHAR ParametersW
[] = {'P','a','r','a','m','e','t','e','r','s',0};
93 static const WCHAR PortW
[] = {'P','o','r','t',0};
94 static const WCHAR Print_ProcessorW
[] = {'P','r','i','n','t',' ','P','r','o','c','e',
96 static const WCHAR Printer_DriverW
[] = {'P','r','i','n','t','e','r',' ','D','r','i',
98 static const WCHAR PrinterDriverDataW
[] = {'P','r','i','n','t','e','r','D','r','i',
99 'v','e','r','D','a','t','a',0};
100 static const WCHAR Separator_FileW
[] = {'S','e','p','a','r','a','t','o','r',' ','F',
102 static const WCHAR Share_NameW
[] = {'S','h','a','r','e',' ','N','a','m','e',0};
103 static const WCHAR WinPrintW
[] = {'W','i','n','P','r','i','n','t',0};
104 static const WCHAR devicesW
[] = {'d','e','v','i','c','e','s',0};
106 static const WCHAR May_Delete_Value
[] = {'W','i','n','e','M','a','y','D','e','l','e','t','e','M','e',0};
108 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
);
109 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
110 DWORD Level
, LPBYTE pDriverInfo
,
111 DWORD cbBuf
, LPDWORD pcbNeeded
,
113 static DWORD
WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter
, HKEY
*phkey
);
115 /* RtlCreateUnicodeStringFromAsciiz will return an empty string in the buffer
116 if passed a NULL string. This returns NULLs to the result.
118 static inline PWSTR
asciitounicode( UNICODE_STRING
* usBufferPtr
, LPCSTR src
)
122 RtlCreateUnicodeStringFromAsciiz(usBufferPtr
, src
);
123 return usBufferPtr
->Buffer
;
125 usBufferPtr
->Buffer
= NULL
; /* so that RtlFreeUnicodeString won't barf */
130 WINSPOOL_SetDefaultPrinter(const char *devname
, const char *name
,BOOL force
) {
133 /* If forcing, or no profile string entry for device yet, set the entry
135 * The always change entry if not WINEPS yet is discussable.
138 !GetProfileStringA("windows","device","*",qbuf
,sizeof(qbuf
)) ||
140 !strstr(qbuf
,"WINEPS")
142 char *buf
= HeapAlloc(GetProcessHeap(),0,strlen(name
)+strlen(devname
)+strlen(",WINEPS,LPR:")+1);
144 sprintf(buf
,"%s,WINEPS,LPR:%s",devname
,name
);
145 WriteProfileStringA("windows","device",buf
);
146 HeapFree(GetProcessHeap(),0,buf
);
150 #ifdef HAVE_CUPS_CUPS_H
151 static BOOL
CUPS_LoadPrinters(void)
153 typeof(cupsGetDests
) *pcupsGetDests
= NULL
;
154 typeof(cupsGetPPD
) *pcupsGetPPD
= NULL
;
156 BOOL hadprinter
= FALSE
;
158 PRINTER_INFO_2A pinfo2a
;
159 void *cupshandle
= NULL
;
161 HKEY hkeyPrinter
, hkeyPrinters
;
163 cupshandle
= wine_dlopen(SONAME_LIBCUPS
, RTLD_NOW
, NULL
, 0);
166 TRACE("loaded %s\n", SONAME_LIBCUPS
);
169 p##x = wine_dlsym(cupshandle, #x, NULL,0); \
170 if (!p##x) return FALSE;
173 DYNCUPS(cupsGetDests
);
176 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
178 ERR("Can't create Printers key\n");
182 nrofdests
= pcupsGetDests(&dests
);
183 TRACE("Found %d CUPS %s:\n", nrofdests
, (nrofdests
== 1) ? "printer" : "printers");
184 for (i
=0;i
<nrofdests
;i
++) {
185 port
= HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(dests
[i
].name
)+1);
186 sprintf(port
,"LPR:%s",dests
[i
].name
);
187 devline
=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port
)+1);
188 sprintf(devline
,"WINEPS,%s",port
);
189 WriteProfileStringA("devices",dests
[i
].name
,devline
);
190 HeapFree(GetProcessHeap(),0,devline
);
192 TRACE("Printer %d: %s\n", i
, dests
[i
].name
);
193 if(RegOpenKeyA(hkeyPrinters
, dests
[i
].name
, &hkeyPrinter
) == ERROR_SUCCESS
) {
194 /* Printer already in registry, delete the tag added in WINSPOOL_LoadSystemPrinters
196 TRACE("Printer already exists\n");
197 RegDeleteValueW(hkeyPrinter
, May_Delete_Value
);
198 RegCloseKey(hkeyPrinter
);
200 memset(&pinfo2a
,0,sizeof(pinfo2a
));
201 pinfo2a
.pPrinterName
= dests
[i
].name
;
202 pinfo2a
.pDatatype
= "RAW";
203 pinfo2a
.pPrintProcessor
= "WinPrint";
204 pinfo2a
.pDriverName
= "PS Driver";
205 pinfo2a
.pComment
= "WINEPS Printer using CUPS";
206 pinfo2a
.pLocation
= "<physical location of printer>";
207 pinfo2a
.pPortName
= port
;
208 pinfo2a
.pParameters
= "<parameters?>";
209 pinfo2a
.pShareName
= "<share name?>";
210 pinfo2a
.pSepFile
= "<sep file?>";
212 if (!AddPrinterA(NULL
,2,(LPBYTE
)&pinfo2a
)) {
213 if (GetLastError() != ERROR_PRINTER_ALREADY_EXISTS
)
214 ERR("printer '%s' not added by AddPrinterA (error %ld)\n",dests
[i
].name
,GetLastError());
217 HeapFree(GetProcessHeap(),0,port
);
220 if (dests
[i
].is_default
)
221 WINSPOOL_SetDefaultPrinter(dests
[i
].name
, dests
[i
].name
, TRUE
);
223 RegCloseKey(hkeyPrinters
);
224 wine_dlclose(cupshandle
, NULL
, 0);
230 PRINTCAP_ParseEntry(char *pent
,BOOL isfirst
) {
231 PRINTER_INFO_2A pinfo2a
;
232 char *e
,*s
,*name
,*prettyname
,*devname
;
233 BOOL ret
= FALSE
, set_default
= FALSE
;
234 char *port
,*devline
,*env_default
;
235 HKEY hkeyPrinter
, hkeyPrinters
;
237 while (isspace(*pent
)) pent
++;
238 s
= strchr(pent
,':');
240 name
= HeapAlloc(GetProcessHeap(), 0, strlen(pent
) + 1);
248 TRACE("name=%s entry=%s\n",name
, pent
);
250 if(ispunct(*name
)) { /* a tc entry, not a real printer */
251 TRACE("skipping tc entry\n");
255 if(strstr(pent
,":server")) { /* server only version so skip */
256 TRACE("skipping server entry\n");
260 /* Determine whether this is a postscript printer. */
263 env_default
= getenv("PRINTER");
265 /* Get longest name, usually the one at the right for later display. */
266 while((s
=strchr(prettyname
,'|'))) {
269 while(isspace(*--e
)) *e
= '\0';
270 TRACE("\t%s\n", debugstr_a(prettyname
));
271 if(env_default
&& !strcasecmp(prettyname
, env_default
)) set_default
= TRUE
;
272 for(prettyname
= s
+1; isspace(*prettyname
); prettyname
++)
275 e
= prettyname
+ strlen(prettyname
);
276 while(isspace(*--e
)) *e
= '\0';
277 TRACE("\t%s\n", debugstr_a(prettyname
));
278 if(env_default
&& !strcasecmp(prettyname
, env_default
)) set_default
= TRUE
;
280 /* prettyname must fit into the dmDeviceName member of DEVMODE struct,
281 * if it is too long, we use it as comment below. */
282 devname
= prettyname
;
283 if (strlen(devname
)>=CCHDEVICENAME
-1)
285 if (strlen(devname
)>=CCHDEVICENAME
-1) {
290 port
= HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(name
)+1);
291 sprintf(port
,"LPR:%s",name
);
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(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
300 ERR("Can't create Printers key\n");
304 if(RegOpenKeyA(hkeyPrinters
, devname
, &hkeyPrinter
) == ERROR_SUCCESS
) {
305 /* Printer already in registry, delete the tag added in WINSPOOL_LoadSystemPrinters
307 TRACE("Printer already exists\n");
308 RegDeleteValueW(hkeyPrinter
, May_Delete_Value
);
309 RegCloseKey(hkeyPrinter
);
311 memset(&pinfo2a
,0,sizeof(pinfo2a
));
312 pinfo2a
.pPrinterName
= devname
;
313 pinfo2a
.pDatatype
= "RAW";
314 pinfo2a
.pPrintProcessor
= "WinPrint";
315 pinfo2a
.pDriverName
= "PS Driver";
316 pinfo2a
.pComment
= "WINEPS Printer using LPR";
317 pinfo2a
.pLocation
= prettyname
;
318 pinfo2a
.pPortName
= port
;
319 pinfo2a
.pParameters
= "<parameters?>";
320 pinfo2a
.pShareName
= "<share name?>";
321 pinfo2a
.pSepFile
= "<sep file?>";
323 if (!AddPrinterA(NULL
,2,(LPBYTE
)&pinfo2a
)) {
324 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS
)
325 ERR("%s not added by AddPrinterA (%ld)\n",name
,GetLastError());
328 RegCloseKey(hkeyPrinters
);
330 if (isfirst
|| set_default
)
331 WINSPOOL_SetDefaultPrinter(devname
,name
,TRUE
);
333 HeapFree(GetProcessHeap(), 0, port
);
335 HeapFree(GetProcessHeap(), 0, name
);
340 PRINTCAP_LoadPrinters(void) {
341 BOOL hadprinter
= FALSE
;
345 BOOL had_bash
= FALSE
;
347 f
= fopen("/etc/printcap","r");
351 while(fgets(buf
,sizeof(buf
),f
)) {
354 end
=strchr(buf
,'\n');
358 while(isspace(*start
)) start
++;
359 if(*start
== '#' || *start
== '\0')
362 if(pent
&& !had_bash
&& *start
!= ':' && *start
!= '|') { /* start of new entry, parse the previous one */
363 hadprinter
|= PRINTCAP_ParseEntry(pent
,!hadprinter
);
364 HeapFree(GetProcessHeap(),0,pent
);
368 if (end
&& *--end
== '\\') {
375 pent
=HeapReAlloc(GetProcessHeap(),0,pent
,strlen(pent
)+strlen(start
)+1);
378 pent
=HeapAlloc(GetProcessHeap(),0,strlen(start
)+1);
384 hadprinter
|= PRINTCAP_ParseEntry(pent
,!hadprinter
);
385 HeapFree(GetProcessHeap(),0,pent
);
391 static inline DWORD
set_reg_szW(HKEY hkey
, const WCHAR
*keyname
, const WCHAR
*value
)
394 return RegSetValueExW(hkey
, keyname
, 0, REG_SZ
, (LPBYTE
)value
,
395 lstrlenW(value
) * sizeof(WCHAR
));
397 return ERROR_FILE_NOT_FOUND
;
400 void WINSPOOL_LoadSystemPrinters(void)
402 HKEY hkey
, hkeyPrinters
;
405 DWORD needed
, num
, i
;
406 WCHAR PrinterName
[256];
409 di3a
.cVersion
= 0x400;
410 di3a
.pName
= "PS Driver";
411 di3a
.pEnvironment
= NULL
; /* NULL means auto */
412 di3a
.pDriverPath
= "wineps16";
413 di3a
.pDataFile
= "<datafile?>";
414 di3a
.pConfigFile
= "wineps16";
415 di3a
.pHelpFile
= "<helpfile?>";
416 di3a
.pDependentFiles
= "<dependend files?>";
417 di3a
.pMonitorName
= "<monitor name?>";
418 di3a
.pDefaultDataType
= "RAW";
420 if (!AddPrinterDriverA(NULL
,3,(LPBYTE
)&di3a
)) {
421 ERR("Failed adding PS Driver (%ld)\n",GetLastError());
425 /* This ensures that all printer entries have a valid Name value. If causes
426 problems later if they don't. If one is found to be missed we create one
427 and set it equal to the name of the key */
428 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) == ERROR_SUCCESS
) {
429 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &num
, NULL
, NULL
,
430 NULL
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
431 for(i
= 0; i
< num
; i
++) {
432 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) == ERROR_SUCCESS
) {
433 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkey
) == ERROR_SUCCESS
) {
434 if(RegQueryValueExW(hkey
, NameW
, 0, 0, 0, &needed
) == ERROR_FILE_NOT_FOUND
) {
435 set_reg_szW(hkey
, NameW
, PrinterName
);
442 RegCloseKey(hkeyPrinters
);
445 /* We want to avoid calling AddPrinter on printers as much as
446 possible, because on cups printers this will (eventually) lead
447 to a call to cupsGetPPD which takes forever, even with non-cups
448 printers AddPrinter takes a while. So we'll tag all printers that
449 were automatically added last time around, if they still exist
450 we'll leave them be otherwise we'll delete them. */
451 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 5, NULL
, 0, &needed
, &num
);
453 PRINTER_INFO_5A
* pi
= HeapAlloc(GetProcessHeap(), 0, needed
);
454 if(EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 5, (LPBYTE
)pi
, needed
, &needed
, &num
)) {
455 for(i
= 0; i
< num
; i
++) {
456 if(pi
[i
].pPortName
== NULL
|| !strncmp(pi
[i
].pPortName
,"CUPS:", 5) || !strncmp(pi
[i
].pPortName
, "LPR:", 4)) {
457 if(OpenPrinterA(pi
[i
].pPrinterName
, &hprn
, NULL
)) {
458 if(WINSPOOL_GetOpenedPrinterRegKey(hprn
, &hkey
) == ERROR_SUCCESS
) {
460 RegSetValueExW(hkey
, May_Delete_Value
, 0, REG_DWORD
, (LPBYTE
)&dw
, sizeof(dw
));
468 HeapFree(GetProcessHeap(), 0, pi
);
472 #ifdef HAVE_CUPS_CUPS_H
473 done
= CUPS_LoadPrinters();
476 if(!done
) { /* If we have any CUPS based printers, skip looking for printcap printers */
477 /* Check for [ppd] section in config file before parsing /etc/printcap */
478 if (RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\ppd",
479 &hkey
) == ERROR_SUCCESS
) {
481 PRINTCAP_LoadPrinters();
485 /* Now enumerate the list again and delete any printers that a still tagged */
486 EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 5, NULL
, 0, &needed
, &num
);
488 PRINTER_INFO_5A
* pi
= HeapAlloc(GetProcessHeap(), 0, needed
);
489 if(EnumPrintersA(PRINTER_ENUM_LOCAL
, NULL
, 5, (LPBYTE
)pi
, needed
, &needed
, &num
)) {
490 for(i
= 0; i
< num
; i
++) {
491 if(pi
[i
].pPortName
== NULL
|| !strncmp(pi
[i
].pPortName
,"CUPS:", 5) || !strncmp(pi
[i
].pPortName
, "LPR:", 4)) {
492 if(OpenPrinterA(pi
[i
].pPrinterName
, &hprn
, NULL
)) {
493 if(WINSPOOL_GetOpenedPrinterRegKey(hprn
, &hkey
) == ERROR_SUCCESS
) {
494 DWORD dw
, type
, size
= sizeof(dw
);
495 if(RegQueryValueExW(hkey
, May_Delete_Value
, NULL
, &type
, (LPBYTE
)&dw
, &size
) == ERROR_SUCCESS
) {
496 TRACE("Deleting old printer %s\n", pi
[i
].pPrinterName
);
506 HeapFree(GetProcessHeap(), 0, pi
);
514 /******************************************************************
515 * WINSPOOL_GetOpenedPrinterEntry
516 * Get the first place empty in the opened printer table
518 static HANDLE
WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name
)
522 for (i
= 0; i
< nb_printers
; i
++) if (!printer_array
[i
]) break;
524 if (i
>= nb_printers
)
528 new_array
= HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, printer_array
,
529 (nb_printers
+ 16) * sizeof(*new_array
) );
531 new_array
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
532 (nb_printers
+ 16) * sizeof(*new_array
) );
534 if (!new_array
) return 0;
535 printer_array
= new_array
;
539 if ((printer_array
[i
] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name
)+1)*sizeof(WCHAR
) )))
541 strcpyW( printer_array
[i
], name
);
542 return (HANDLE
)(i
+ 1);
547 /******************************************************************
548 * WINSPOOL_GetOpenedPrinter
549 * Get the pointer to the opened printer referred by the handle
551 static LPCWSTR
WINSPOOL_GetOpenedPrinter(HANDLE printerHandle
)
553 int idx
= (int)printerHandle
;
554 if ((idx
<= 0) || (idx
> nb_printers
))
556 SetLastError(ERROR_INVALID_HANDLE
);
559 return printer_array
[idx
- 1];
562 /******************************************************************
563 * WINSPOOL_GetOpenedPrinterRegKey
566 static DWORD
WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter
, HKEY
*phkey
)
568 LPCWSTR name
= WINSPOOL_GetOpenedPrinter(hPrinter
);
572 if(!name
) return ERROR_INVALID_HANDLE
;
574 if((ret
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
)) !=
578 if(RegOpenKeyW(hkeyPrinters
, name
, phkey
) != ERROR_SUCCESS
)
580 ERR("Can't find opened printer %s in registry\n",
582 RegCloseKey(hkeyPrinters
);
583 return ERROR_INVALID_PRINTER_NAME
; /* ? */
585 RegCloseKey(hkeyPrinters
);
586 return ERROR_SUCCESS
;
589 /***********************************************************
592 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
595 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
598 Formname
= (dmA
->dmSize
> off_formname
);
599 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
600 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
603 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
604 dmA
->dmSize
- CCHDEVICENAME
);
606 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
607 off_formname
- CCHDEVICENAME
);
608 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
610 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
611 (off_formname
+ CCHFORMNAME
));
614 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
619 /***********************************************************
621 * Creates an ascii copy of supplied devmode on heap
623 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
628 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
630 if(!dmW
) return NULL
;
631 Formname
= (dmW
->dmSize
> off_formname
);
632 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
633 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
634 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
635 CCHDEVICENAME
, NULL
, NULL
);
637 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
638 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
640 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
641 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
642 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
643 CCHFORMNAME
, NULL
, NULL
);
644 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
645 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
648 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
653 /***********************************************************
655 * Creates a unicode copy of PRINTER_INFO_2A on heap
657 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
659 LPPRINTER_INFO_2W piW
;
660 UNICODE_STRING usBuffer
;
662 if(!piA
) return NULL
;
663 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
664 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
666 piW
->pServerName
= asciitounicode(&usBuffer
,piA
->pServerName
);
667 piW
->pPrinterName
= asciitounicode(&usBuffer
,piA
->pPrinterName
);
668 piW
->pShareName
= asciitounicode(&usBuffer
,piA
->pShareName
);
669 piW
->pPortName
= asciitounicode(&usBuffer
,piA
->pPortName
);
670 piW
->pDriverName
= asciitounicode(&usBuffer
,piA
->pDriverName
);
671 piW
->pComment
= asciitounicode(&usBuffer
,piA
->pComment
);
672 piW
->pLocation
= asciitounicode(&usBuffer
,piA
->pLocation
);
673 piW
->pDevMode
= piA
->pDevMode
? GdiConvertToDevmodeW(piA
->pDevMode
) : NULL
;
674 piW
->pSepFile
= asciitounicode(&usBuffer
,piA
->pSepFile
);
675 piW
->pPrintProcessor
= asciitounicode(&usBuffer
,piA
->pPrintProcessor
);
676 piW
->pDatatype
= asciitounicode(&usBuffer
,piA
->pDatatype
);
677 piW
->pParameters
= asciitounicode(&usBuffer
,piA
->pParameters
);
681 /***********************************************************
682 * FREE_PRINTER_INFO_2W
683 * Free PRINTER_INFO_2W and all strings
685 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
689 HeapFree(heap
,0,piW
->pServerName
);
690 HeapFree(heap
,0,piW
->pPrinterName
);
691 HeapFree(heap
,0,piW
->pShareName
);
692 HeapFree(heap
,0,piW
->pPortName
);
693 HeapFree(heap
,0,piW
->pDriverName
);
694 HeapFree(heap
,0,piW
->pComment
);
695 HeapFree(heap
,0,piW
->pLocation
);
696 HeapFree(heap
,0,piW
->pDevMode
);
697 HeapFree(heap
,0,piW
->pSepFile
);
698 HeapFree(heap
,0,piW
->pPrintProcessor
);
699 HeapFree(heap
,0,piW
->pDatatype
);
700 HeapFree(heap
,0,piW
->pParameters
);
701 HeapFree(heap
,0,piW
);
705 /******************************************************************
706 * DeviceCapabilities [WINSPOOL.@]
707 * DeviceCapabilitiesA [WINSPOOL.@]
710 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
711 LPSTR pOutput
, LPDEVMODEA lpdm
)
715 if (!GDI_CallDeviceCapabilities16
)
717 GDI_CallDeviceCapabilities16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
719 if (!GDI_CallDeviceCapabilities16
) return -1;
721 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
723 /* If DC_PAPERSIZE map POINT16s to POINTs */
724 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
725 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
726 POINT
*pt
= (POINT
*)pOutput
;
728 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
729 for(i
= 0; i
< ret
; i
++, pt
++)
734 HeapFree( GetProcessHeap(), 0, tmp
);
740 /*****************************************************************************
741 * DeviceCapabilitiesW [WINSPOOL.@]
743 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
746 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
747 WORD fwCapability
, LPWSTR pOutput
,
748 const DEVMODEW
*pDevMode
)
750 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
751 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
752 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
755 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
756 fwCapability
== DC_FILEDEPENDENCIES
||
757 fwCapability
== DC_PAPERNAMES
)) {
758 /* These need A -> W translation */
761 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
765 switch(fwCapability
) {
770 case DC_FILEDEPENDENCIES
:
774 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
775 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
777 for(i
= 0; i
< ret
; i
++)
778 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
779 pOutput
+ (i
* size
), size
);
780 HeapFree(GetProcessHeap(), 0, pOutputA
);
782 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
783 (LPSTR
)pOutput
, dmA
);
785 HeapFree(GetProcessHeap(),0,pPortA
);
786 HeapFree(GetProcessHeap(),0,pDeviceA
);
787 HeapFree(GetProcessHeap(),0,dmA
);
791 /******************************************************************
792 * DocumentPropertiesA [WINSPOOL.@]
794 * FIXME: implement DocumentPropertiesA via DocumentPropertiesW, not vice versa
796 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
797 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
798 LPDEVMODEA pDevModeInput
,DWORD fMode
)
800 LPSTR lpName
= pDeviceName
;
803 TRACE("(%p,%p,%s,%p,%p,%ld)\n",
804 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
808 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
810 ERR("no name from hPrinter?\n");
813 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
816 if (!GDI_CallExtDeviceMode16
)
818 GDI_CallExtDeviceMode16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
820 if (!GDI_CallExtDeviceMode16
) {
821 ERR("No CallExtDeviceMode16?\n");
825 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
826 pDevModeInput
, NULL
, fMode
);
829 HeapFree(GetProcessHeap(),0,lpName
);
834 /*****************************************************************************
835 * DocumentPropertiesW (WINSPOOL.@)
837 * FIXME: implement DocumentPropertiesA via DocumentPropertiesW, not vice versa
839 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
841 LPDEVMODEW pDevModeOutput
,
842 LPDEVMODEW pDevModeInput
, DWORD fMode
)
845 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
846 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
847 LPDEVMODEA pDevModeOutputA
= NULL
;
850 TRACE("(%p,%p,%s,%p,%p,%ld)\n",
851 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
854 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
855 if(ret
< 0) return ret
;
856 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
858 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
859 pDevModeInputA
, fMode
);
861 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
862 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
864 if(fMode
== 0 && ret
> 0)
865 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
866 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
867 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
871 /******************************************************************
872 * OpenPrinterA [WINSPOOL.@]
875 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
876 LPPRINTER_DEFAULTSA pDefault
)
878 UNICODE_STRING lpPrinterNameW
;
879 UNICODE_STRING usBuffer
;
880 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
881 PWSTR pwstrPrinterNameW
;
884 pwstrPrinterNameW
= asciitounicode(&lpPrinterNameW
,lpPrinterName
);
887 DefaultW
.pDatatype
= asciitounicode(&usBuffer
,pDefault
->pDatatype
);
888 DefaultW
.pDevMode
= pDefault
->pDevMode
? GdiConvertToDevmodeW(pDefault
->pDevMode
) : NULL
;
889 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
890 pDefaultW
= &DefaultW
;
892 ret
= OpenPrinterW(pwstrPrinterNameW
, phPrinter
, pDefaultW
);
894 RtlFreeUnicodeString(&usBuffer
);
895 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
897 RtlFreeUnicodeString(&lpPrinterNameW
);
901 /******************************************************************
902 * OpenPrinterW [WINSPOOL.@]
905 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
906 LPPRINTER_DEFAULTSW pDefault
)
908 HKEY hkeyPrinters
, hkeyPrinter
;
910 if (!lpPrinterName
) {
911 FIXME("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
912 SetLastError(ERROR_INVALID_PARAMETER
);
916 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
919 /* Check Printer exists */
920 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
922 ERR("Can't create Printers key\n");
923 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
927 if(lpPrinterName
[0] == '\0' || /* explicitly exclude "" */
928 RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
930 TRACE("Can't find printer %s in registry\n",
931 debugstr_w(lpPrinterName
));
932 RegCloseKey(hkeyPrinters
);
933 SetLastError(ERROR_INVALID_PRINTER_NAME
);
936 RegCloseKey(hkeyPrinter
);
937 RegCloseKey(hkeyPrinters
);
939 if(!phPrinter
) /* This seems to be what win95 does anyway */
942 /* Get the unique handle of the printer*/
943 *phPrinter
= WINSPOOL_GetOpenedPrinterEntry( lpPrinterName
);
945 if (pDefault
!= NULL
)
946 FIXME("Not handling pDefault\n");
951 /******************************************************************
952 * AddMonitorA [WINSPOOL.@]
955 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
957 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
958 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
962 /******************************************************************
963 * DeletePrinterDriverA [WINSPOOL.@]
967 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
969 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
970 debugstr_a(pDriverName
));
971 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
976 /******************************************************************
977 * DeleteMonitorA [WINSPOOL.@]
981 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
983 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
984 debugstr_a(pMonitorName
));
985 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
990 /******************************************************************
991 * DeletePortA [WINSPOOL.@]
995 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
997 FIXME("(%s,%p,%s):stub\n",debugstr_a(pName
),hWnd
,
998 debugstr_a(pPortName
));
999 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1003 /******************************************************************************
1004 * SetPrinterW [WINSPOOL.@]
1014 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1018 /******************************************************************************
1019 * WritePrinter [WINSPOOL.@]
1026 LPDWORD pcWritten
) {
1029 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1033 /*****************************************************************************
1034 * AddFormA [WINSPOOL.@]
1036 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
1038 FIXME("(%p,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
1042 /*****************************************************************************
1043 * AddFormW [WINSPOOL.@]
1045 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
1047 FIXME("(%p,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
1051 /*****************************************************************************
1052 * AddJobA [WINSPOOL.@]
1054 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
1055 DWORD cbBuf
, LPDWORD pcbNeeded
)
1057 FIXME("(%p,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
1062 /*****************************************************************************
1063 * AddJobW [WINSPOOL.@]
1065 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
1068 FIXME("(%p,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
1073 /*****************************************************************************
1074 * GetPrintProcessorDirectoryA [WINSPOOL.@]
1076 BOOL WINAPI
GetPrintProcessorDirectoryA(LPSTR server
, LPSTR env
,
1077 DWORD level
, LPBYTE Info
,
1078 DWORD cbBuf
, LPDWORD needed
)
1080 FIXME("(%s,%s,%ld,%p,0x%08lx): stub\n", server
, env
, level
, Info
, cbBuf
);
1084 /*****************************************************************************
1085 * WINSPOOL_OpenDriverReg [internal]
1087 * opens the registry for the printer drivers depending on the given input
1088 * variable pEnvironment
1091 * the opened hkey on success
1094 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
)
1096 LPSTR lpKey
, p
= NULL
;
1099 (unicode
) ? debugstr_w(pEnvironment
) : debugstr_a(pEnvironment
));
1102 p
= (unicode
) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
) :
1106 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
1108 if(!GetVersionExA( &ver
))
1111 switch (ver
.dwPlatformId
) {
1112 case VER_PLATFORM_WIN32s
:
1113 ERR("win32 style printing used with 16 bits app, try specifying 'win95' Windows version\n");
1116 case VER_PLATFORM_WIN32_NT
:
1117 p
= "Windows NT x86";
1123 TRACE("set environment to %s\n", p
);
1126 lpKey
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1127 strlen(p
) + strlen(Drivers
));
1128 sprintf( lpKey
, Drivers
, p
);
1130 TRACE("%s\n", lpKey
);
1132 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, lpKey
, &retval
) !=
1136 if(pEnvironment
&& unicode
)
1137 HeapFree( GetProcessHeap(), 0, p
);
1138 HeapFree( GetProcessHeap(), 0, lpKey
);
1143 /*****************************************************************************
1144 * AddPrinterW [WINSPOOL.@]
1146 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1148 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
1152 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
1155 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
1158 ERR("pName = %s - unsupported\n", debugstr_w(pName
));
1159 SetLastError(ERROR_INVALID_PARAMETER
);
1163 ERR("Level = %ld, unsupported!\n", Level
);
1164 SetLastError(ERROR_INVALID_LEVEL
);
1167 if (strlenW(pi
->pPrinterName
) >= CCHDEVICENAME
) {
1168 ERR("Printername %s must not exceed length of DEVMODE.dmDeviceName !\n",
1169 debugstr_w(pi
->pPrinterName
)
1171 SetLastError(ERROR_INVALID_LEVEL
);
1175 SetLastError(ERROR_INVALID_PARAMETER
);
1178 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1180 ERR("Can't create Printers key\n");
1183 if(!RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
)) {
1184 if (!RegQueryValueA(hkeyPrinter
,"Attributes",NULL
,NULL
)) {
1185 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
1186 RegCloseKey(hkeyPrinter
);
1187 RegCloseKey(hkeyPrinters
);
1190 RegCloseKey(hkeyPrinter
);
1192 hkeyDrivers
= WINSPOOL_OpenDriverReg( NULL
, TRUE
);
1194 ERR("Can't create Drivers key\n");
1195 RegCloseKey(hkeyPrinters
);
1198 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
1200 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
1201 RegCloseKey(hkeyPrinters
);
1202 RegCloseKey(hkeyDrivers
);
1203 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
1206 RegCloseKey(hkeyDriver
);
1207 RegCloseKey(hkeyDrivers
);
1209 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
1210 FIXME("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
1211 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
1212 RegCloseKey(hkeyPrinters
);
1216 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
1218 FIXME("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
1219 SetLastError(ERROR_INVALID_PRINTER_NAME
);
1220 RegCloseKey(hkeyPrinters
);
1223 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
1224 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
1225 set_reg_szW(hkeyPrinter
, DatatypeW
, pi
->pDatatype
);
1227 /* See if we can load the driver. We may need the devmode structure anyway
1230 * Note that DocumentPropertiesW will briefly try to open the printer we
1231 * just create to find a DEVMODEA struct (it will use the WINEPS default
1232 * one in case it is not there, so we are ok).
1234 size
= DocumentPropertiesW(0, 0, pi
->pPrinterName
, NULL
, NULL
, 0);
1237 FIXME("DocumentPropertiesW on printer '%s' fails\n", debugstr_w(pi
->pPrinterName
));
1238 size
= sizeof(DEVMODEW
);
1244 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
1245 ZeroMemory(dmW
,size
);
1247 if (0>DocumentPropertiesW(0,0,pi
->pPrinterName
,dmW
,NULL
,DM_OUT_BUFFER
))
1249 WARN("DocumentPropertiesW on printer '%s' failed!\n", debugstr_w(pi
->pPrinterName
));
1250 HeapFree(GetProcessHeap(),0,dmW
);
1255 /* set devmode to printer name */
1256 strcpyW(dmW
->dmDeviceName
,pi
->pPrinterName
);
1260 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
1261 and we support these drivers. NT writes DEVMODEW so somehow
1262 we'll need to distinguish between these when we support NT
1266 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
1267 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
,
1268 (LPBYTE
)dmA
, dmA
->dmSize
+ dmA
->dmDriverExtra
);
1269 HeapFree(GetProcessHeap(), 0, dmA
);
1271 HeapFree(GetProcessHeap(), 0, dmW
);
1273 set_reg_szW(hkeyPrinter
, DescriptionW
, pi
->pComment
);
1274 set_reg_szW(hkeyPrinter
, LocationW
, pi
->pLocation
);
1275 set_reg_szW(hkeyPrinter
, NameW
, pi
->pPrinterName
);
1276 set_reg_szW(hkeyPrinter
, ParametersW
, pi
->pParameters
);
1278 set_reg_szW(hkeyPrinter
, PortW
, pi
->pPortName
);
1279 set_reg_szW(hkeyPrinter
, Print_ProcessorW
, pi
->pPrintProcessor
);
1280 set_reg_szW(hkeyPrinter
, Printer_DriverW
, pi
->pDriverName
);
1281 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
1282 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
1283 set_reg_szW(hkeyPrinter
, Separator_FileW
, pi
->pSepFile
);
1284 set_reg_szW(hkeyPrinter
, Share_NameW
, pi
->pShareName
);
1285 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
1286 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
1287 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
1288 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
1289 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
1290 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
1292 RegCloseKey(hkeyPrinter
);
1293 RegCloseKey(hkeyPrinters
);
1294 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
1295 ERR("OpenPrinter failing\n");
1301 /*****************************************************************************
1302 * AddPrinterA [WINSPOOL.@]
1304 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1306 UNICODE_STRING pNameW
;
1308 PRINTER_INFO_2W
*piW
;
1309 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
1312 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
1314 ERR("Level = %ld, unsupported!\n", Level
);
1315 SetLastError(ERROR_INVALID_LEVEL
);
1318 pwstrNameW
= asciitounicode(&pNameW
,pName
);
1319 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
1321 ret
= AddPrinterW(pwstrNameW
, Level
, (LPBYTE
)piW
);
1323 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
1324 RtlFreeUnicodeString(&pNameW
);
1329 /*****************************************************************************
1330 * ClosePrinter [WINSPOOL.@]
1332 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
1334 int i
= (int)hPrinter
;
1336 TRACE("Handle %p\n", hPrinter
);
1338 if ((i
<= 0) || (i
> nb_printers
)) return FALSE
;
1339 HeapFree( GetProcessHeap(), 0, printer_array
[i
- 1] );
1340 printer_array
[i
- 1] = NULL
;
1344 /*****************************************************************************
1345 * DeleteFormA [WINSPOOL.@]
1347 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
1349 FIXME("(%p,%s): stub\n", hPrinter
, pFormName
);
1353 /*****************************************************************************
1354 * DeleteFormW [WINSPOOL.@]
1356 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
1358 FIXME("(%p,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
1362 /*****************************************************************************
1363 * WINSPOOL_SHRegDeleteKey
1365 * Recursively delete subkeys.
1366 * Cut & paste from shlwapi.
1369 static DWORD
WINSPOOL_SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1371 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1372 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1375 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1378 /* Find how many subkeys there are */
1379 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1380 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1384 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1385 /* Name too big: alloc a buffer for it */
1386 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1389 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1392 /* Recursively delete all the subkeys */
1393 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1395 dwSize
= dwMaxSubkeyLen
;
1396 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1398 dwRet
= WINSPOOL_SHDeleteKeyW(hSubKey
, lpszName
);
1401 if (lpszName
!= szNameBuf
)
1402 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1406 RegCloseKey(hSubKey
);
1408 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1413 /*****************************************************************************
1414 * DeletePrinter [WINSPOOL.@]
1416 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
1418 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1421 if(!lpNameW
) return FALSE
;
1422 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) == ERROR_SUCCESS
) {
1423 WINSPOOL_SHDeleteKeyW(hkeyPrinters
, lpNameW
);
1424 RegCloseKey(hkeyPrinters
);
1426 WriteProfileStringW(devicesW
, lpNameW
, NULL
);
1430 /*****************************************************************************
1431 * SetPrinterA [WINSPOOL.@]
1433 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1436 FIXME("(%p,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
1440 /*****************************************************************************
1441 * SetJobA [WINSPOOL.@]
1443 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1444 LPBYTE pJob
, DWORD Command
)
1446 FIXME("(%p,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1451 /*****************************************************************************
1452 * SetJobW [WINSPOOL.@]
1454 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1455 LPBYTE pJob
, DWORD Command
)
1457 FIXME("(%p,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1462 /*****************************************************************************
1463 * EndDocPrinter [WINSPOOL.@]
1465 BOOL WINAPI
EndDocPrinter(HANDLE hPrinter
)
1467 FIXME("(hPrinter=%p): stub\n", hPrinter
);
1471 /*****************************************************************************
1472 * EndPagePrinter [WINSPOOL.@]
1474 BOOL WINAPI
EndPagePrinter(HANDLE hPrinter
)
1476 FIXME("(hPrinter=%p): stub\n", hPrinter
);
1480 /*****************************************************************************
1481 * StartDocPrinterA [WINSPOOL.@]
1483 DWORD WINAPI
StartDocPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pDocInfo
)
1485 FIXME("(hPrinter=%p, Level=0x%lx, pDocInfo=%p): stub\n", hPrinter
, Level
, pDocInfo
);
1489 /*****************************************************************************
1490 * StartDocPrinterW [WINSPOOL.@]
1492 DWORD WINAPI
StartDocPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pDocInfo
)
1494 FIXME("(hPrinter=%p, Level=0x%lx, pDocInfo=%p): stub\n", hPrinter
, Level
, pDocInfo
);
1498 /*****************************************************************************
1499 * StartPagePrinter [WINSPOOL.@]
1501 BOOL WINAPI
StartPagePrinter(HANDLE hPrinter
)
1503 FIXME("(hPrinter=%p): stub\n", hPrinter
);
1507 /*****************************************************************************
1508 * GetFormA [WINSPOOL.@]
1510 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1511 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1513 FIXME("(%p,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1514 Level
,pForm
,cbBuf
,pcbNeeded
);
1518 /*****************************************************************************
1519 * GetFormW [WINSPOOL.@]
1521 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1522 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1524 FIXME("(%p,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1525 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1529 /*****************************************************************************
1530 * SetFormA [WINSPOOL.@]
1532 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1535 FIXME("(%p,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1539 /*****************************************************************************
1540 * SetFormW [WINSPOOL.@]
1542 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1545 FIXME("(%p,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1549 /*****************************************************************************
1550 * ReadPrinter [WINSPOOL.@]
1552 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1553 LPDWORD pNoBytesRead
)
1555 FIXME("(%p,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1559 /*****************************************************************************
1560 * ResetPrinterA [WINSPOOL.@]
1562 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1564 FIXME("(%p, %p): stub\n", hPrinter
, pDefault
);
1568 /*****************************************************************************
1569 * ResetPrinterW [WINSPOOL.@]
1571 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1573 FIXME("(%p, %p): stub\n", hPrinter
, pDefault
);
1577 /*****************************************************************************
1578 * WINSPOOL_GetDWORDFromReg
1580 * Return DWORD associated with ValueName from hkey.
1582 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
1584 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
1587 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
1589 if(ret
!= ERROR_SUCCESS
) {
1590 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
1593 if(type
!= REG_DWORD
) {
1594 ERR("Got type %ld\n", type
);
1600 /*****************************************************************************
1601 * WINSPOOL_GetStringFromReg
1603 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1604 * String is stored either as unicode or ascii.
1605 * Bit of a hack here to get the ValueName if we want ascii.
1607 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1608 DWORD buflen
, DWORD
*needed
,
1611 DWORD sz
= buflen
, type
;
1615 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1617 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1618 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1619 HeapFree(GetProcessHeap(),0,ValueNameA
);
1621 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1622 WARN("Got ret = %ld\n", ret
);
1630 /*****************************************************************************
1631 * WINSPOOL_GetDefaultDevMode
1633 * Get a default DevMode values for wineps.
1637 static void WINSPOOL_GetDefaultDevMode(
1639 DWORD buflen
, DWORD
*needed
,
1644 /* fill default DEVMODE - should be read from ppd... */
1645 ZeroMemory( &dm
, sizeof(dm
) );
1646 strcpy(dm
.dmDeviceName
,"wineps");
1647 dm
.dmSpecVersion
= DM_SPECVERSION
;
1648 dm
.dmDriverVersion
= 1;
1649 dm
.dmSize
= sizeof(DEVMODEA
);
1650 dm
.dmDriverExtra
= 0;
1652 DM_ORIENTATION
| DM_PAPERSIZE
|
1653 DM_PAPERLENGTH
| DM_PAPERWIDTH
|
1656 DM_DEFAULTSOURCE
| DM_PRINTQUALITY
|
1657 DM_YRESOLUTION
| DM_TTOPTION
;
1659 dm
.u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1660 dm
.u1
.s1
.dmPaperSize
= DMPAPER_A4
;
1661 dm
.u1
.s1
.dmPaperLength
= 2970;
1662 dm
.u1
.s1
.dmPaperWidth
= 2100;
1666 dm
.dmDefaultSource
= DMBIN_AUTO
;
1667 dm
.dmPrintQuality
= DMRES_MEDIUM
;
1670 dm
.dmYResolution
= 300; /* 300dpi */
1671 dm
.dmTTOption
= DMTT_BITMAP
;
1674 /* dm.dmLogPixels */
1675 /* dm.dmBitsPerPel */
1676 /* dm.dmPelsWidth */
1677 /* dm.dmPelsHeight */
1678 /* dm.dmDisplayFlags */
1679 /* dm.dmDisplayFrequency */
1680 /* dm.dmICMMethod */
1681 /* dm.dmICMIntent */
1682 /* dm.dmMediaType */
1683 /* dm.dmDitherType */
1684 /* dm.dmReserved1 */
1685 /* dm.dmReserved2 */
1686 /* dm.dmPanningWidth */
1687 /* dm.dmPanningHeight */
1690 if(buflen
>= sizeof(DEVMODEW
)) {
1691 DEVMODEW
*pdmW
= GdiConvertToDevmodeW(&dm
);
1692 memcpy(ptr
, pdmW
, sizeof(DEVMODEW
));
1693 HeapFree(GetProcessHeap(),0,pdmW
);
1695 *needed
= sizeof(DEVMODEW
);
1699 if(buflen
>= sizeof(DEVMODEA
)) {
1700 memcpy(ptr
, &dm
, sizeof(DEVMODEA
));
1702 *needed
= sizeof(DEVMODEA
);
1706 /*****************************************************************************
1707 * WINSPOOL_GetDevModeFromReg
1709 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1710 * DevMode is stored either as unicode or ascii.
1712 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1714 DWORD buflen
, DWORD
*needed
,
1717 DWORD sz
= buflen
, type
;
1720 if (ptr
&& buflen
>=sizeof(DEVMODEA
)) memset(ptr
, 0, sizeof(DEVMODEA
));
1721 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1722 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1723 if (sz
< sizeof(DEVMODEA
))
1725 TRACE("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName
),sz
);
1728 /* ensures that dmSize is not erratically bogus if registry is invalid */
1729 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1730 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1732 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1734 DEVMODEW
*dmW
= GdiConvertToDevmodeW((DEVMODEA
*)ptr
);
1735 memcpy(ptr
, dmW
, sz
);
1736 HeapFree(GetProcessHeap(),0,dmW
);
1743 /*********************************************************************
1744 * WINSPOOL_GetPrinter_2
1746 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1747 * The strings are either stored as unicode or ascii.
1749 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1750 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1753 DWORD size
, left
= cbBuf
;
1754 BOOL space
= (cbBuf
> 0);
1759 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1761 if(space
&& size
<= left
) {
1762 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1769 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1771 if(space
&& size
<= left
) {
1772 pi2
->pShareName
= (LPWSTR
)ptr
;
1779 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1781 if(space
&& size
<= left
) {
1782 pi2
->pPortName
= (LPWSTR
)ptr
;
1789 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1791 if(space
&& size
<= left
) {
1792 pi2
->pDriverName
= (LPWSTR
)ptr
;
1799 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1801 if(space
&& size
<= left
) {
1802 pi2
->pComment
= (LPWSTR
)ptr
;
1809 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1811 if(space
&& size
<= left
) {
1812 pi2
->pLocation
= (LPWSTR
)ptr
;
1819 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1821 if(space
&& size
<= left
) {
1822 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1831 WINSPOOL_GetDefaultDevMode(ptr
, left
, &size
, unicode
);
1832 if(space
&& size
<= left
) {
1833 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1840 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1842 if(space
&& size
<= left
) {
1843 pi2
->pSepFile
= (LPWSTR
)ptr
;
1850 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1852 if(space
&& size
<= left
) {
1853 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1860 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1862 if(space
&& size
<= left
) {
1863 pi2
->pDatatype
= (LPWSTR
)ptr
;
1870 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1872 if(space
&& size
<= left
) {
1873 pi2
->pParameters
= (LPWSTR
)ptr
;
1881 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1882 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1883 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1884 "Default Priority");
1885 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1886 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1889 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1890 memset(pi2
, 0, sizeof(*pi2
));
1895 /*********************************************************************
1896 * WINSPOOL_GetPrinter_4
1898 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1900 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1901 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1904 DWORD size
, left
= cbBuf
;
1905 BOOL space
= (cbBuf
> 0);
1910 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1912 if(space
&& size
<= left
) {
1913 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1921 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1924 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1925 memset(pi4
, 0, sizeof(*pi4
));
1930 /*********************************************************************
1931 * WINSPOOL_GetPrinter_5
1933 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1935 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1936 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1939 DWORD size
, left
= cbBuf
;
1940 BOOL space
= (cbBuf
> 0);
1945 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1947 if(space
&& size
<= left
) {
1948 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1955 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1957 if(space
&& size
<= left
) {
1958 pi5
->pPortName
= (LPWSTR
)ptr
;
1966 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1967 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1969 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1973 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1974 memset(pi5
, 0, sizeof(*pi5
));
1979 /*****************************************************************************
1980 * WINSPOOL_GetPrinter
1982 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1983 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1984 * just a collection of pointers to strings.
1986 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1987 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1990 DWORD size
, needed
= 0;
1992 HKEY hkeyPrinter
, hkeyPrinters
;
1995 TRACE("(%p,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1997 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
1999 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
2001 ERR("Can't create Printers key\n");
2004 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
) != ERROR_SUCCESS
)
2006 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
2007 RegCloseKey(hkeyPrinters
);
2008 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
2015 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
2017 size
= sizeof(PRINTER_INFO_2W
);
2019 ptr
= pPrinter
+ size
;
2021 memset(pPrinter
, 0, size
);
2026 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
2034 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
2036 size
= sizeof(PRINTER_INFO_4W
);
2038 ptr
= pPrinter
+ size
;
2040 memset(pPrinter
, 0, size
);
2045 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
2054 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
2056 size
= sizeof(PRINTER_INFO_5W
);
2058 ptr
= pPrinter
+ size
;
2060 memset(pPrinter
, 0, size
);
2066 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
2073 FIXME("Unimplemented level %ld\n", Level
);
2074 SetLastError(ERROR_INVALID_LEVEL
);
2075 RegCloseKey(hkeyPrinters
);
2076 RegCloseKey(hkeyPrinter
);
2080 RegCloseKey(hkeyPrinter
);
2081 RegCloseKey(hkeyPrinters
);
2083 TRACE("returning %d needed = %ld\n", ret
, needed
);
2084 if(pcbNeeded
) *pcbNeeded
= needed
;
2086 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2090 /*****************************************************************************
2091 * GetPrinterW [WINSPOOL.@]
2093 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
2094 DWORD cbBuf
, LPDWORD pcbNeeded
)
2096 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
2100 /*****************************************************************************
2101 * GetPrinterA [WINSPOOL.@]
2103 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
2104 DWORD cbBuf
, LPDWORD pcbNeeded
)
2106 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
2110 /*****************************************************************************
2111 * WINSPOOL_EnumPrinters
2113 * Implementation of EnumPrintersA|W
2115 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
2116 DWORD dwLevel
, LPBYTE lpbPrinters
,
2117 DWORD cbBuf
, LPDWORD lpdwNeeded
,
2118 LPDWORD lpdwReturned
, BOOL unicode
)
2121 HKEY hkeyPrinters
, hkeyPrinter
;
2122 WCHAR PrinterName
[255];
2123 DWORD needed
= 0, number
= 0;
2124 DWORD used
, i
, left
;
2128 memset(lpbPrinters
, 0, cbBuf
);
2134 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
2135 if(dwType
== PRINTER_ENUM_DEFAULT
)
2138 if (dwType
& PRINTER_ENUM_CONNECTIONS
) {
2139 FIXME("We dont handle PRINTER_ENUM_CONNECTIONS\n");
2140 dwType
&= ~PRINTER_ENUM_CONNECTIONS
; /* we dont handle that */
2141 if(!dwType
) return TRUE
;
2144 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
2145 FIXME("dwType = %08lx\n", dwType
);
2146 SetLastError(ERROR_INVALID_FLAGS
);
2150 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
2152 ERR("Can't create Printers key\n");
2156 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2157 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2158 RegCloseKey(hkeyPrinters
);
2159 ERR("Can't query Printers key\n");
2162 TRACE("Found %ld printers\n", number
);
2166 RegCloseKey(hkeyPrinters
);
2168 *lpdwReturned
= number
;
2172 used
= number
* sizeof(PRINTER_INFO_2W
);
2175 used
= number
* sizeof(PRINTER_INFO_4W
);
2178 used
= number
* sizeof(PRINTER_INFO_5W
);
2182 SetLastError(ERROR_INVALID_LEVEL
);
2183 RegCloseKey(hkeyPrinters
);
2186 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
2188 for(i
= 0; i
< number
; i
++) {
2189 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
2191 ERR("Can't enum key number %ld\n", i
);
2192 RegCloseKey(hkeyPrinters
);
2195 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
2196 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
2198 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
2199 RegCloseKey(hkeyPrinters
);
2204 buf
= lpbPrinters
+ used
;
2205 left
= cbBuf
- used
;
2213 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
2214 left
, &needed
, unicode
);
2216 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
2219 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
2220 left
, &needed
, unicode
);
2222 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
2225 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
2226 left
, &needed
, unicode
);
2228 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
2231 ERR("Shouldn't be here!\n");
2232 RegCloseKey(hkeyPrinter
);
2233 RegCloseKey(hkeyPrinters
);
2236 RegCloseKey(hkeyPrinter
);
2238 RegCloseKey(hkeyPrinters
);
2245 memset(lpbPrinters
, 0, cbBuf
);
2246 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2250 *lpdwReturned
= number
;
2251 SetLastError(ERROR_SUCCESS
);
2256 /******************************************************************
2257 * EnumPrintersW [WINSPOOL.@]
2259 * Enumerates the available printers, print servers and print
2260 * providers, depending on the specified flags, name and level.
2264 * If level is set to 1:
2265 * Not implemented yet!
2266 * Returns TRUE with an empty list.
2268 * If level is set to 2:
2269 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2270 * Returns an array of PRINTER_INFO_2 data structures in the
2271 * lpbPrinters buffer. Note that according to MSDN also an
2272 * OpenPrinter should be performed on every remote printer.
2274 * If level is set to 4 (officially WinNT only):
2275 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2276 * Fast: Only the registry is queried to retrieve printer names,
2277 * no connection to the driver is made.
2278 * Returns an array of PRINTER_INFO_4 data structures in the
2279 * lpbPrinters buffer.
2281 * If level is set to 5 (officially WinNT4/Win9x only):
2282 * Fast: Only the registry is queried to retrieve printer names,
2283 * no connection to the driver is made.
2284 * Returns an array of PRINTER_INFO_5 data structures in the
2285 * lpbPrinters buffer.
2287 * If level set to 3 or 6+:
2288 * returns zero (failure!)
2290 * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
2294 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
2295 * - Only levels 2, 4 and 5 are implemented at the moment.
2296 * - 16-bit printer drivers are not enumerated.
2297 * - Returned amount of bytes used/needed does not match the real Windoze
2298 * implementation (as in this implementation, all strings are part
2299 * of the buffer, whereas Win32 keeps them somewhere else)
2300 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
2303 * - In a regular Wine installation, no registry settings for printers
2304 * exist, which makes this function return an empty list.
2306 BOOL WINAPI
EnumPrintersW(
2307 DWORD dwType
, /* [in] Types of print objects to enumerate */
2308 LPWSTR lpszName
, /* [in] name of objects to enumerate */
2309 DWORD dwLevel
, /* [in] type of printer info structure */
2310 LPBYTE lpbPrinters
, /* [out] buffer which receives info */
2311 DWORD cbBuf
, /* [in] max size of buffer in bytes */
2312 LPDWORD lpdwNeeded
, /* [out] pointer to var: # bytes used/needed */
2313 LPDWORD lpdwReturned
/* [out] number of entries returned */
2316 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
2317 lpdwNeeded
, lpdwReturned
, TRUE
);
2320 /******************************************************************
2321 * EnumPrintersA [WINSPOOL.@]
2324 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
2325 DWORD dwLevel
, LPBYTE lpbPrinters
,
2326 DWORD cbBuf
, LPDWORD lpdwNeeded
,
2327 LPDWORD lpdwReturned
)
2330 UNICODE_STRING lpszNameW
;
2333 pwstrNameW
= asciitounicode(&lpszNameW
,lpszName
);
2334 ret
= WINSPOOL_EnumPrinters(dwType
, pwstrNameW
, dwLevel
, lpbPrinters
, cbBuf
,
2335 lpdwNeeded
, lpdwReturned
, FALSE
);
2336 RtlFreeUnicodeString(&lpszNameW
);
2340 /*****************************************************************************
2341 * WINSPOOL_GetDriverInfoFromReg [internal]
2343 * Enters the information from the registry into the DRIVER_INFO struct
2346 * zero if the printer driver does not exist in the registry
2347 * (only if Level > 1) otherwise nonzero
2349 static BOOL
WINSPOOL_GetDriverInfoFromReg(
2352 LPWSTR pEnvironment
,
2354 LPBYTE ptr
, /* DRIVER_INFO */
2355 LPBYTE pDriverStrings
, /* strings buffer */
2356 DWORD cbBuf
, /* size of string buffer */
2357 LPDWORD pcbNeeded
, /* space needed for str. */
2358 BOOL unicode
) /* type of strings */
2359 { DWORD dw
, size
, tmp
, type
;
2361 LPBYTE strPtr
= pDriverStrings
;
2363 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
2364 debugstr_w(DriverName
), debugstr_w(pEnvironment
),
2365 Level
, ptr
, pDriverStrings
, cbBuf
, unicode
);
2368 *pcbNeeded
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
2369 if (*pcbNeeded
<= cbBuf
)
2370 strcpyW((LPWSTR
)strPtr
, DriverName
);
2372 *pcbNeeded
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0,
2374 if(*pcbNeeded
<= cbBuf
)
2375 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, strPtr
, *pcbNeeded
,
2380 ((PDRIVER_INFO_1W
) ptr
)->pName
= (LPWSTR
) strPtr
;
2384 ((PDRIVER_INFO_3W
) ptr
)->pName
= (LPWSTR
) strPtr
;
2385 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2388 if(!DriverName
[0] || RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
) != ERROR_SUCCESS
) {
2389 ERR("Can't find driver '%s' in registry\n", debugstr_w(DriverName
));
2390 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
2395 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
, &size
) !=
2397 WARN("Can't get Version\n");
2399 ((PDRIVER_INFO_3A
) ptr
)->cVersion
= dw
;
2402 pEnvironment
= (LPWSTR
)DefaultEnvironmentW
;
2404 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
2406 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
2409 if(*pcbNeeded
<= cbBuf
) {
2411 strcpyW((LPWSTR
)strPtr
, pEnvironment
);
2413 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, strPtr
, size
,
2416 ((PDRIVER_INFO_3W
) ptr
)->pEnvironment
= (LPWSTR
)strPtr
;
2417 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2420 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, 0, &size
,
2423 if(*pcbNeeded
<= cbBuf
)
2424 WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, size
, &tmp
,
2427 ((PDRIVER_INFO_3W
) ptr
)->pDriverPath
= (LPWSTR
)strPtr
;
2428 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2431 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, 0, &size
,
2434 if(*pcbNeeded
<= cbBuf
)
2435 WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, size
,
2438 ((PDRIVER_INFO_3W
) ptr
)->pDataFile
= (LPWSTR
)strPtr
;
2439 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2442 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
2443 0, &size
, unicode
)) {
2445 if(*pcbNeeded
<= cbBuf
)
2446 WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
2447 size
, &tmp
, unicode
);
2449 ((PDRIVER_INFO_3W
) ptr
)->pConfigFile
= (LPWSTR
)strPtr
;
2450 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2454 RegCloseKey(hkeyDriver
);
2455 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2459 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
, 0, &size
,
2462 if(*pcbNeeded
<= cbBuf
)
2463 WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
,
2464 size
, &tmp
, unicode
);
2466 ((PDRIVER_INFO_3W
) ptr
)->pHelpFile
= (LPWSTR
)strPtr
;
2467 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2470 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
, 0,
2473 if(*pcbNeeded
<= cbBuf
)
2474 WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
,
2475 size
, &tmp
, unicode
);
2477 ((PDRIVER_INFO_3W
) ptr
)->pDependentFiles
= (LPWSTR
)strPtr
;
2478 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2481 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
, 0, &size
,
2484 if(*pcbNeeded
<= cbBuf
)
2485 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
2486 size
, &tmp
, unicode
);
2488 ((PDRIVER_INFO_3W
) ptr
)->pMonitorName
= (LPWSTR
)strPtr
;
2489 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2492 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, strPtr
, 0, &size
,
2495 if(*pcbNeeded
<= cbBuf
)
2496 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
2497 size
, &tmp
, unicode
);
2499 ((PDRIVER_INFO_3W
) ptr
)->pDefaultDataType
= (LPWSTR
)strPtr
;
2500 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2503 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2504 RegCloseKey(hkeyDriver
);
2508 /*****************************************************************************
2509 * WINSPOOL_GetPrinterDriver
2511 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
2512 DWORD Level
, LPBYTE pDriverInfo
,
2513 DWORD cbBuf
, LPDWORD pcbNeeded
,
2517 WCHAR DriverName
[100];
2518 DWORD ret
, type
, size
, needed
= 0;
2520 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDrivers
;
2522 TRACE("(%p,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
2523 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
2525 ZeroMemory(pDriverInfo
, cbBuf
);
2527 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
2529 if(Level
< 1 || Level
> 3) {
2530 SetLastError(ERROR_INVALID_LEVEL
);
2533 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
2535 ERR("Can't create Printers key\n");
2538 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
)
2540 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
2541 RegCloseKey(hkeyPrinters
);
2542 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
2545 size
= sizeof(DriverName
);
2547 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
2548 (LPBYTE
)DriverName
, &size
);
2549 RegCloseKey(hkeyPrinter
);
2550 RegCloseKey(hkeyPrinters
);
2551 if(ret
!= ERROR_SUCCESS
) {
2552 ERR("Can't get DriverName for printer %s\n", debugstr_w(name
));
2556 hkeyDrivers
= WINSPOOL_OpenDriverReg( pEnvironment
, TRUE
);
2558 ERR("Can't create Drivers key\n");
2564 size
= sizeof(DRIVER_INFO_1W
);
2567 size
= sizeof(DRIVER_INFO_2W
);
2570 size
= sizeof(DRIVER_INFO_3W
);
2573 ERR("Invalid level\n");
2578 ptr
= pDriverInfo
+ size
;
2580 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverName
,
2581 pEnvironment
, Level
, pDriverInfo
,
2582 (cbBuf
< size
) ? NULL
: ptr
,
2583 (cbBuf
< size
) ? 0 : cbBuf
- size
,
2584 &needed
, unicode
)) {
2585 RegCloseKey(hkeyDrivers
);
2589 RegCloseKey(hkeyDrivers
);
2591 if(pcbNeeded
) *pcbNeeded
= size
+ needed
;
2592 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2593 if(cbBuf
>= needed
) return TRUE
;
2594 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2598 /*****************************************************************************
2599 * GetPrinterDriverA [WINSPOOL.@]
2601 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
2602 DWORD Level
, LPBYTE pDriverInfo
,
2603 DWORD cbBuf
, LPDWORD pcbNeeded
)
2606 UNICODE_STRING pEnvW
;
2609 pwstrEnvW
= asciitounicode(&pEnvW
, pEnvironment
);
2610 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pwstrEnvW
, Level
, pDriverInfo
,
2611 cbBuf
, pcbNeeded
, FALSE
);
2612 RtlFreeUnicodeString(&pEnvW
);
2615 /*****************************************************************************
2616 * GetPrinterDriverW [WINSPOOL.@]
2618 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
2619 DWORD Level
, LPBYTE pDriverInfo
,
2620 DWORD cbBuf
, LPDWORD pcbNeeded
)
2622 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
2623 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
2626 /*****************************************************************************
2627 * GetPrinterDriverDirectoryW [WINSPOOL.@]
2629 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
2630 DWORD Level
, LPBYTE pDriverDirectory
,
2631 DWORD cbBuf
, LPDWORD pcbNeeded
)
2635 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", debugstr_w(pName
),
2636 debugstr_w(pEnvironment
), Level
, pDriverDirectory
, cbBuf
, pcbNeeded
);
2638 FIXME("pName = `%s' - unsupported\n", debugstr_w(pName
));
2639 SetLastError(ERROR_INVALID_PARAMETER
);
2642 if(pEnvironment
!= NULL
) {
2643 FIXME("pEnvironment = `%s' - unsupported\n", debugstr_w(pEnvironment
));
2644 SetLastError(ERROR_INVALID_ENVIRONMENT
);
2647 if(Level
!= 1) /* win95 ignores this so we just carry on */
2648 WARN("Level = %ld - assuming 1\n", Level
);
2650 /* FIXME should read from registry */
2651 needed
= GetSystemDirectoryW( (LPWSTR
)pDriverDirectory
, cbBuf
/sizeof(WCHAR
));
2652 /* GetSystemDirectoryW returns number of TCHAR without '\0'
2656 needed
*=sizeof(WCHAR
);
2659 *pcbNeeded
= needed
;
2660 TRACE("required <%08lx>\n", *pcbNeeded
);
2661 if(needed
> cbBuf
) {
2662 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2669 /*****************************************************************************
2670 * GetPrinterDriverDirectoryA [WINSPOOL.@]
2672 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
2673 DWORD Level
, LPBYTE pDriverDirectory
,
2674 DWORD cbBuf
, LPDWORD pcbNeeded
)
2676 UNICODE_STRING nameW
, environmentW
;
2679 INT len
= cbBuf
* sizeof(WCHAR
)/sizeof(CHAR
);
2680 WCHAR
*driverDirectoryW
= NULL
;
2682 if (len
) driverDirectoryW
= HeapAlloc( GetProcessHeap(), 0, len
);
2684 if(pName
) RtlCreateUnicodeStringFromAsciiz(&nameW
, pName
);
2685 else nameW
.Buffer
= NULL
;
2686 if(pEnvironment
) RtlCreateUnicodeStringFromAsciiz(&environmentW
, pEnvironment
);
2687 else environmentW
.Buffer
= NULL
;
2689 ret
= GetPrinterDriverDirectoryW( nameW
.Buffer
, environmentW
.Buffer
, Level
,
2690 (LPBYTE
)driverDirectoryW
, len
, &pcbNeededW
);
2693 needed
= 1 + WideCharToMultiByte( CP_ACP
, 0, driverDirectoryW
, -1,
2694 pDriverDirectory
, cbBuf
, NULL
, NULL
);
2696 *pcbNeeded
= needed
;
2697 ret
= (needed
<= cbBuf
) ? TRUE
: FALSE
;
2699 if(pcbNeeded
) *pcbNeeded
= pcbNeededW
* sizeof(CHAR
)/sizeof(WCHAR
);
2701 TRACE("provided<%ld> required <%ld>\n", cbBuf
, *pcbNeeded
);
2703 if(driverDirectoryW
)
2704 HeapFree( GetProcessHeap(), 0, driverDirectoryW
);
2705 RtlFreeUnicodeString(&environmentW
);
2706 RtlFreeUnicodeString(&nameW
);
2711 /*****************************************************************************
2712 * AddPrinterDriverA [WINSPOOL.@]
2714 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
2717 HKEY hkeyDrivers
, hkeyName
;
2719 TRACE("(%s,%ld,%p)\n",debugstr_a(pName
),level
,pDriverInfo
);
2721 if(level
!= 2 && level
!= 3) {
2722 SetLastError(ERROR_INVALID_LEVEL
);
2726 FIXME("pName= %s - unsupported\n", debugstr_a(pName
));
2727 SetLastError(ERROR_INVALID_PARAMETER
);
2731 WARN("pDriverInfo == NULL\n");
2732 SetLastError(ERROR_INVALID_PARAMETER
);
2737 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
2739 memset(&di3
, 0, sizeof(di3
));
2740 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
2743 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
2745 SetLastError(ERROR_INVALID_PARAMETER
);
2748 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
2749 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
2750 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
2751 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
2753 hkeyDrivers
= WINSPOOL_OpenDriverReg(di3
.pEnvironment
, FALSE
);
2756 ERR("Can't create Drivers key\n");
2760 if(level
== 2) { /* apparently can't overwrite with level2 */
2761 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2762 RegCloseKey(hkeyName
);
2763 RegCloseKey(hkeyDrivers
);
2764 WARN("Trying to create existing printer driver %s\n", debugstr_a(di3
.pName
));
2765 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2769 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2770 RegCloseKey(hkeyDrivers
);
2771 ERR("Can't create Name key\n");
2774 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2776 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2777 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2778 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2780 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2781 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2782 di3
.pDependentFiles
, 0);
2783 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2784 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2785 RegCloseKey(hkeyName
);
2786 RegCloseKey(hkeyDrivers
);
2790 /*****************************************************************************
2791 * AddPrinterDriverW [WINSPOOL.@]
2793 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2796 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2802 /*****************************************************************************
2803 * PrinterProperties [WINSPOOL.@]
2805 * Displays a dialog to set the properties of the printer.
2808 * nonzero on success or zero on failure
2811 * implemented as stub only
2813 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* [in] handle to parent window */
2814 HANDLE hPrinter
/* [in] handle to printer object */
2816 FIXME("(%p,%p): stub\n", hWnd
, hPrinter
);
2817 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2821 /*****************************************************************************
2822 * EnumJobsA [WINSPOOL.@]
2825 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2826 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2829 FIXME("(%p,first=%ld,no=%ld,level=%ld,job=%p,cb=%ld,%p,%p), stub!\n",
2830 hPrinter
, FirstJob
, NoJobs
, Level
, pJob
, cbBuf
, pcbNeeded
, pcReturned
2832 if(pcbNeeded
) *pcbNeeded
= 0;
2833 if(pcReturned
) *pcReturned
= 0;
2838 /*****************************************************************************
2839 * EnumJobsW [WINSPOOL.@]
2842 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2843 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2846 FIXME("(%p,first=%ld,no=%ld,level=%ld,job=%p,cb=%ld,%p,%p), stub!\n",
2847 hPrinter
, FirstJob
, NoJobs
, Level
, pJob
, cbBuf
, pcbNeeded
, pcReturned
2849 if(pcbNeeded
) *pcbNeeded
= 0;
2850 if(pcReturned
) *pcReturned
= 0;
2854 /*****************************************************************************
2855 * WINSPOOL_EnumPrinterDrivers [internal]
2857 * Delivers information about all printer drivers installed on the
2858 * localhost or a given server
2861 * nonzero on success or zero on failure. If the buffer for the returned
2862 * information is too small the function will return an error
2865 * - only implemented for localhost, foreign hosts will return an error
2867 static BOOL
WINSPOOL_EnumPrinterDrivers(LPWSTR pName
, LPWSTR pEnvironment
,
2868 DWORD Level
, LPBYTE pDriverInfo
,
2869 DWORD cbBuf
, LPDWORD pcbNeeded
,
2870 LPDWORD pcReturned
, BOOL unicode
)
2873 DWORD i
, needed
, number
= 0, size
= 0;
2874 WCHAR DriverNameW
[255];
2877 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2878 debugstr_w(pName
), debugstr_w(pEnvironment
),
2879 Level
, pDriverInfo
, cbBuf
, unicode
);
2881 /* check for local drivers */
2883 ERR("remote drivers unsupported! Current remote host is %s\n",
2888 /* check input parameter */
2889 if((Level
< 1) || (Level
> 3)) {
2890 ERR("unsupported level %ld \n", Level
);
2894 /* initialize return values */
2896 memset( pDriverInfo
, 0, cbBuf
);
2900 hkeyDrivers
= WINSPOOL_OpenDriverReg(pEnvironment
, TRUE
);
2902 ERR("Can't open Drivers key\n");
2906 if(RegQueryInfoKeyA(hkeyDrivers
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2907 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2908 RegCloseKey(hkeyDrivers
);
2909 ERR("Can't query Drivers key\n");
2912 TRACE("Found %ld Drivers\n", number
);
2914 /* get size of single struct
2915 * unicode and ascii structure have the same size
2919 size
= sizeof(DRIVER_INFO_1A
);
2922 size
= sizeof(DRIVER_INFO_2A
);
2925 size
= sizeof(DRIVER_INFO_3A
);
2929 /* calculate required buffer size */
2930 *pcbNeeded
= size
* number
;
2932 for( i
= 0, ptr
= (pDriverInfo
&& (cbBuf
>= size
)) ? pDriverInfo
: NULL
;
2934 i
++, ptr
= (ptr
&& (cbBuf
>= size
* i
)) ? ptr
+ size
: NULL
) {
2935 if(RegEnumKeyW(hkeyDrivers
, i
, DriverNameW
, sizeof(DriverNameW
))
2937 ERR("Can't enum key number %ld\n", i
);
2938 RegCloseKey(hkeyDrivers
);
2941 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverNameW
,
2942 pEnvironment
, Level
, ptr
,
2943 (cbBuf
< *pcbNeeded
) ? NULL
: pDriverInfo
+ *pcbNeeded
,
2944 (cbBuf
< *pcbNeeded
) ? 0 : cbBuf
- *pcbNeeded
,
2945 &needed
, unicode
)) {
2946 RegCloseKey(hkeyDrivers
);
2949 (*pcbNeeded
) += needed
;
2952 RegCloseKey(hkeyDrivers
);
2954 if(cbBuf
< *pcbNeeded
){
2955 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2962 /*****************************************************************************
2963 * EnumPrinterDriversW [WINSPOOL.@]
2965 * see function EnumPrinterDrivers for RETURNS, BUGS
2967 BOOL WINAPI
EnumPrinterDriversW(LPWSTR pName
, LPWSTR pEnvironment
, DWORD Level
,
2968 LPBYTE pDriverInfo
, DWORD cbBuf
,
2969 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2971 return WINSPOOL_EnumPrinterDrivers(pName
, pEnvironment
, Level
, pDriverInfo
,
2972 cbBuf
, pcbNeeded
, pcReturned
, TRUE
);
2975 /*****************************************************************************
2976 * EnumPrinterDriversA [WINSPOOL.@]
2978 * see function EnumPrinterDrivers for RETURNS, BUGS
2980 BOOL WINAPI
EnumPrinterDriversA(LPSTR pName
, LPSTR pEnvironment
, DWORD Level
,
2981 LPBYTE pDriverInfo
, DWORD cbBuf
,
2982 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2984 UNICODE_STRING pNameW
, pEnvironmentW
;
2985 PWSTR pwstrNameW
, pwstrEnvironmentW
;
2987 pwstrNameW
= asciitounicode(&pNameW
, pName
);
2988 pwstrEnvironmentW
= asciitounicode(&pEnvironmentW
, pEnvironment
);
2990 ret
= WINSPOOL_EnumPrinterDrivers(pwstrNameW
, pwstrEnvironmentW
,
2991 Level
, pDriverInfo
, cbBuf
, pcbNeeded
,
2993 RtlFreeUnicodeString(&pNameW
);
2994 RtlFreeUnicodeString(&pEnvironmentW
);
2999 static CHAR PortMonitor
[] = "Wine Port Monitor";
3000 static CHAR PortDescription
[] = "Wine Port";
3002 /******************************************************************************
3003 * EnumPortsA (WINSPOOL.@)
3005 BOOL WINAPI
EnumPortsA(LPSTR name
,DWORD level
,LPBYTE buffer
,DWORD bufsize
,
3006 LPDWORD bufneeded
,LPDWORD bufreturned
)
3009 DWORD info_size
, ofs
, i
, printer_count
, serial_count
, count
, n
, r
;
3010 const LPCSTR szSerialPortKey
= "Software\\Wine\\Wine\\Config\\serialports";
3011 const LPCSTR szPrinterPortKey
= "Software\\Wine\\Wine\\Config\\spooler";
3012 HKEY hkey_serial
, hkey_printer
;
3014 TRACE("(%s,%ld,%p,%ld,%p,%p)\n",
3015 name
,level
,buffer
,bufsize
,bufneeded
,bufreturned
);
3020 info_size
= sizeof (PORT_INFO_1A
);
3023 info_size
= sizeof (PORT_INFO_2A
);
3026 SetLastError(ERROR_INVALID_LEVEL
);
3030 /* see how many exist */
3036 r
= RegOpenKeyA( HKEY_LOCAL_MACHINE
, szSerialPortKey
, &hkey_serial
);
3037 if (r
== ERROR_SUCCESS
)
3039 RegQueryInfoKeyA ( hkey_serial
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
3040 &serial_count
, NULL
, NULL
, NULL
, NULL
);
3043 r
= RegOpenKeyA( HKEY_LOCAL_MACHINE
, szPrinterPortKey
, &hkey_printer
);
3044 if ( r
== ERROR_SUCCESS
)
3046 RegQueryInfoKeyA( hkey_printer
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
3047 &printer_count
, NULL
, NULL
, NULL
, NULL
);
3049 count
= serial_count
+ printer_count
;
3051 /* then fill in the structure info structure once
3052 we know the offset to the first string */
3054 memset( buffer
, 0, bufsize
);
3056 ofs
= info_size
*count
;
3057 for ( i
=0; i
<count
; i
++)
3059 DWORD vallen
= sizeof(portname
) - 1;
3061 /* get the serial port values, then the printer values */
3062 if ( i
< serial_count
)
3063 r
= RegEnumValueA( hkey_serial
, i
,
3064 portname
, &vallen
, NULL
, NULL
, NULL
, 0 );
3066 r
= RegEnumValueA( hkey_printer
, i
-serial_count
,
3067 portname
, &vallen
, NULL
, NULL
, NULL
, 0 );
3072 /* add a colon if necessary, and make it upper case */
3073 CharUpperBuffA(portname
,vallen
);
3074 if (strcasecmp(portname
,"nul")!=0)
3075 if (vallen
&& (portname
[vallen
-1] != ':') )
3076 lstrcatA(portname
,":");
3078 /* add the port info structure if we can fit it */
3079 if ( info_size
*(n
+1) < bufsize
)
3083 PORT_INFO_1A
*info
= (PORT_INFO_1A
*) &buffer
[info_size
*n
];
3084 info
->pName
= (LPSTR
) &buffer
[ofs
];
3086 else if ( level
== 2)
3088 PORT_INFO_2A
*info
= (PORT_INFO_2A
*) &buffer
[info_size
*n
];
3089 info
->pPortName
= (LPSTR
) &buffer
[ofs
];
3090 /* FIXME: fill in more stuff here */
3091 info
->pMonitorName
= PortMonitor
;
3092 info
->pDescription
= PortDescription
;
3093 info
->fPortType
= PORT_TYPE_WRITE
|PORT_TYPE_READ
;
3096 /* add the name of the port if we can fit it */
3097 if ( ofs
< bufsize
)
3098 lstrcpynA(&buffer
[ofs
],portname
,bufsize
- ofs
);
3101 ofs
+= lstrlenA(portname
)+1;
3105 RegCloseKey(hkey_serial
);
3106 RegCloseKey(hkey_printer
);
3112 *bufreturned
= count
;
3117 /******************************************************************************
3118 * GetDefaultPrinterA (WINSPOOL.@)
3120 BOOL WINAPI
GetDefaultPrinterA(LPSTR name
, LPDWORD namesize
)
3126 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
3130 if (!GetProfileStringA ("windows", "device", "", name
, *namesize
))
3132 SetLastError (ERROR_FILE_NOT_FOUND
);
3136 if ((ptr
= strchr (name
, ',')) == NULL
)
3138 SetLastError (ERROR_FILE_NOT_FOUND
);
3143 *namesize
= strlen (name
) + 1;
3148 /******************************************************************************
3149 * GetDefaultPrinterW (WINSPOOL.@)
3151 BOOL WINAPI
GetDefaultPrinterW(LPWSTR name
, LPDWORD namesize
)
3158 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
3162 buf
= HeapAlloc (GetProcessHeap (), 0, *namesize
);
3163 ret
= GetDefaultPrinterA (buf
, namesize
);
3166 DWORD len
= MultiByteToWideChar (CP_ACP
, 0, buf
, -1, name
, *namesize
);
3169 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
3172 else *namesize
= len
;
3175 HeapFree (GetProcessHeap (), 0, buf
);
3180 /******************************************************************************
3181 * SetPrinterDataExA (WINSPOOL.@)
3183 DWORD WINAPI
SetPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
,
3184 LPCSTR pValueName
, DWORD Type
,
3185 LPBYTE pData
, DWORD cbData
)
3187 HKEY hkeyPrinter
, hkeySubkey
;
3190 TRACE("(%p, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_a(pKeyName
),
3191 debugstr_a(pValueName
), Type
, pData
, cbData
);
3193 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
3197 if((ret
= RegCreateKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
3199 ERR("Can't create subkey %s\n", debugstr_a(pKeyName
));
3200 RegCloseKey(hkeyPrinter
);
3203 ret
= RegSetValueExA(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
3204 RegCloseKey(hkeySubkey
);
3205 RegCloseKey(hkeyPrinter
);
3209 /******************************************************************************
3210 * SetPrinterDataExW (WINSPOOL.@)
3212 DWORD WINAPI
SetPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
,
3213 LPCWSTR pValueName
, DWORD Type
,
3214 LPBYTE pData
, DWORD cbData
)
3216 HKEY hkeyPrinter
, hkeySubkey
;
3219 TRACE("(%p, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_w(pKeyName
),
3220 debugstr_w(pValueName
), Type
, pData
, cbData
);
3222 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
3226 if((ret
= RegCreateKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
3228 ERR("Can't create subkey %s\n", debugstr_w(pKeyName
));
3229 RegCloseKey(hkeyPrinter
);
3232 ret
= RegSetValueExW(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
3233 RegCloseKey(hkeySubkey
);
3234 RegCloseKey(hkeyPrinter
);
3238 /******************************************************************************
3239 * SetPrinterDataA (WINSPOOL.@)
3241 DWORD WINAPI
SetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, DWORD Type
,
3242 LPBYTE pData
, DWORD cbData
)
3244 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
,
3248 /******************************************************************************
3249 * SetPrinterDataW (WINSPOOL.@)
3251 DWORD WINAPI
SetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, DWORD Type
,
3252 LPBYTE pData
, DWORD cbData
)
3254 return SetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, Type
,
3258 /******************************************************************************
3259 * GetPrinterDataExA (WINSPOOL.@)
3261 DWORD WINAPI
GetPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
,
3262 LPCSTR pValueName
, LPDWORD pType
,
3263 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3265 HKEY hkeyPrinter
, hkeySubkey
;
3268 TRACE("(%p, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
3269 debugstr_a(pKeyName
), debugstr_a(pValueName
), pType
, pData
, nSize
,
3272 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
3276 if((ret
= RegOpenKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
3278 WARN("Can't open subkey %s\n", debugstr_a(pKeyName
));
3279 RegCloseKey(hkeyPrinter
);
3283 ret
= RegQueryValueExA(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
3284 RegCloseKey(hkeySubkey
);
3285 RegCloseKey(hkeyPrinter
);
3289 /******************************************************************************
3290 * GetPrinterDataExW (WINSPOOL.@)
3292 DWORD WINAPI
GetPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
,
3293 LPCWSTR pValueName
, LPDWORD pType
,
3294 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3296 HKEY hkeyPrinter
, hkeySubkey
;
3299 TRACE("(%p, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
3300 debugstr_w(pKeyName
), debugstr_w(pValueName
), pType
, pData
, nSize
,
3303 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
3307 if((ret
= RegOpenKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
3309 WARN("Can't open subkey %s\n", debugstr_w(pKeyName
));
3310 RegCloseKey(hkeyPrinter
);
3314 ret
= RegQueryValueExW(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
3315 RegCloseKey(hkeySubkey
);
3316 RegCloseKey(hkeyPrinter
);
3320 /******************************************************************************
3321 * GetPrinterDataA (WINSPOOL.@)
3323 DWORD WINAPI
GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
,
3324 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3326 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
,
3327 pData
, nSize
, pcbNeeded
);
3330 /******************************************************************************
3331 * GetPrinterDataW (WINSPOOL.@)
3333 DWORD WINAPI
GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
,
3334 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
3336 return GetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, pType
,
3337 pData
, nSize
, pcbNeeded
);
3340 /*******************************************************************************
3341 * EnumPrinterDataExW [WINSPOOL.@]
3343 DWORD WINAPI
EnumPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
,
3344 LPBYTE pEnumValues
, DWORD cbEnumValues
,
3345 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
3347 HKEY hkPrinter
, hkSubKey
;
3348 DWORD r
, ret
, dwIndex
, cValues
, cbMaxValueNameLen
,
3349 cbValueNameLen
, cbMaxValueLen
, cbValueLen
,
3354 PPRINTER_ENUM_VALUESW ppev
;
3356 TRACE ("%p %s\n", hPrinter
, debugstr_w (pKeyName
));
3358 if (pKeyName
== NULL
|| *pKeyName
== 0)
3359 return ERROR_INVALID_PARAMETER
;
3361 ret
= WINSPOOL_GetOpenedPrinterRegKey (hPrinter
, &hkPrinter
);
3362 if (ret
!= ERROR_SUCCESS
)
3364 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%p) returned %li\n",
3369 ret
= RegOpenKeyExW (hkPrinter
, pKeyName
, 0, KEY_READ
, &hkSubKey
);
3370 if (ret
!= ERROR_SUCCESS
)
3372 r
= RegCloseKey (hkPrinter
);
3373 if (r
!= ERROR_SUCCESS
)
3374 WARN ("RegCloseKey returned %li\n", r
);
3375 TRACE ("RegOpenKeyExW (%p, %s) returned %li\n", hPrinter
,
3376 debugstr_w (pKeyName
), ret
);
3380 ret
= RegCloseKey (hkPrinter
);
3381 if (ret
!= ERROR_SUCCESS
)
3383 ERR ("RegCloseKey returned %li\n", ret
);
3384 r
= RegCloseKey (hkSubKey
);
3385 if (r
!= ERROR_SUCCESS
)
3386 WARN ("RegCloseKey returned %li\n", r
);
3390 ret
= RegQueryInfoKeyW (hkSubKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
3391 &cValues
, &cbMaxValueNameLen
, &cbMaxValueLen
, NULL
, NULL
);
3392 if (ret
!= ERROR_SUCCESS
)
3394 r
= RegCloseKey (hkSubKey
);
3395 if (r
!= ERROR_SUCCESS
)
3396 WARN ("RegCloseKey returned %li\n", r
);
3397 TRACE ("RegQueryInfoKeyW (%p) returned %li\n", hkSubKey
, ret
);
3401 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
3402 "cbMaxValueLen = %li\n", cValues
, cbMaxValueNameLen
, cbMaxValueLen
);
3404 if (cValues
== 0) /* empty key */
3406 r
= RegCloseKey (hkSubKey
);
3407 if (r
!= ERROR_SUCCESS
)
3408 WARN ("RegCloseKey returned %li\n", r
);
3409 *pcbEnumValues
= *pnEnumValues
= 0;
3410 return ERROR_SUCCESS
;
3413 ++cbMaxValueNameLen
; /* allow for trailing '\0' */
3415 hHeap
= GetProcessHeap ();
3418 ERR ("GetProcessHeap failed\n");
3419 r
= RegCloseKey (hkSubKey
);
3420 if (r
!= ERROR_SUCCESS
)
3421 WARN ("RegCloseKey returned %li\n", r
);
3422 return ERROR_OUTOFMEMORY
;
3425 lpValueName
= HeapAlloc (hHeap
, 0, cbMaxValueNameLen
* sizeof (WCHAR
));
3426 if (lpValueName
== NULL
)
3428 ERR ("Failed to allocate %li bytes from process heap\n",
3429 cbMaxValueNameLen
* sizeof (WCHAR
));
3430 r
= RegCloseKey (hkSubKey
);
3431 if (r
!= ERROR_SUCCESS
)
3432 WARN ("RegCloseKey returned %li\n", r
);
3433 return ERROR_OUTOFMEMORY
;
3436 lpValue
= HeapAlloc (hHeap
, 0, cbMaxValueLen
);
3437 if (lpValue
== NULL
)
3439 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen
);
3440 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3441 WARN ("HeapFree failed with code %li\n", GetLastError ());
3442 r
= RegCloseKey (hkSubKey
);
3443 if (r
!= ERROR_SUCCESS
)
3444 WARN ("RegCloseKey returned %li\n", r
);
3445 return ERROR_OUTOFMEMORY
;
3448 TRACE ("pass 1: calculating buffer required for all names and values\n");
3450 cbBufSize
= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
3452 TRACE ("%li bytes required for %li headers\n", cbBufSize
, cValues
);
3454 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
3456 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
3457 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
3458 NULL
, NULL
, lpValue
, &cbValueLen
);
3459 if (ret
!= ERROR_SUCCESS
)
3461 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3462 WARN ("HeapFree failed with code %li\n", GetLastError ());
3463 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3464 WARN ("HeapFree failed with code %li\n", GetLastError ());
3465 r
= RegCloseKey (hkSubKey
);
3466 if (r
!= ERROR_SUCCESS
)
3467 WARN ("RegCloseKey returned %li\n", r
);
3468 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
3472 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
3473 debugstr_w (lpValueName
), dwIndex
,
3474 (cbValueNameLen
+ 1) * sizeof (WCHAR
), cbValueLen
);
3476 cbBufSize
+= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
3477 cbBufSize
+= cbValueLen
;
3480 TRACE ("%li bytes required for all %li values\n", cbBufSize
, cValues
);
3482 *pcbEnumValues
= cbBufSize
;
3483 *pnEnumValues
= cValues
;
3485 if (cbEnumValues
< cbBufSize
) /* buffer too small */
3487 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3488 WARN ("HeapFree failed with code %li\n", GetLastError ());
3489 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3490 WARN ("HeapFree failed with code %li\n", GetLastError ());
3491 r
= RegCloseKey (hkSubKey
);
3492 if (r
!= ERROR_SUCCESS
)
3493 WARN ("RegCloseKey returned %li\n", r
);
3494 TRACE ("%li byte buffer is not large enough\n", cbEnumValues
);
3495 return ERROR_MORE_DATA
;
3498 TRACE ("pass 2: copying all names and values to buffer\n");
3500 ppev
= (PPRINTER_ENUM_VALUESW
) pEnumValues
; /* array of structs */
3501 pEnumValues
+= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
3503 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
3505 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
3506 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
3507 NULL
, &dwType
, lpValue
, &cbValueLen
);
3508 if (ret
!= ERROR_SUCCESS
)
3510 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3511 WARN ("HeapFree failed with code %li\n", GetLastError ());
3512 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3513 WARN ("HeapFree failed with code %li\n", GetLastError ());
3514 r
= RegCloseKey (hkSubKey
);
3515 if (r
!= ERROR_SUCCESS
)
3516 WARN ("RegCloseKey returned %li\n", r
);
3517 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
3521 cbValueNameLen
= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
3522 memcpy (pEnumValues
, lpValueName
, cbValueNameLen
);
3523 ppev
[dwIndex
].pValueName
= (LPWSTR
) pEnumValues
;
3524 pEnumValues
+= cbValueNameLen
;
3526 /* return # of *bytes* (including trailing \0), not # of chars */
3527 ppev
[dwIndex
].cbValueName
= cbValueNameLen
;
3529 ppev
[dwIndex
].dwType
= dwType
;
3531 memcpy (pEnumValues
, lpValue
, cbValueLen
);
3532 ppev
[dwIndex
].pData
= pEnumValues
;
3533 pEnumValues
+= cbValueLen
;
3535 ppev
[dwIndex
].cbData
= cbValueLen
;
3537 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
3538 debugstr_w (lpValueName
), dwIndex
, cbValueNameLen
, cbValueLen
);
3541 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3543 ret
= GetLastError ();
3544 ERR ("HeapFree failed with code %li\n", ret
);
3545 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3546 WARN ("HeapFree failed with code %li\n", GetLastError ());
3547 r
= RegCloseKey (hkSubKey
);
3548 if (r
!= ERROR_SUCCESS
)
3549 WARN ("RegCloseKey returned %li\n", r
);
3553 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3555 ret
= GetLastError ();
3556 ERR ("HeapFree failed with code %li\n", ret
);
3557 r
= RegCloseKey (hkSubKey
);
3558 if (r
!= ERROR_SUCCESS
)
3559 WARN ("RegCloseKey returned %li\n", r
);
3563 ret
= RegCloseKey (hkSubKey
);
3564 if (ret
!= ERROR_SUCCESS
)
3566 ERR ("RegCloseKey returned %li\n", ret
);
3570 return ERROR_SUCCESS
;
3573 /*******************************************************************************
3574 * EnumPrinterDataExA [WINSPOOL.@]
3576 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
3577 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
3578 * what Windows 2000 SP1 does.
3581 DWORD WINAPI
EnumPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
,
3582 LPBYTE pEnumValues
, DWORD cbEnumValues
,
3583 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
3587 DWORD ret
, dwIndex
, dwBufSize
;
3591 TRACE ("%p %s\n", hPrinter
, pKeyName
);
3593 if (pKeyName
== NULL
|| *pKeyName
== 0)
3594 return ERROR_INVALID_PARAMETER
;
3596 len
= MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, NULL
, 0);
3599 ret
= GetLastError ();
3600 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
3604 hHeap
= GetProcessHeap ();
3607 ERR ("GetProcessHeap failed\n");
3608 return ERROR_OUTOFMEMORY
;
3611 pKeyNameW
= HeapAlloc (hHeap
, 0, len
* sizeof (WCHAR
));
3612 if (pKeyNameW
== NULL
)
3614 ERR ("Failed to allocate %li bytes from process heap\n",
3615 (LONG
) len
* sizeof (WCHAR
));
3616 return ERROR_OUTOFMEMORY
;
3619 if (MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, pKeyNameW
, len
) == 0)
3621 ret
= GetLastError ();
3622 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
3623 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3624 WARN ("HeapFree failed with code %li\n", GetLastError ());
3628 ret
= EnumPrinterDataExW (hPrinter
, pKeyNameW
, pEnumValues
, cbEnumValues
,
3629 pcbEnumValues
, pnEnumValues
);
3630 if (ret
!= ERROR_SUCCESS
)
3632 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3633 WARN ("HeapFree failed with code %li\n", GetLastError ());
3634 TRACE ("EnumPrinterDataExW returned %li\n", ret
);
3638 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3640 ret
= GetLastError ();
3641 ERR ("HeapFree failed with code %li\n", ret
);
3645 if (*pnEnumValues
== 0) /* empty key */
3646 return ERROR_SUCCESS
;
3649 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
3651 PPRINTER_ENUM_VALUESW ppev
=
3652 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
3654 if (dwBufSize
< ppev
->cbValueName
)
3655 dwBufSize
= ppev
->cbValueName
;
3657 if (dwBufSize
< ppev
->cbData
&& (ppev
->dwType
== REG_SZ
||
3658 ppev
->dwType
== REG_EXPAND_SZ
|| ppev
->dwType
== REG_MULTI_SZ
))
3659 dwBufSize
= ppev
->cbData
;
3662 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize
);
3664 pBuffer
= HeapAlloc (hHeap
, 0, dwBufSize
);
3665 if (pBuffer
== NULL
)
3667 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize
);
3668 return ERROR_OUTOFMEMORY
;
3671 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
3673 PPRINTER_ENUM_VALUESW ppev
=
3674 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
3676 len
= WideCharToMultiByte (CP_ACP
, 0, ppev
->pValueName
,
3677 ppev
->cbValueName
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
,
3681 ret
= GetLastError ();
3682 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
3683 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3684 WARN ("HeapFree failed with code %li\n", GetLastError ());
3688 memcpy (ppev
->pValueName
, pBuffer
, len
);
3690 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
3692 if (ppev
->dwType
!= REG_SZ
&& ppev
->dwType
!= REG_EXPAND_SZ
&&
3693 ppev
->dwType
!= REG_MULTI_SZ
)
3696 len
= WideCharToMultiByte (CP_ACP
, 0, (LPWSTR
) ppev
->pData
,
3697 ppev
->cbData
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
, NULL
);
3700 ret
= GetLastError ();
3701 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
3702 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3703 WARN ("HeapFree failed with code %li\n", GetLastError ());
3707 memcpy (ppev
->pData
, pBuffer
, len
);
3709 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
3710 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
3713 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3715 ret
= GetLastError ();
3716 ERR ("HeapFree failed with code %li\n", ret
);
3720 return ERROR_SUCCESS
;
3723 /******************************************************************************
3724 * AddPortA (WINSPOOL.@)
3726 BOOL WINAPI
AddPortA(LPSTR pName
,HWND hWnd
, LPSTR pMonitorName
)
3728 FIXME("(%s, %p, %s\n), stub!\n",pName
,hWnd
,pMonitorName
);
3732 /******************************************************************************
3733 * AddPrinterDriverExW (WINSPOOL.@)
3735 BOOL WINAPI
AddPrinterDriverExW( LPWSTR pName
, DWORD Level
,
3736 LPBYTE pDriverInfo
, DWORD dwFileCopyFlags
)
3738 FIXME("%s %ld %p %ld\n", debugstr_w(pName
),
3739 Level
, pDriverInfo
, dwFileCopyFlags
);
3740 SetLastError(ERROR_PRINTER_DRIVER_BLOCKED
);
3744 /******************************************************************************
3745 * AddPrinterDriverExA (WINSPOOL.@)
3747 BOOL WINAPI
AddPrinterDriverExA( LPSTR pName
, DWORD Level
,
3748 LPBYTE pDriverInfo
, DWORD dwFileCopyFlags
)
3750 FIXME("%s %ld %p %ld\n", debugstr_a(pName
),
3751 Level
, pDriverInfo
, dwFileCopyFlags
);
3752 SetLastError(ERROR_PRINTER_DRIVER_BLOCKED
);
3756 /******************************************************************************
3757 * DeletePrinterDriverExW (WINSPOOL.@)
3759 BOOL WINAPI
DeletePrinterDriverExW( LPWSTR pName
, LPWSTR pEnvironment
,
3760 LPWSTR pDriverName
, DWORD dwDeleteFlag
, DWORD dwVersionFlag
)
3762 FIXME("%s %s %s %lx %lx\n", debugstr_w(pName
), debugstr_w(pEnvironment
),
3763 debugstr_w(pDriverName
), dwDeleteFlag
, dwVersionFlag
);
3767 /******************************************************************************
3768 * DeletePrinterDriverExA (WINSPOOL.@)
3770 BOOL WINAPI
DeletePrinterDriverExA( LPSTR pName
, LPSTR pEnvironment
,
3771 LPSTR pDriverName
, DWORD dwDeleteFlag
, DWORD dwVersionFlag
)
3773 FIXME("%s %s %s %lx %lx\n", debugstr_a(pName
), debugstr_a(pEnvironment
),
3774 debugstr_a(pDriverName
), dwDeleteFlag
, dwVersionFlag
);
3778 /******************************************************************************
3779 * DeletePrinterDataExW (WINSPOOL.@)
3781 DWORD WINAPI
DeletePrinterDataExW( HANDLE hPrinter
, LPCWSTR pKeyName
,
3784 FIXME("%p %s %s\n", hPrinter
,
3785 debugstr_w(pKeyName
), debugstr_w(pValueName
));
3786 return ERROR_INVALID_PARAMETER
;
3789 /******************************************************************************
3790 * DeletePrinterDataExA (WINSPOOL.@)
3792 DWORD WINAPI
DeletePrinterDataExA( HANDLE hPrinter
, LPCSTR pKeyName
,
3795 FIXME("%p %s %s\n", hPrinter
,
3796 debugstr_a(pKeyName
), debugstr_a(pValueName
));
3797 return ERROR_INVALID_PARAMETER
;
3800 /******************************************************************************
3801 * XcvDataW (WINSPOOL.@)
3804 * There doesn't seem to be an A version...
3806 BOOL WINAPI
XcvDataW( HANDLE hXcv
, LPCWSTR pszDataName
, PBYTE pInputData
,
3807 DWORD cbInputData
, PBYTE pOutputData
, DWORD cbOutputData
,
3808 PDWORD pcbOutputNeeded
, PDWORD pdwStatus
)
3810 FIXME("%p %s %p %ld %p %ld %p %p\n", hXcv
, debugstr_w(pszDataName
),
3811 pInputData
, cbInputData
, pOutputData
,
3812 cbOutputData
, pcbOutputNeeded
, pdwStatus
);