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
33 # include <cups/cups.h>
39 #include "wine/windef16.h"
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(winspool
);
47 static LPWSTR
*printer_array
;
48 static int nb_printers
;
50 static DWORD (WINAPI
*GDI_CallDeviceCapabilities16
)( LPCSTR lpszDevice
, LPCSTR lpszPort
,
51 WORD fwCapability
, LPSTR lpszOutput
,
53 static INT (WINAPI
*GDI_CallExtDeviceMode16
)( HWND hwnd
, LPDEVMODEA lpdmOutput
,
54 LPSTR lpszDevice
, LPSTR lpszPort
,
55 LPDEVMODEA lpdmInput
, LPSTR lpszProfile
,
58 static char Printers
[] =
59 "System\\CurrentControlSet\\control\\Print\\Printers\\";
60 static char Drivers
[] =
61 "System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
63 static WCHAR DefaultEnvironmentW
[] = {'W','i','n','e',0};
65 static WCHAR Configuration_FileW
[] = {'C','o','n','f','i','g','u','r','a','t',
66 'i','o','n',' ','F','i','l','e',0};
67 static WCHAR DatatypeW
[] = {'D','a','t','a','t','y','p','e',0};
68 static WCHAR Data_FileW
[] = {'D','a','t','a',' ','F','i','l','e',0};
69 static WCHAR Default_DevModeW
[] = {'D','e','f','a','u','l','t',' ','D','e','v',
71 static WCHAR Dependent_FilesW
[] = {'D','e','p','e','n','d','e','n','t',' ','F',
73 static WCHAR DescriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
74 static WCHAR DriverW
[] = {'D','r','i','v','e','r',0};
75 static WCHAR Help_FileW
[] = {'H','e','l','p',' ','F','i','l','e',0};
76 static WCHAR LocationW
[] = {'L','o','c','a','t','i','o','n',0};
77 static WCHAR MonitorW
[] = {'M','o','n','i','t','o','r',0};
78 static WCHAR NameW
[] = {'N','a','m','e',0};
79 static WCHAR ParametersW
[] = {'P','a','r','a','m','e','t','e','r','s',0};
80 static WCHAR PortW
[] = {'P','o','r','t',0};
81 static WCHAR Print_ProcessorW
[] = {'P','r','i','n','t',' ','P','r','o','c','e',
83 static WCHAR Printer_DriverW
[] = {'P','r','i','n','t','e','r',' ','D','r','i',
85 static WCHAR PrinterDriverDataW
[] = {'P','r','i','n','t','e','r','D','r','i',
86 'v','e','r','D','a','t','a',0};
87 static WCHAR Separator_FileW
[] = {'S','e','p','a','r','a','t','o','r',' ','F',
89 static WCHAR Share_NameW
[] = {'S','h','a','r','e',' ','N','a','m','e',0};
90 static WCHAR WinPrintW
[] = {'W','i','n','P','r','i','n','t',0};
92 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
);
93 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
94 DWORD Level
, LPBYTE pDriverInfo
,
95 DWORD cbBuf
, LPDWORD pcbNeeded
,
98 WINSPOOL_SetDefaultPrinter(const char *devname
, const char *name
,BOOL force
) {
101 /* If forcing, or no profile string entry for device yet, set the entry
103 * The always change entry if not WINEPS yet is discussable.
106 !GetProfileStringA("windows","device","*",qbuf
,sizeof(qbuf
)) ||
108 !strstr(qbuf
,"WINEPS")
110 char *buf
= HeapAlloc(GetProcessHeap(),0,strlen(name
)+strlen(devname
)+strlen(",WINEPS,LPR:")+1);
112 sprintf(buf
,"%s,WINEPS,LPR:%s",devname
,name
);
113 WriteProfileStringA("windows","device",buf
);
114 HeapFree(GetProcessHeap(),0,buf
);
120 CUPS_LoadPrinters(void) {
122 int i
,nrofdests
,hadprinter
= FALSE
;
123 PRINTER_INFO_2A pinfo2a
;
124 const char* def
= cupsGetDefault();
126 nrofdests
= cupsGetPrinters(&printers
);
128 for (i
=0;i
<nrofdests
;i
++) {
129 const char *ppd
= cupsGetPPD(printers
[i
]);
133 WARN("No ppd file for %s.\n",printers
[i
]);
140 if (!strcmp(def
,printers
[i
]))
141 WINSPOOL_SetDefaultPrinter(printers
[i
],printers
[i
],FALSE
);
142 memset(&pinfo2a
,0,sizeof(pinfo2a
));
143 pinfo2a
.pPrinterName
= printers
[i
];
144 pinfo2a
.pDatatype
= "RAW";
145 pinfo2a
.pPrintProcessor
= "WinPrint";
146 pinfo2a
.pDriverName
= "PS Driver";
147 pinfo2a
.pComment
= "WINEPS Printer using CUPS";
148 pinfo2a
.pLocation
= "<physical location of printer>";
149 port
= HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(printers
[i
])+1);
150 sprintf(port
,"LPR:%s",printers
[i
]);
151 pinfo2a
.pPortName
= port
;
152 pinfo2a
.pParameters
= "<parameters?>";
153 pinfo2a
.pShareName
= "<share name?>";
154 pinfo2a
.pSepFile
= "<sep file?>";
156 devline
=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port
)+1);
157 sprintf(devline
,"WINEPS,%s",port
);
158 WriteProfileStringA("devices",printers
[i
],devline
);
159 HeapFree(GetProcessHeap(),0,devline
);
161 if (!AddPrinterA(NULL
,2,(LPBYTE
)&pinfo2a
)) {
162 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS
)
163 ERR("printer '%s' not added by AddPrinterA (error %ld)\n",printers
[i
],GetLastError());
165 HeapFree(GetProcessHeap(),0,port
);
172 PRINTCAP_ParseEntry(char *pent
,BOOL isfirst
) {
173 PRINTER_INFO_2A pinfo2a
;
174 char *s
,*name
,*prettyname
,*devname
;
178 while (isspace(*pent
)) pent
++;
179 s
= strchr(pent
,':');
180 if (!s
) return FALSE
;
186 /* Determine whether this is a postscript printer. */
188 /* 1. Check if name or aliases contain trigger phrases like 'ps' */
189 if (strstr(name
,"ps") ||
190 strstr(name
,"pd") || /* postscript double page */
191 strstr(name
,"postscript") ||
192 strstr(name
,"PostScript")
194 TRACE("%s has 'ps' style name, assuming postscript.\n",name
);
197 /* 2. Check if this is a remote printer. These usually are postscript
200 if (strstr(pent
,":rm")) {
202 TRACE("%s is remote, assuming postscript.\n",name
);
204 /* 3. Check if we have an input filter program. If we have one, it
205 * most likely is one capable of converting postscript.
206 * (Could probably check for occurrence of 'gs' or 'ghostscript'
207 * in the if file itself.)
209 if (strstr(pent
,":if=/")) {
211 TRACE("%s has inputfilter program, assuming postscript.\n",name
);
214 /* If it is not a postscript printer, we cannot use it. */
219 /* Get longest name, usually the one at the right for later display. */
220 while ((s
=strchr(prettyname
,'|'))) prettyname
= s
+1;
221 s
=strchr(name
,'|');if (s
) *s
='\0';
223 /* prettyname must fit into the dmDeviceName member of DEVMODE struct,
224 * if it is too long, we use it as comment below. */
225 devname
= prettyname
;
226 if (strlen(devname
)>=CCHDEVICENAME
-1)
228 if (strlen(devname
)>=CCHDEVICENAME
-1)
231 if (isfirst
) /* set first entry as default */
232 WINSPOOL_SetDefaultPrinter(devname
,name
,FALSE
);
234 memset(&pinfo2a
,0,sizeof(pinfo2a
));
235 pinfo2a
.pPrinterName
= devname
;
236 pinfo2a
.pDatatype
= "RAW";
237 pinfo2a
.pPrintProcessor
= "WinPrint";
238 pinfo2a
.pDriverName
= "PS Driver";
239 pinfo2a
.pComment
= "WINEPS Printer using LPR";
240 pinfo2a
.pLocation
= prettyname
;
241 port
= HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(name
)+1);
242 sprintf(port
,"LPR:%s",name
);
243 pinfo2a
.pPortName
= port
;
244 pinfo2a
.pParameters
= "<parameters?>";
245 pinfo2a
.pShareName
= "<share name?>";
246 pinfo2a
.pSepFile
= "<sep file?>";
248 devline
=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port
)+1);
249 sprintf(devline
,"WINEPS,%s",port
);
250 WriteProfileStringA("devices",devname
,devline
);
251 HeapFree(GetProcessHeap(),0,devline
);
253 if (!AddPrinterA(NULL
,2,(LPBYTE
)&pinfo2a
)) {
254 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS
)
255 ERR("%s not added by AddPrinterA (%ld)\n",name
,GetLastError());
257 HeapFree(GetProcessHeap(),0,port
);
262 PRINTCAP_LoadPrinters(void) {
263 BOOL hadprinter
= FALSE
, isfirst
= TRUE
;
267 f
= fopen("/etc/printcap","r");
271 while (fgets(buf
,sizeof(buf
),f
)) {
275 s
=strchr(buf
,'\n'); if (s
) *s
='\0';
276 if ((buf
[0]=='#') || (buf
[0]=='\0'))
280 pent
=HeapReAlloc(GetProcessHeap(),0,pent
,strlen(pent
)+strlen(buf
)+2);
283 pent
=HeapAlloc(GetProcessHeap(),0,strlen(buf
)+1);
287 if (strlen(pent
) && (pent
[strlen(pent
)-1] == '\\'))
288 pent
[strlen(pent
)-1] = '\0';
291 } while (fgets(buf
,sizeof(buf
),f
));
293 hadprinter
|= PRINTCAP_ParseEntry(pent
,isfirst
);
295 if (pent
) HeapFree(GetProcessHeap(),0,pent
);
303 static inline DWORD
set_reg_szW(HKEY hkey
, WCHAR
*keyname
, WCHAR
*value
)
305 return RegSetValueExW(hkey
, keyname
, 0, REG_SZ
, (LPBYTE
)value
,
306 lstrlenW(value
) * sizeof(WCHAR
));
310 WINSPOOL_LoadSystemPrinters() {
313 di3a
.cVersion
= 0x400;
314 di3a
.pName
= "PS Driver";
315 di3a
.pEnvironment
= NULL
; /* NULL means auto */
316 di3a
.pDriverPath
= "wineps.drv";
317 di3a
.pDataFile
= "<datafile?>";
318 di3a
.pConfigFile
= "wineps.drv";
319 di3a
.pHelpFile
= "<helpfile?>";
320 di3a
.pDependentFiles
= "<dependend files?>";
321 di3a
.pMonitorName
= "<monitor name?>";
322 di3a
.pDefaultDataType
= "RAW";
324 if (!AddPrinterDriverA(NULL
,3,(LPBYTE
)&di3a
)) {
325 ERR("Failed adding PS Driver (%ld)\n",GetLastError());
329 /* If we have any CUPS based printers, skip looking for printcap printers */
330 if (CUPS_LoadPrinters())
334 /* Check for [ppd] section in config file before parsing /etc/printcap */
336 if (RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\ppd",
337 &hkPPD
) == ERROR_SUCCESS
)
340 PRINTCAP_LoadPrinters();
345 /******************************************************************
346 * WINSPOOL_GetOpenedPrinterEntry
347 * Get the first place empty in the opened printer table
349 static HANDLE
WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name
)
353 for (i
= 0; i
< nb_printers
; i
++) if (!printer_array
[i
]) break;
355 if (i
>= nb_printers
)
357 LPWSTR
*new_array
= HeapReAlloc( GetProcessHeap(), 0, printer_array
,
358 (nb_printers
+ 16) * sizeof(*new_array
) );
359 if (!new_array
) return 0;
360 printer_array
= new_array
;
364 if ((printer_array
[i
] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name
)+1)*sizeof(WCHAR
) )))
366 strcpyW( printer_array
[i
], name
);
367 return (HANDLE
)(i
+ 1);
372 /******************************************************************
373 * WINSPOOL_GetOpenedPrinter
374 * Get the pointer to the opened printer referred by the handle
376 static LPCWSTR
WINSPOOL_GetOpenedPrinter(HANDLE printerHandle
)
378 int idx
= (int)printerHandle
;
379 if ((idx
<= 0) || (idx
> nb_printers
))
381 SetLastError(ERROR_INVALID_HANDLE
);
384 return printer_array
[idx
- 1];
387 /******************************************************************
388 * WINSPOOL_GetOpenedPrinterRegKey
391 static DWORD
WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter
, HKEY
*phkey
)
393 LPCWSTR name
= WINSPOOL_GetOpenedPrinter(hPrinter
);
397 if(!name
) return ERROR_INVALID_HANDLE
;
399 if((ret
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
)) !=
403 if(RegOpenKeyW(hkeyPrinters
, name
, phkey
) != ERROR_SUCCESS
)
405 ERR("Can't find opened printer %s in registry\n",
407 RegCloseKey(hkeyPrinters
);
408 return ERROR_INVALID_PRINTER_NAME
; /* ? */
410 RegCloseKey(hkeyPrinters
);
411 return ERROR_SUCCESS
;
414 /***********************************************************
417 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
420 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
423 Formname
= (dmA
->dmSize
> off_formname
);
424 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
425 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
428 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
429 dmA
->dmSize
- CCHDEVICENAME
);
431 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
432 off_formname
- CCHDEVICENAME
);
433 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
435 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
436 (off_formname
+ CCHFORMNAME
));
439 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
444 /***********************************************************
446 * Creates a unicode copy of supplied devmode on heap
448 static LPDEVMODEW
DEVMODEdupAtoW(HANDLE heap
, const DEVMODEA
*dmA
)
453 ptrdiff_t off_formname
;
456 if(!dmA
) return NULL
;
458 off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
459 Formname
= (dmA
->dmSize
> off_formname
);
460 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
461 dmW
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmA
->dmDriverExtra
);
462 return DEVMODEcpyAtoW(dmW
, dmA
);
465 /***********************************************************
467 * Creates an ascii copy of supplied devmode on heap
469 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
474 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
476 if(!dmW
) return NULL
;
477 Formname
= (dmW
->dmSize
> off_formname
);
478 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
479 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
480 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
481 CCHDEVICENAME
, NULL
, NULL
);
483 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
484 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
486 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
487 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
488 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
489 CCHFORMNAME
, NULL
, NULL
);
490 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
491 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
494 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
499 /***********************************************************
501 * Creates a unicode copy of PRINTER_INFO_2A on heap
503 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
505 LPPRINTER_INFO_2W piW
;
506 if(!piA
) return NULL
;
507 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
508 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
509 piW
->pServerName
= HEAP_strdupAtoW(heap
, 0, piA
->pServerName
);
510 piW
->pPrinterName
= HEAP_strdupAtoW(heap
, 0, piA
->pPrinterName
);
511 piW
->pShareName
= HEAP_strdupAtoW(heap
, 0, piA
->pShareName
);
512 piW
->pPortName
= HEAP_strdupAtoW(heap
, 0, piA
->pPortName
);
513 piW
->pDriverName
= HEAP_strdupAtoW(heap
, 0, piA
->pDriverName
);
514 piW
->pComment
= HEAP_strdupAtoW(heap
, 0, piA
->pComment
);
515 piW
->pLocation
= HEAP_strdupAtoW(heap
, 0, piA
->pLocation
);
516 piW
->pDevMode
= DEVMODEdupAtoW(heap
, piA
->pDevMode
);
517 piW
->pSepFile
= HEAP_strdupAtoW(heap
, 0, piA
->pSepFile
);
518 piW
->pPrintProcessor
= HEAP_strdupAtoW(heap
, 0, piA
->pPrintProcessor
);
519 piW
->pDatatype
= HEAP_strdupAtoW(heap
, 0, piA
->pDatatype
);
520 piW
->pParameters
= HEAP_strdupAtoW(heap
, 0, piA
->pParameters
);
524 /***********************************************************
525 * FREE_PRINTER_INFO_2W
526 * Free PRINTER_INFO_2W and all strings
528 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
532 HeapFree(heap
,0,piW
->pServerName
);
533 HeapFree(heap
,0,piW
->pPrinterName
);
534 HeapFree(heap
,0,piW
->pShareName
);
535 HeapFree(heap
,0,piW
->pPortName
);
536 HeapFree(heap
,0,piW
->pDriverName
);
537 HeapFree(heap
,0,piW
->pComment
);
538 HeapFree(heap
,0,piW
->pLocation
);
539 HeapFree(heap
,0,piW
->pDevMode
);
540 HeapFree(heap
,0,piW
->pSepFile
);
541 HeapFree(heap
,0,piW
->pPrintProcessor
);
542 HeapFree(heap
,0,piW
->pDatatype
);
543 HeapFree(heap
,0,piW
->pParameters
);
544 HeapFree(heap
,0,piW
);
548 /******************************************************************
549 * DeviceCapabilities [WINSPOOL.@]
550 * DeviceCapabilitiesA [WINSPOOL.@]
553 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
554 LPSTR pOutput
, LPDEVMODEA lpdm
)
558 if (!GDI_CallDeviceCapabilities16
)
560 GDI_CallDeviceCapabilities16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
562 if (!GDI_CallDeviceCapabilities16
) return -1;
564 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
566 /* If DC_PAPERSIZE map POINT16s to POINTs */
567 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
568 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
569 POINT
*pt
= (POINT
*)pOutput
;
571 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
572 for(i
= 0; i
< ret
; i
++, pt
++)
577 HeapFree( GetProcessHeap(), 0, tmp
);
583 /*****************************************************************************
584 * DeviceCapabilitiesW [WINSPOOL.@]
586 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
589 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
590 WORD fwCapability
, LPWSTR pOutput
,
591 const DEVMODEW
*pDevMode
)
593 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
594 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
595 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
598 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
599 fwCapability
== DC_FILEDEPENDENCIES
||
600 fwCapability
== DC_PAPERNAMES
)) {
601 /* These need A -> W translation */
604 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
608 switch(fwCapability
) {
613 case DC_FILEDEPENDENCIES
:
617 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
618 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
620 for(i
= 0; i
< ret
; i
++)
621 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
622 pOutput
+ (i
* size
), size
);
623 HeapFree(GetProcessHeap(), 0, pOutputA
);
625 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
626 (LPSTR
)pOutput
, dmA
);
628 HeapFree(GetProcessHeap(),0,pPortA
);
629 HeapFree(GetProcessHeap(),0,pDeviceA
);
630 HeapFree(GetProcessHeap(),0,dmA
);
634 /******************************************************************
635 * DocumentPropertiesA [WINSPOOL.@]
638 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
639 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
640 LPDEVMODEA pDevModeInput
,DWORD fMode
)
642 LPSTR lpName
= pDeviceName
;
645 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
646 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
650 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
652 ERR("no name from hPrinter?\n");
655 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
658 if (!GDI_CallExtDeviceMode16
)
660 GDI_CallExtDeviceMode16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
662 if (!GDI_CallExtDeviceMode16
) {
663 ERR("No CallExtDeviceMode16?\n");
667 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
668 pDevModeInput
, NULL
, fMode
);
671 HeapFree(GetProcessHeap(),0,lpName
);
676 /*****************************************************************************
677 * DocumentPropertiesW (WINSPOOL.@)
679 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
681 LPDEVMODEW pDevModeOutput
,
682 LPDEVMODEW pDevModeInput
, DWORD fMode
)
685 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
686 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
687 LPDEVMODEA pDevModeOutputA
= NULL
;
690 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
691 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
694 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
695 if(ret
< 0) return ret
;
696 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
698 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
699 pDevModeInputA
, fMode
);
701 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
702 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
704 if(fMode
== 0 && ret
> 0)
705 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
706 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
707 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
711 /******************************************************************
712 * OpenPrinterA [WINSPOOL.@]
715 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
716 LPPRINTER_DEFAULTSA pDefault
)
718 LPWSTR lpPrinterNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName
);
719 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
723 DefaultW
.pDatatype
= HEAP_strdupAtoW(GetProcessHeap(), 0,
724 pDefault
->pDatatype
);
725 DefaultW
.pDevMode
= DEVMODEdupAtoW(GetProcessHeap(),
727 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
728 pDefaultW
= &DefaultW
;
730 ret
= OpenPrinterW(lpPrinterNameW
, phPrinter
, pDefaultW
);
732 HeapFree(GetProcessHeap(), 0, DefaultW
.pDatatype
);
733 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
735 HeapFree(GetProcessHeap(), 0, lpPrinterNameW
);
739 /******************************************************************
740 * OpenPrinterW [WINSPOOL.@]
743 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
744 LPPRINTER_DEFAULTSW pDefault
)
746 HKEY hkeyPrinters
, hkeyPrinter
;
748 if (!lpPrinterName
) {
749 FIXME("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
750 SetLastError(ERROR_INVALID_PARAMETER
);
754 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
757 /* Check Printer exists */
758 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
760 ERR("Can't create Printers key\n");
761 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
765 if(lpPrinterName
[0] == '\0' || /* explicitly exclude "" */
766 RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
768 TRACE("Can't find printer %s in registry\n",
769 debugstr_w(lpPrinterName
));
770 RegCloseKey(hkeyPrinters
);
771 SetLastError(ERROR_INVALID_PRINTER_NAME
);
774 RegCloseKey(hkeyPrinter
);
775 RegCloseKey(hkeyPrinters
);
777 if(!phPrinter
) /* This seems to be what win95 does anyway */
780 /* Get the unique handle of the printer*/
781 *phPrinter
= WINSPOOL_GetOpenedPrinterEntry( lpPrinterName
);
783 if (pDefault
!= NULL
)
784 FIXME("Not handling pDefault\n");
789 /******************************************************************
790 * AddMonitorA [WINSPOOL.@]
793 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
795 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
796 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
800 /******************************************************************
801 * DeletePrinterDriverA [WINSPOOL.@]
805 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
807 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
808 debugstr_a(pDriverName
));
809 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
814 /******************************************************************
815 * DeleteMonitorA [WINSPOOL.@]
819 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
821 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
822 debugstr_a(pMonitorName
));
823 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
828 /******************************************************************
829 * DeletePortA [WINSPOOL.@]
833 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
835 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
836 debugstr_a(pPortName
));
837 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
841 /******************************************************************************
842 * SetPrinterW [WINSPOOL.@]
852 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
856 /******************************************************************************
857 * WritePrinter [WINSPOOL.@]
867 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
871 /*****************************************************************************
872 * AddFormA [WINSPOOL.@]
874 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
876 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
880 /*****************************************************************************
881 * AddFormW [WINSPOOL.@]
883 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
885 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
889 /*****************************************************************************
890 * AddJobA [WINSPOOL.@]
892 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
893 DWORD cbBuf
, LPDWORD pcbNeeded
)
895 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
900 /*****************************************************************************
901 * AddJobW [WINSPOOL.@]
903 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
906 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
911 /*****************************************************************************
912 * WINSPOOL_OpenDriverReg [internal]
914 * opens the registry for the printer drivers depending on the given input
915 * variable pEnvironment
918 * the opened hkey on success
921 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
)
923 LPSTR lpKey
, p
= NULL
;
926 (unicode
) ? debugstr_w(pEnvironment
) : debugstr_a(pEnvironment
));
929 p
= (unicode
) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
) :
933 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
935 if(!GetVersionExA( &ver
))
938 switch (ver
.dwPlatformId
) {
939 case VER_PLATFORM_WIN32s
:
940 ERR("win32 style printing used with 16 bits app, try specifying 'win95' Windows version\n");
943 case VER_PLATFORM_WIN32_NT
:
944 p
= "Windows NT x86";
950 TRACE("set environment to %s\n", p
);
953 lpKey
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
954 strlen(p
) + strlen(Drivers
));
955 sprintf( lpKey
, Drivers
, p
);
957 TRACE("%s\n", lpKey
);
959 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, lpKey
, &retval
) !=
963 if(pEnvironment
&& unicode
)
964 HeapFree( GetProcessHeap(), 0, p
);
965 HeapFree( GetProcessHeap(), 0, lpKey
);
970 /*****************************************************************************
971 * AddPrinterW [WINSPOOL.@]
973 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
975 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
979 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
982 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
985 ERR("pName = %s - unsupported\n", debugstr_w(pName
));
986 SetLastError(ERROR_INVALID_PARAMETER
);
990 ERR("Level = %ld, unsupported!\n", Level
);
991 SetLastError(ERROR_INVALID_LEVEL
);
994 if (strlenW(pi
->pPrinterName
) >= CCHDEVICENAME
) {
995 ERR("Printername %s must not exceed length of DEVMODE.dmDeviceName !\n",
996 debugstr_w(pi
->pPrinterName
)
998 SetLastError(ERROR_INVALID_LEVEL
);
1002 SetLastError(ERROR_INVALID_PARAMETER
);
1005 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1007 ERR("Can't create Printers key\n");
1010 if(!RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
)) {
1011 if (!RegQueryValueA(hkeyPrinter
,"Attributes",NULL
,NULL
)) {
1012 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
1013 RegCloseKey(hkeyPrinter
);
1014 RegCloseKey(hkeyPrinters
);
1017 RegCloseKey(hkeyPrinter
);
1019 hkeyDrivers
= WINSPOOL_OpenDriverReg( NULL
, TRUE
);
1021 ERR("Can't create Drivers key\n");
1022 RegCloseKey(hkeyPrinters
);
1025 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
1027 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
1028 RegCloseKey(hkeyPrinters
);
1029 RegCloseKey(hkeyDrivers
);
1030 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
1033 RegCloseKey(hkeyDriver
);
1034 RegCloseKey(hkeyDrivers
);
1036 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
1037 FIXME("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
1038 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
1039 RegCloseKey(hkeyPrinters
);
1043 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
1045 FIXME("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
1046 SetLastError(ERROR_INVALID_PRINTER_NAME
);
1047 RegCloseKey(hkeyPrinters
);
1050 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
1051 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
1052 set_reg_szW(hkeyPrinter
, DatatypeW
, pi
->pDatatype
);
1054 /* See if we can load the driver. We may need the devmode structure anyway
1057 * Note that DocumentPropertiesW will briefly try to open the printer we
1058 * just create to find a DEVMODEA struct (it will use the WINEPS default
1059 * one in case it is not there, so we are ok).
1061 size
= DocumentPropertiesW(0, -1, pi
->pPrinterName
, NULL
, NULL
, 0);
1063 FIXME("DocumentPropertiesW on printer '%s' fails\n", debugstr_w(pi
->pPrinterName
));
1064 size
= sizeof(DEVMODEW
);
1069 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
1071 if (0>DocumentPropertiesW(0,-1,pi
->pPrinterName
,dmW
,NULL
,DM_OUT_BUFFER
)) {
1072 ERR("DocumentPropertiesW on printer '%s' failed!\n", debugstr_w(pi
->pPrinterName
));
1073 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
1076 /* set devmode to printer name */
1077 strcpyW(dmW
->dmDeviceName
,pi
->pPrinterName
);
1080 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
1081 and we support these drivers. NT writes DEVMODEW so somehow
1082 we'll need to distinguish between these when we support NT
1084 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
1085 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
, (LPBYTE
)dmA
,
1086 dmA
->dmSize
+ dmA
->dmDriverExtra
);
1087 HeapFree(GetProcessHeap(), 0, dmA
);
1089 HeapFree(GetProcessHeap(), 0, dmW
);
1090 set_reg_szW(hkeyPrinter
, DescriptionW
, pi
->pComment
);
1091 set_reg_szW(hkeyPrinter
, LocationW
, pi
->pLocation
);
1092 set_reg_szW(hkeyPrinter
, NameW
, pi
->pPrinterName
);
1093 set_reg_szW(hkeyPrinter
, ParametersW
, pi
->pParameters
);
1095 set_reg_szW(hkeyPrinter
, PortW
, pi
->pPortName
);
1096 set_reg_szW(hkeyPrinter
, Print_ProcessorW
, pi
->pPrintProcessor
);
1097 set_reg_szW(hkeyPrinter
, Printer_DriverW
, pi
->pDriverName
);
1098 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
1099 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
1100 set_reg_szW(hkeyPrinter
, Separator_FileW
, pi
->pSepFile
);
1101 set_reg_szW(hkeyPrinter
, Share_NameW
, pi
->pShareName
);
1102 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
1103 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
1104 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
1105 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
1106 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
1107 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
1109 RegCloseKey(hkeyPrinter
);
1110 RegCloseKey(hkeyPrinters
);
1111 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
1112 ERR("OpenPrinter failing\n");
1118 /*****************************************************************************
1119 * AddPrinterA [WINSPOOL.@]
1121 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1124 PRINTER_INFO_2W
*piW
;
1125 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
1128 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
1130 ERR("Level = %ld, unsupported!\n", Level
);
1131 SetLastError(ERROR_INVALID_LEVEL
);
1134 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
1135 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
1137 ret
= AddPrinterW(pNameW
, Level
, (LPBYTE
)piW
);
1139 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
1140 HeapFree(GetProcessHeap(),0,pNameW
);
1145 /*****************************************************************************
1146 * ClosePrinter [WINSPOOL.@]
1148 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
1150 int i
= (int)hPrinter
;
1152 TRACE("Handle %d\n", hPrinter
);
1154 if ((i
<= 0) || (i
> nb_printers
)) return FALSE
;
1155 HeapFree( GetProcessHeap(), 0, printer_array
[i
- 1] );
1156 printer_array
[i
- 1] = NULL
;
1160 /*****************************************************************************
1161 * DeleteFormA [WINSPOOL.@]
1163 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
1165 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
1169 /*****************************************************************************
1170 * DeleteFormW [WINSPOOL.@]
1172 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
1174 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
1178 /*****************************************************************************
1179 * DeletePrinter [WINSPOOL.@]
1181 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
1183 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1186 if(!lpNameW
) return FALSE
;
1187 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1189 ERR("Can't open Printers key\n");
1193 /* This should use a recursive delete see Q142491 or SHDeleteKey */
1194 if(RegDeleteKeyW(hkeyPrinters
, lpNameW
) == ERROR_SUCCESS
) {
1195 SetLastError(ERROR_PRINTER_NOT_FOUND
); /* ?? */
1196 RegCloseKey(hkeyPrinters
);
1200 ClosePrinter(hPrinter
);
1204 /*****************************************************************************
1205 * SetPrinterA [WINSPOOL.@]
1207 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1210 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
1214 /*****************************************************************************
1215 * SetJobA [WINSPOOL.@]
1217 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1218 LPBYTE pJob
, DWORD Command
)
1220 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1225 /*****************************************************************************
1226 * SetJobW [WINSPOOL.@]
1228 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1229 LPBYTE pJob
, DWORD Command
)
1231 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1236 /*****************************************************************************
1237 * GetFormA [WINSPOOL.@]
1239 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1240 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1242 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1243 Level
,pForm
,cbBuf
,pcbNeeded
);
1247 /*****************************************************************************
1248 * GetFormW [WINSPOOL.@]
1250 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1251 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1253 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1254 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1258 /*****************************************************************************
1259 * SetFormA [WINSPOOL.@]
1261 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1264 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1268 /*****************************************************************************
1269 * SetFormW [WINSPOOL.@]
1271 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1274 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1278 /*****************************************************************************
1279 * ReadPrinter [WINSPOOL.@]
1281 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1282 LPDWORD pNoBytesRead
)
1284 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1288 /*****************************************************************************
1289 * ResetPrinterA [WINSPOOL.@]
1291 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1293 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1297 /*****************************************************************************
1298 * ResetPrinterW [WINSPOOL.@]
1300 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1302 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1306 /*****************************************************************************
1307 * WINSPOOL_GetDWORDFromReg
1309 * Return DWORD associated with ValueName from hkey.
1311 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
1313 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
1316 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
1318 if(ret
!= ERROR_SUCCESS
) {
1319 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
1322 if(type
!= REG_DWORD
) {
1323 ERR("Got type %ld\n", type
);
1329 /*****************************************************************************
1330 * WINSPOOL_GetStringFromReg
1332 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1333 * String is stored either as unicode or ascii.
1334 * Bit of a hack here to get the ValueName if we want ascii.
1336 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1337 DWORD buflen
, DWORD
*needed
,
1340 DWORD sz
= buflen
, type
;
1344 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1346 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1347 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1348 HeapFree(GetProcessHeap(),0,ValueNameA
);
1350 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1351 WARN("Got ret = %ld\n", ret
);
1359 /*****************************************************************************
1360 * WINSPOOL_GetDefaultDevMode
1362 * Get a default DevMode values for wineps.
1366 static void WINSPOOL_GetDefaultDevMode(
1368 DWORD buflen
, DWORD
*needed
,
1373 /* fill default DEVMODE - should be read from ppd... */
1374 ZeroMemory( &dm
, sizeof(dm
) );
1375 strcpy(dm
.dmDeviceName
,"wineps");
1376 dm
.dmSpecVersion
= DM_SPECVERSION
;
1377 dm
.dmDriverVersion
= 1;
1378 dm
.dmSize
= sizeof(DEVMODEA
);
1379 dm
.dmDriverExtra
= 0;
1381 DM_ORIENTATION
| DM_PAPERSIZE
|
1382 DM_PAPERLENGTH
| DM_PAPERWIDTH
|
1385 DM_DEFAULTSOURCE
| DM_PRINTQUALITY
|
1386 DM_YRESOLUTION
| DM_TTOPTION
;
1388 dm
.u1
.s1
.dmOrientation
= DMORIENT_PORTRAIT
;
1389 dm
.u1
.s1
.dmPaperSize
= DMPAPER_A4
;
1390 dm
.u1
.s1
.dmPaperLength
= 2970;
1391 dm
.u1
.s1
.dmPaperWidth
= 2100;
1395 dm
.dmDefaultSource
= DMBIN_AUTO
;
1396 dm
.dmPrintQuality
= DMRES_MEDIUM
;
1399 dm
.dmYResolution
= 300; /* 300dpi */
1400 dm
.dmTTOption
= DMTT_BITMAP
;
1403 /* dm.dmLogPixels */
1404 /* dm.dmBitsPerPel */
1405 /* dm.dmPelsWidth */
1406 /* dm.dmPelsHeight */
1407 /* dm.dmDisplayFlags */
1408 /* dm.dmDisplayFrequency */
1409 /* dm.dmICMMethod */
1410 /* dm.dmICMIntent */
1411 /* dm.dmMediaType */
1412 /* dm.dmDitherType */
1413 /* dm.dmReserved1 */
1414 /* dm.dmReserved2 */
1415 /* dm.dmPanningWidth */
1416 /* dm.dmPanningHeight */
1419 if(buflen
>= sizeof(DEVMODEW
)) {
1420 DEVMODEW
*pdmW
= DEVMODEdupAtoW(GetProcessHeap(), &dm
);
1421 memcpy(ptr
, pdmW
, sizeof(DEVMODEW
));
1422 HeapFree(GetProcessHeap(),0,pdmW
);
1424 *needed
= sizeof(DEVMODEW
);
1428 if(buflen
>= sizeof(DEVMODEA
)) {
1429 memcpy(ptr
, &dm
, sizeof(DEVMODEA
));
1431 *needed
= sizeof(DEVMODEA
);
1435 /*****************************************************************************
1436 * WINSPOOL_GetDevModeFromReg
1438 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1439 * DevMode is stored either as unicode or ascii.
1441 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1443 DWORD buflen
, DWORD
*needed
,
1446 DWORD sz
= buflen
, type
;
1449 if (ptr
&& buflen
>=sizeof(DEVMODEA
)) memset(ptr
, 0, sizeof(DEVMODEA
));
1450 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1451 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1452 if (sz
< sizeof(DEVMODEA
))
1454 ERR("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName
),sz
);
1457 /* ensures that dmSize is not erratically bogus if registry is invalid */
1458 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1459 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1461 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1463 DEVMODEW
*dmW
= DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA
*)ptr
);
1464 memcpy(ptr
, dmW
, sz
);
1465 HeapFree(GetProcessHeap(),0,dmW
);
1472 /*********************************************************************
1473 * WINSPOOL_GetPrinter_2
1475 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1476 * The strings are either stored as unicode or ascii.
1478 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1479 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1482 DWORD size
, left
= cbBuf
;
1483 BOOL space
= (cbBuf
> 0);
1488 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1490 if(space
&& size
<= left
) {
1491 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1498 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1500 if(space
&& size
<= left
) {
1501 pi2
->pShareName
= (LPWSTR
)ptr
;
1508 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1510 if(space
&& size
<= left
) {
1511 pi2
->pPortName
= (LPWSTR
)ptr
;
1518 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1520 if(space
&& size
<= left
) {
1521 pi2
->pDriverName
= (LPWSTR
)ptr
;
1528 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1530 if(space
&& size
<= left
) {
1531 pi2
->pComment
= (LPWSTR
)ptr
;
1538 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1540 if(space
&& size
<= left
) {
1541 pi2
->pLocation
= (LPWSTR
)ptr
;
1548 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1550 if(space
&& size
<= left
) {
1551 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1560 MESSAGE( "no DevMode in registry. please setup your printer again.\n"
1561 "use the default hard-coded DevMode(wineps/A4/300dpi).\n" );
1562 WINSPOOL_GetDefaultDevMode(ptr
, left
, &size
, unicode
);
1563 if(space
&& size
<= left
) {
1564 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1571 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1573 if(space
&& size
<= left
) {
1574 pi2
->pSepFile
= (LPWSTR
)ptr
;
1581 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1583 if(space
&& size
<= left
) {
1584 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1591 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1593 if(space
&& size
<= left
) {
1594 pi2
->pDatatype
= (LPWSTR
)ptr
;
1601 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1603 if(space
&& size
<= left
) {
1604 pi2
->pParameters
= (LPWSTR
)ptr
;
1612 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1613 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1614 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1615 "Default Priority");
1616 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1617 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1620 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1621 memset(pi2
, 0, sizeof(*pi2
));
1626 /*********************************************************************
1627 * WINSPOOL_GetPrinter_4
1629 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1631 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1632 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1635 DWORD size
, left
= cbBuf
;
1636 BOOL space
= (cbBuf
> 0);
1641 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1643 if(space
&& size
<= left
) {
1644 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1652 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1655 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1656 memset(pi4
, 0, sizeof(*pi4
));
1661 /*********************************************************************
1662 * WINSPOOL_GetPrinter_5
1664 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1666 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1667 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1670 DWORD size
, left
= cbBuf
;
1671 BOOL space
= (cbBuf
> 0);
1676 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1678 if(space
&& size
<= left
) {
1679 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1686 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1688 if(space
&& size
<= left
) {
1689 pi5
->pPortName
= (LPWSTR
)ptr
;
1697 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1698 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1700 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1704 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1705 memset(pi5
, 0, sizeof(*pi5
));
1710 /*****************************************************************************
1711 * WINSPOOL_GetPrinter
1713 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1714 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1715 * just a collection of pointers to strings.
1717 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1718 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1721 DWORD size
, needed
= 0;
1723 HKEY hkeyPrinter
, hkeyPrinters
;
1726 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1728 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
1730 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1732 ERR("Can't create Printers key\n");
1735 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
) != ERROR_SUCCESS
)
1737 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
1738 RegCloseKey(hkeyPrinters
);
1739 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1746 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
1748 size
= sizeof(PRINTER_INFO_2W
);
1750 ptr
= pPrinter
+ size
;
1752 memset(pPrinter
, 0, size
);
1757 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
1765 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
1767 size
= sizeof(PRINTER_INFO_4W
);
1769 ptr
= pPrinter
+ size
;
1771 memset(pPrinter
, 0, size
);
1776 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
1785 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
1787 size
= sizeof(PRINTER_INFO_5W
);
1789 ptr
= pPrinter
+ size
;
1791 memset(pPrinter
, 0, size
);
1797 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
1804 FIXME("Unimplemented level %ld\n", Level
);
1805 SetLastError(ERROR_INVALID_LEVEL
);
1806 RegCloseKey(hkeyPrinters
);
1807 RegCloseKey(hkeyPrinter
);
1811 RegCloseKey(hkeyPrinter
);
1812 RegCloseKey(hkeyPrinters
);
1814 TRACE("returing %d needed = %ld\n", ret
, needed
);
1815 if(pcbNeeded
) *pcbNeeded
= needed
;
1817 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1821 /*****************************************************************************
1822 * GetPrinterW [WINSPOOL.@]
1824 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1825 DWORD cbBuf
, LPDWORD pcbNeeded
)
1827 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1831 /*****************************************************************************
1832 * GetPrinterA [WINSPOOL.@]
1834 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1835 DWORD cbBuf
, LPDWORD pcbNeeded
)
1837 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1841 /*****************************************************************************
1842 * WINSPOOL_EnumPrinters
1844 * Implementation of EnumPrintersA|W
1846 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
1847 DWORD dwLevel
, LPBYTE lpbPrinters
,
1848 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1849 LPDWORD lpdwReturned
, BOOL unicode
)
1852 HKEY hkeyPrinters
, hkeyPrinter
;
1853 WCHAR PrinterName
[255];
1854 DWORD needed
= 0, number
= 0;
1855 DWORD used
, i
, left
;
1859 memset(lpbPrinters
, 0, cbBuf
);
1865 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1866 if(dwType
== PRINTER_ENUM_DEFAULT
)
1869 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
1870 FIXME("dwType = %08lx\n", dwType
);
1871 SetLastError(ERROR_INVALID_FLAGS
);
1875 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1877 ERR("Can't create Printers key\n");
1881 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
1882 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
1883 RegCloseKey(hkeyPrinters
);
1884 ERR("Can't query Printers key\n");
1887 TRACE("Found %ld printers\n", number
);
1891 RegCloseKey(hkeyPrinters
);
1893 *lpdwReturned
= number
;
1897 used
= number
* sizeof(PRINTER_INFO_2W
);
1900 used
= number
* sizeof(PRINTER_INFO_4W
);
1903 used
= number
* sizeof(PRINTER_INFO_5W
);
1907 SetLastError(ERROR_INVALID_LEVEL
);
1908 RegCloseKey(hkeyPrinters
);
1911 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
1913 for(i
= 0; i
< number
; i
++) {
1914 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
1916 ERR("Can't enum key number %ld\n", i
);
1917 RegCloseKey(hkeyPrinters
);
1920 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
1921 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
1923 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
1924 RegCloseKey(hkeyPrinters
);
1929 buf
= lpbPrinters
+ used
;
1930 left
= cbBuf
- used
;
1938 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
1939 left
, &needed
, unicode
);
1941 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
1944 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
1945 left
, &needed
, unicode
);
1947 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
1950 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
1951 left
, &needed
, unicode
);
1953 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
1956 ERR("Shouldn't be here!\n");
1957 RegCloseKey(hkeyPrinter
);
1958 RegCloseKey(hkeyPrinters
);
1961 RegCloseKey(hkeyPrinter
);
1963 RegCloseKey(hkeyPrinters
);
1970 memset(lpbPrinters
, 0, cbBuf
);
1971 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1975 *lpdwReturned
= number
;
1976 SetLastError(ERROR_SUCCESS
);
1981 /******************************************************************
1982 * EnumPrintersW [WINSPOOL.@]
1984 * Enumerates the available printers, print servers and print
1985 * providers, depending on the specified flags, name and level.
1989 * If level is set to 1:
1990 * Not implemented yet!
1991 * Returns TRUE with an empty list.
1993 * If level is set to 2:
1994 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1995 * Returns an array of PRINTER_INFO_2 data structures in the
1996 * lpbPrinters buffer. Note that according to MSDN also an
1997 * OpenPrinter should be performed on every remote printer.
1999 * If level is set to 4 (officially WinNT only):
2000 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2001 * Fast: Only the registry is queried to retrieve printer names,
2002 * no connection to the driver is made.
2003 * Returns an array of PRINTER_INFO_4 data structures in the
2004 * lpbPrinters buffer.
2006 * If level is set to 5 (officially WinNT4/Win9x only):
2007 * Fast: Only the registry is queried to retrieve printer names,
2008 * no connection to the driver is made.
2009 * Returns an array of PRINTER_INFO_5 data structures in the
2010 * lpbPrinters buffer.
2012 * If level set to 3 or 6+:
2013 * returns zero (failure!)
2015 * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
2019 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
2020 * - Only levels 2, 4 and 5 are implemented at the moment.
2021 * - 16-bit printer drivers are not enumerated.
2022 * - Returned amount of bytes used/needed does not match the real Windoze
2023 * implementation (as in this implementation, all strings are part
2024 * of the buffer, whereas Win32 keeps them somewhere else)
2025 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
2028 * - In a regular Wine installation, no registry settings for printers
2029 * exist, which makes this function return an empty list.
2031 BOOL WINAPI
EnumPrintersW(
2032 DWORD dwType
, /* [in] Types of print objects to enumerate */
2033 LPWSTR lpszName
, /* [in] name of objects to enumerate */
2034 DWORD dwLevel
, /* [in] type of printer info structure */
2035 LPBYTE lpbPrinters
, /* [out] buffer which receives info */
2036 DWORD cbBuf
, /* [in] max size of buffer in bytes */
2037 LPDWORD lpdwNeeded
, /* [out] pointer to var: # bytes used/needed */
2038 LPDWORD lpdwReturned
/* [out] number of entries returned */
2041 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
2042 lpdwNeeded
, lpdwReturned
, TRUE
);
2045 /******************************************************************
2046 * EnumPrintersA [WINSPOOL.@]
2049 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
2050 DWORD dwLevel
, LPBYTE lpbPrinters
,
2051 DWORD cbBuf
, LPDWORD lpdwNeeded
,
2052 LPDWORD lpdwReturned
)
2055 LPWSTR lpszNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpszName
);
2057 ret
= WINSPOOL_EnumPrinters(dwType
, lpszNameW
, dwLevel
, lpbPrinters
, cbBuf
,
2058 lpdwNeeded
, lpdwReturned
, FALSE
);
2059 HeapFree(GetProcessHeap(),0,lpszNameW
);
2063 /*****************************************************************************
2064 * WINSPOOL_GetDriverInfoFromReg [internal]
2066 * Enters the information from the registry into the DRIVER_INFO struct
2069 * zero if the printer driver does not exist in the registry
2070 * (only if Level > 1) otherwise nonzero
2072 static BOOL
WINSPOOL_GetDriverInfoFromReg(
2075 LPWSTR pEnvironment
,
2077 LPBYTE ptr
, /* DRIVER_INFO */
2078 LPBYTE pDriverStrings
, /* strings buffer */
2079 DWORD cbBuf
, /* size of string buffer */
2080 LPDWORD pcbNeeded
, /* space needed for str. */
2081 BOOL unicode
) /* type of strings */
2082 { DWORD dw
, size
, tmp
, type
;
2084 LPBYTE strPtr
= pDriverStrings
;
2086 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
2087 debugstr_w(DriverName
), debugstr_w(pEnvironment
),
2088 Level
, ptr
, pDriverStrings
, cbBuf
, unicode
);
2091 *pcbNeeded
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
2092 if (*pcbNeeded
<= cbBuf
)
2093 strcpyW((LPWSTR
)strPtr
, DriverName
);
2095 *pcbNeeded
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0,
2097 if(*pcbNeeded
<= cbBuf
)
2098 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, strPtr
, *pcbNeeded
,
2103 ((PDRIVER_INFO_1W
) ptr
)->pName
= (LPWSTR
) strPtr
;
2107 ((PDRIVER_INFO_3W
) ptr
)->pName
= (LPWSTR
) strPtr
;
2108 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2111 if(!DriverName
[0] || RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
) != ERROR_SUCCESS
) {
2112 ERR("Can't find driver '%s' in registry\n", debugstr_w(DriverName
));
2113 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
2118 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
, &size
) !=
2120 WARN("Can't get Version\n");
2122 ((PDRIVER_INFO_3A
) ptr
)->cVersion
= dw
;
2125 pEnvironment
= DefaultEnvironmentW
;
2127 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
2129 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
2132 if(*pcbNeeded
<= cbBuf
) {
2134 strcpyW((LPWSTR
)strPtr
, pEnvironment
);
2136 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, strPtr
, size
,
2139 ((PDRIVER_INFO_3W
) ptr
)->pEnvironment
= (LPWSTR
)strPtr
;
2140 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2143 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, 0, &size
,
2146 if(*pcbNeeded
<= cbBuf
)
2147 WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, size
, &tmp
,
2150 ((PDRIVER_INFO_3W
) ptr
)->pDriverPath
= (LPWSTR
)strPtr
;
2151 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
2154 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, 0, &size
,
2157 if(*pcbNeeded
<= cbBuf
)
2158 WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, size
,
2161 ((PDRIVER_INFO_3W
) ptr
)->pDataFile
= (LPWSTR
)strPtr
;
2162 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2165 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
2166 0, &size
, unicode
)) {
2168 if(*pcbNeeded
<= cbBuf
)
2169 WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
2170 size
, &tmp
, unicode
);
2172 ((PDRIVER_INFO_3W
) ptr
)->pConfigFile
= (LPWSTR
)strPtr
;
2173 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2177 RegCloseKey(hkeyDriver
);
2178 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2182 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
, 0, &size
,
2185 if(*pcbNeeded
<= cbBuf
)
2186 WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
,
2187 size
, &tmp
, unicode
);
2189 ((PDRIVER_INFO_3W
) ptr
)->pHelpFile
= (LPWSTR
)strPtr
;
2190 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2193 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
, 0,
2196 if(*pcbNeeded
<= cbBuf
)
2197 WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
,
2198 size
, &tmp
, unicode
);
2200 ((PDRIVER_INFO_3W
) ptr
)->pDependentFiles
= (LPWSTR
)strPtr
;
2201 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2204 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
, 0, &size
,
2207 if(*pcbNeeded
<= cbBuf
)
2208 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
2209 size
, &tmp
, unicode
);
2211 ((PDRIVER_INFO_3W
) ptr
)->pMonitorName
= (LPWSTR
)strPtr
;
2212 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2215 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, strPtr
, 0, &size
,
2218 if(*pcbNeeded
<= cbBuf
)
2219 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
2220 size
, &tmp
, unicode
);
2222 ((PDRIVER_INFO_3W
) ptr
)->pDefaultDataType
= (LPWSTR
)strPtr
;
2223 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
2226 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2227 RegCloseKey(hkeyDriver
);
2231 /*****************************************************************************
2232 * WINSPOOL_GetPrinterDriver
2234 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
2235 DWORD Level
, LPBYTE pDriverInfo
,
2236 DWORD cbBuf
, LPDWORD pcbNeeded
,
2240 WCHAR DriverName
[100];
2241 DWORD ret
, type
, size
, needed
= 0;
2243 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDrivers
;
2245 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
2246 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
2248 ZeroMemory(pDriverInfo
, cbBuf
);
2250 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
2252 if(Level
< 1 || Level
> 3) {
2253 SetLastError(ERROR_INVALID_LEVEL
);
2256 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
2258 ERR("Can't create Printers key\n");
2261 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
)
2263 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
2264 RegCloseKey(hkeyPrinters
);
2265 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
2268 size
= sizeof(DriverName
);
2270 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
2271 (LPBYTE
)DriverName
, &size
);
2272 RegCloseKey(hkeyPrinter
);
2273 RegCloseKey(hkeyPrinters
);
2274 if(ret
!= ERROR_SUCCESS
) {
2275 ERR("Can't get DriverName for printer %s\n", debugstr_w(name
));
2279 hkeyDrivers
= WINSPOOL_OpenDriverReg( pEnvironment
, TRUE
);
2281 ERR("Can't create Drivers key\n");
2287 size
= sizeof(DRIVER_INFO_1W
);
2290 size
= sizeof(DRIVER_INFO_2W
);
2293 size
= sizeof(DRIVER_INFO_3W
);
2296 ERR("Invalid level\n");
2301 ptr
= pDriverInfo
+ size
;
2303 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverName
,
2304 pEnvironment
, Level
, pDriverInfo
,
2305 (cbBuf
< size
) ? NULL
: ptr
,
2306 (cbBuf
< size
) ? 0 : cbBuf
- size
,
2307 &needed
, unicode
)) {
2308 RegCloseKey(hkeyDrivers
);
2312 RegCloseKey(hkeyDrivers
);
2314 if(pcbNeeded
) *pcbNeeded
= size
+ needed
;
2315 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2316 if(cbBuf
>= needed
) return TRUE
;
2317 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2321 /*****************************************************************************
2322 * GetPrinterDriverA [WINSPOOL.@]
2324 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
2325 DWORD Level
, LPBYTE pDriverInfo
,
2326 DWORD cbBuf
, LPDWORD pcbNeeded
)
2329 LPWSTR pEnvW
= HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment
);
2330 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pEnvW
, Level
, pDriverInfo
,
2331 cbBuf
, pcbNeeded
, FALSE
);
2332 HeapFree(GetProcessHeap(),0,pEnvW
);
2335 /*****************************************************************************
2336 * GetPrinterDriverW [WINSPOOL.@]
2338 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
2339 DWORD Level
, LPBYTE pDriverInfo
,
2340 DWORD cbBuf
, LPDWORD pcbNeeded
)
2342 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
2343 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
2346 /*****************************************************************************
2347 * GetPrinterDriverDirectoryA [WINSPOOL.@]
2349 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
2350 DWORD Level
, LPBYTE pDriverDirectory
,
2351 DWORD cbBuf
, LPDWORD pcbNeeded
)
2355 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName
, pEnvironment
, Level
,
2356 pDriverDirectory
, cbBuf
, pcbNeeded
);
2358 FIXME("pName = `%s' - unsupported\n", pName
);
2359 SetLastError(ERROR_INVALID_PARAMETER
);
2362 if(pEnvironment
!= NULL
) {
2363 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment
);
2364 SetLastError(ERROR_INVALID_ENVIRONMENT
);
2367 if(Level
!= 1) /* win95 ignores this so we just carry on */
2368 WARN("Level = %ld - assuming 1\n", Level
);
2370 /* FIXME should read from registry */
2371 needed
= GetSystemDirectoryA(pDriverDirectory
, cbBuf
);
2374 *pcbNeeded
= needed
;
2375 if(needed
> cbBuf
) {
2376 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2383 /*****************************************************************************
2384 * GetPrinterDriverDirectoryW [WINSPOOL.@]
2386 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
2387 DWORD Level
, LPBYTE pDriverDirectory
,
2388 DWORD cbBuf
, LPDWORD pcbNeeded
)
2390 LPSTR pNameA
= NULL
, pEnvironmentA
= NULL
;
2394 pNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pName
);
2396 pEnvironmentA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
);
2397 ret
= GetPrinterDriverDirectoryA( pNameA
, pEnvironmentA
, Level
,
2398 pDriverDirectory
, cbBuf
, pcbNeeded
);
2400 HeapFree( GetProcessHeap(), 0, pNameA
);
2402 HeapFree( GetProcessHeap(), 0, pEnvironmentA
);
2407 /*****************************************************************************
2408 * AddPrinterDriverA [WINSPOOL.@]
2410 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
2413 HKEY hkeyDrivers
, hkeyName
;
2415 TRACE("(%s,%ld,%p)\n",debugstr_a(pName
),level
,pDriverInfo
);
2417 if(level
!= 2 && level
!= 3) {
2418 SetLastError(ERROR_INVALID_LEVEL
);
2422 FIXME("pName= %s - unsupported\n", debugstr_a(pName
));
2423 SetLastError(ERROR_INVALID_PARAMETER
);
2427 WARN("pDriverInfo == NULL\n");
2428 SetLastError(ERROR_INVALID_PARAMETER
);
2433 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
2435 memset(&di3
, 0, sizeof(di3
));
2436 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
2439 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
2441 SetLastError(ERROR_INVALID_PARAMETER
);
2444 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
2445 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
2446 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
2447 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
2449 hkeyDrivers
= WINSPOOL_OpenDriverReg(di3
.pEnvironment
, FALSE
);
2452 ERR("Can't create Drivers key\n");
2456 if(level
== 2) { /* apparently can't overwrite with level2 */
2457 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2458 RegCloseKey(hkeyName
);
2459 RegCloseKey(hkeyDrivers
);
2460 WARN("Trying to create existing printer driver %s\n", debugstr_a(di3
.pName
));
2461 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2465 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2466 RegCloseKey(hkeyDrivers
);
2467 ERR("Can't create Name key\n");
2470 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2472 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2473 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2474 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2476 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2477 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2478 di3
.pDependentFiles
, 0);
2479 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2480 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2481 RegCloseKey(hkeyName
);
2482 RegCloseKey(hkeyDrivers
);
2486 /*****************************************************************************
2487 * AddPrinterDriverW [WINSPOOL.@]
2489 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2492 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2498 /*****************************************************************************
2499 * PrinterProperties [WINSPOOL.@]
2501 * Displays a dialog to set the properties of the printer.
2504 * nonzero on success or zero on failure
2507 * implemented as stub only
2509 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* [in] handle to parent window */
2510 HANDLE hPrinter
/* [in] handle to printer object */
2512 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
2513 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2517 /*****************************************************************************
2518 * EnumJobsA [WINSPOOL.@]
2521 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2522 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2526 if(pcbNeeded
) *pcbNeeded
= 0;
2527 if(pcReturned
) *pcReturned
= 0;
2532 /*****************************************************************************
2533 * EnumJobsW [WINSPOOL.@]
2536 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2537 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2541 if(pcbNeeded
) *pcbNeeded
= 0;
2542 if(pcReturned
) *pcReturned
= 0;
2546 /*****************************************************************************
2547 * WINSPOOL_EnumPrinterDrivers [internal]
2549 * Delivers information about all printer drivers installed on the
2550 * localhost or a given server
2553 * nonzero on success or zero on failure. If the buffer for the returned
2554 * information is too small the function will return an error
2557 * - only implemented for localhost, foreign hosts will return an error
2559 static BOOL
WINSPOOL_EnumPrinterDrivers(LPWSTR pName
, LPWSTR pEnvironment
,
2560 DWORD Level
, LPBYTE pDriverInfo
,
2561 DWORD cbBuf
, LPDWORD pcbNeeded
,
2562 LPDWORD pcReturned
, BOOL unicode
)
2565 DWORD i
, needed
, number
= 0, size
= 0;
2566 WCHAR DriverNameW
[255];
2569 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2570 debugstr_w(pName
), debugstr_w(pEnvironment
),
2571 Level
, pDriverInfo
, cbBuf
, unicode
);
2573 /* check for local drivers */
2575 ERR("remote drivers unsupported! Current remote host is %s\n",
2580 /* check input parameter */
2581 if((Level
< 1) || (Level
> 3)) {
2582 ERR("unsupported level %ld \n", Level
);
2586 /* initialize return values */
2588 memset( pDriverInfo
, 0, cbBuf
);
2592 hkeyDrivers
= WINSPOOL_OpenDriverReg(pEnvironment
, TRUE
);
2594 ERR("Can't open Drivers key\n");
2598 if(RegQueryInfoKeyA(hkeyDrivers
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2599 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2600 RegCloseKey(hkeyDrivers
);
2601 ERR("Can't query Drivers key\n");
2604 TRACE("Found %ld Drivers\n", number
);
2606 /* get size of single struct
2607 * unicode and ascii structure have the same size
2611 size
= sizeof(DRIVER_INFO_1A
);
2614 size
= sizeof(DRIVER_INFO_2A
);
2617 size
= sizeof(DRIVER_INFO_3A
);
2621 /* calculate required buffer size */
2622 *pcbNeeded
= size
* number
;
2624 for( i
= 0, ptr
= (pDriverInfo
&& (cbBuf
>= size
)) ? pDriverInfo
: NULL
;
2626 i
++, ptr
= (ptr
&& (cbBuf
>= size
* i
)) ? ptr
+ size
: NULL
) {
2627 if(RegEnumKeyW(hkeyDrivers
, i
, DriverNameW
, sizeof(DriverNameW
))
2629 ERR("Can't enum key number %ld\n", i
);
2630 RegCloseKey(hkeyDrivers
);
2633 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverNameW
,
2634 pEnvironment
, Level
, ptr
,
2635 (cbBuf
< *pcbNeeded
) ? NULL
: pDriverInfo
+ *pcbNeeded
,
2636 (cbBuf
< *pcbNeeded
) ? 0 : cbBuf
- *pcbNeeded
,
2637 &needed
, unicode
)) {
2638 RegCloseKey(hkeyDrivers
);
2641 (*pcbNeeded
) += needed
;
2644 RegCloseKey(hkeyDrivers
);
2646 if(cbBuf
< *pcbNeeded
){
2647 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2654 /*****************************************************************************
2655 * EnumPrinterDriversW [WINSPOOL.@]
2657 * see function EnumPrinterDrivers for RETURNS, BUGS
2659 BOOL WINAPI
EnumPrinterDriversW(LPWSTR pName
, LPWSTR pEnvironment
, DWORD Level
,
2660 LPBYTE pDriverInfo
, DWORD cbBuf
,
2661 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2663 return WINSPOOL_EnumPrinterDrivers(pName
, pEnvironment
, Level
, pDriverInfo
,
2664 cbBuf
, pcbNeeded
, pcReturned
, TRUE
);
2667 /*****************************************************************************
2668 * EnumPrinterDriversA [WINSPOOL.@]
2670 * see function EnumPrinterDrivers for RETURNS, BUGS
2672 BOOL WINAPI
EnumPrinterDriversA(LPSTR pName
, LPSTR pEnvironment
, DWORD Level
,
2673 LPBYTE pDriverInfo
, DWORD cbBuf
,
2674 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2676 WCHAR
*pNameW
= NULL
, *pEnvironmentW
= NULL
;
2679 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
2681 pEnvironmentW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment
);
2683 ret
= WINSPOOL_EnumPrinterDrivers(pNameW
, pEnvironmentW
, Level
, pDriverInfo
,
2684 cbBuf
, pcbNeeded
, pcReturned
, FALSE
);
2686 HeapFree(GetProcessHeap(), 0, pNameW
);
2688 HeapFree(GetProcessHeap(), 0, pEnvironmentW
);
2694 /******************************************************************************
2695 * EnumPortsA (WINSPOOL.@)
2697 BOOL WINAPI
EnumPortsA(LPSTR name
,DWORD level
,LPBYTE ports
,DWORD bufsize
,
2698 LPDWORD bufneeded
,LPDWORD bufreturned
)
2700 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name
,level
,ports
,bufsize
,bufneeded
,bufreturned
);
2704 /******************************************************************************
2705 * GetDefaultPrinterA (WINSPOOL.@)
2707 * Based on PRINTDLG_GetDefaultPrinterName in dlls/commdlg/printdlg.c
2709 BOOL WINAPI
GetDefaultPrinterA(LPSTR name
, LPDWORD namesize
)
2715 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
2719 if (!GetProfileStringA ("windows", "device", "", name
, *namesize
))
2721 SetLastError (ERROR_FILE_NOT_FOUND
);
2725 if ((ptr
= strchr (name
, ',')) == NULL
)
2727 SetLastError (ERROR_FILE_NOT_FOUND
);
2732 *namesize
= strlen (name
) + 1;
2737 /******************************************************************************
2738 * GetDefaultPrinterW (WINSPOOL.@)
2740 BOOL WINAPI
GetDefaultPrinterW(LPWSTR name
, LPDWORD namesize
)
2747 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
2751 buf
= HeapAlloc (GetProcessHeap (), 0, *namesize
);
2752 ret
= GetDefaultPrinterA (buf
, namesize
);
2755 DWORD len
= MultiByteToWideChar (CP_ACP
, 0, buf
, -1, name
, *namesize
);
2758 SetLastError (ERROR_INSUFFICIENT_BUFFER
);
2761 else *namesize
= len
;
2764 HeapFree (GetProcessHeap (), 0, buf
);
2769 /******************************************************************************
2770 * SetPrinterDataExA (WINSPOOL.@)
2772 DWORD WINAPI
SetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2773 LPSTR pValueName
, DWORD Type
,
2774 LPBYTE pData
, DWORD cbData
)
2776 HKEY hkeyPrinter
, hkeySubkey
;
2779 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_a(pKeyName
),
2780 debugstr_a(pValueName
), Type
, pData
, cbData
);
2782 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2786 if((ret
= RegCreateKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2788 ERR("Can't create subkey %s\n", debugstr_a(pKeyName
));
2789 RegCloseKey(hkeyPrinter
);
2792 ret
= RegSetValueExA(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2793 RegCloseKey(hkeySubkey
);
2794 RegCloseKey(hkeyPrinter
);
2798 /******************************************************************************
2799 * SetPrinterDataExW (WINSPOOL.@)
2801 DWORD WINAPI
SetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
2802 LPWSTR pValueName
, DWORD Type
,
2803 LPBYTE pData
, DWORD cbData
)
2805 HKEY hkeyPrinter
, hkeySubkey
;
2808 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_w(pKeyName
),
2809 debugstr_w(pValueName
), Type
, pData
, cbData
);
2811 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2815 if((ret
= RegCreateKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2817 ERR("Can't create subkey %s\n", debugstr_w(pKeyName
));
2818 RegCloseKey(hkeyPrinter
);
2821 ret
= RegSetValueExW(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2822 RegCloseKey(hkeySubkey
);
2823 RegCloseKey(hkeyPrinter
);
2827 /******************************************************************************
2828 * SetPrinterDataA (WINSPOOL.@)
2830 DWORD WINAPI
SetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, DWORD Type
,
2831 LPBYTE pData
, DWORD cbData
)
2833 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
,
2837 /******************************************************************************
2838 * SetPrinterDataW (WINSPOOL.@)
2840 DWORD WINAPI
SetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, DWORD Type
,
2841 LPBYTE pData
, DWORD cbData
)
2843 return SetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, Type
,
2847 /******************************************************************************
2848 * GetPrinterDataExA (WINSPOOL.@)
2850 DWORD WINAPI
GetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2851 LPSTR pValueName
, LPDWORD pType
,
2852 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2854 HKEY hkeyPrinter
, hkeySubkey
;
2857 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
2858 debugstr_a(pKeyName
), debugstr_a(pValueName
), pType
, pData
, nSize
,
2861 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2865 if((ret
= RegOpenKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2867 WARN("Can't open subkey %s\n", debugstr_a(pKeyName
));
2868 RegCloseKey(hkeyPrinter
);
2872 ret
= RegQueryValueExA(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
2873 RegCloseKey(hkeySubkey
);
2874 RegCloseKey(hkeyPrinter
);
2878 /******************************************************************************
2879 * GetPrinterDataExW (WINSPOOL.@)
2881 DWORD WINAPI
GetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
2882 LPWSTR pValueName
, LPDWORD pType
,
2883 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2885 HKEY hkeyPrinter
, hkeySubkey
;
2888 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
2889 debugstr_w(pKeyName
), debugstr_w(pValueName
), pType
, pData
, nSize
,
2892 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2896 if((ret
= RegOpenKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2898 WARN("Can't open subkey %s\n", debugstr_w(pKeyName
));
2899 RegCloseKey(hkeyPrinter
);
2903 ret
= RegQueryValueExW(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
2904 RegCloseKey(hkeySubkey
);
2905 RegCloseKey(hkeyPrinter
);
2909 /******************************************************************************
2910 * GetPrinterDataA (WINSPOOL.@)
2912 DWORD WINAPI
GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
,
2913 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2915 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
,
2916 pData
, nSize
, pcbNeeded
);
2919 /******************************************************************************
2920 * GetPrinterDataW (WINSPOOL.@)
2922 DWORD WINAPI
GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
,
2923 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2925 return GetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, pType
,
2926 pData
, nSize
, pcbNeeded
);
2929 /*******************************************************************************
2930 * EnumPrinterDataExW [WINSPOOL.@]
2932 DWORD WINAPI
EnumPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
,
2933 LPBYTE pEnumValues
, DWORD cbEnumValues
,
2934 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
2936 HKEY hkPrinter
, hkSubKey
;
2937 DWORD r
, ret
, dwIndex
, cValues
, cbMaxValueNameLen
,
2938 cbValueNameLen
, cbMaxValueLen
, cbValueLen
,
2943 PPRINTER_ENUM_VALUESW ppev
;
2945 TRACE ("%08x %s\n", hPrinter
, debugstr_w (pKeyName
));
2947 if (pKeyName
== NULL
|| *pKeyName
== 0)
2948 return ERROR_INVALID_PARAMETER
;
2950 ret
= WINSPOOL_GetOpenedPrinterRegKey (hPrinter
, &hkPrinter
);
2951 if (ret
!= ERROR_SUCCESS
)
2953 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%08x) returned %li\n",
2958 ret
= RegOpenKeyExW (hkPrinter
, pKeyName
, 0, KEY_READ
, &hkSubKey
);
2959 if (ret
!= ERROR_SUCCESS
)
2961 r
= RegCloseKey (hkPrinter
);
2962 if (r
!= ERROR_SUCCESS
)
2963 WARN ("RegCloseKey returned %li\n", r
);
2964 TRACE ("RegOpenKeyExW (%08x, %s) returned %li\n", hPrinter
,
2965 debugstr_w (pKeyName
), ret
);
2969 ret
= RegCloseKey (hkPrinter
);
2970 if (ret
!= ERROR_SUCCESS
)
2972 ERR ("RegCloseKey returned %li\n", ret
);
2973 r
= RegCloseKey (hkSubKey
);
2974 if (r
!= ERROR_SUCCESS
)
2975 WARN ("RegCloseKey returned %li\n", r
);
2979 ret
= RegQueryInfoKeyW (hkSubKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
2980 &cValues
, &cbMaxValueNameLen
, &cbMaxValueLen
, NULL
, NULL
);
2981 if (ret
!= ERROR_SUCCESS
)
2983 r
= RegCloseKey (hkSubKey
);
2984 if (r
!= ERROR_SUCCESS
)
2985 WARN ("RegCloseKey returned %li\n", r
);
2986 TRACE ("RegQueryInfoKeyW (%08x) returned %li\n", hkSubKey
, ret
);
2990 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
2991 "cbMaxValueLen = %li\n", cValues
, cbMaxValueNameLen
, cbMaxValueLen
);
2993 if (cValues
== 0) /* empty key */
2995 r
= RegCloseKey (hkSubKey
);
2996 if (r
!= ERROR_SUCCESS
)
2997 WARN ("RegCloseKey returned %li\n", r
);
2998 *pcbEnumValues
= *pnEnumValues
= 0;
2999 return ERROR_SUCCESS
;
3002 ++cbMaxValueNameLen
; /* allow for trailing '\0' */
3004 hHeap
= GetProcessHeap ();
3005 if (hHeap
== (HANDLE
) NULL
)
3007 ERR ("GetProcessHeap failed\n");
3008 r
= RegCloseKey (hkSubKey
);
3009 if (r
!= ERROR_SUCCESS
)
3010 WARN ("RegCloseKey returned %li\n", r
);
3011 return ERROR_OUTOFMEMORY
;
3014 lpValueName
= HeapAlloc (hHeap
, 0, cbMaxValueNameLen
* sizeof (WCHAR
));
3015 if (lpValueName
== NULL
)
3017 ERR ("Failed to allocate %li bytes from process heap\n",
3018 cbMaxValueNameLen
* sizeof (WCHAR
));
3019 r
= RegCloseKey (hkSubKey
);
3020 if (r
!= ERROR_SUCCESS
)
3021 WARN ("RegCloseKey returned %li\n", r
);
3022 return ERROR_OUTOFMEMORY
;
3025 lpValue
= HeapAlloc (hHeap
, 0, cbMaxValueLen
);
3026 if (lpValue
== NULL
)
3028 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen
);
3029 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3030 WARN ("HeapFree failed with code %li\n", GetLastError ());
3031 r
= RegCloseKey (hkSubKey
);
3032 if (r
!= ERROR_SUCCESS
)
3033 WARN ("RegCloseKey returned %li\n", r
);
3034 return ERROR_OUTOFMEMORY
;
3037 TRACE ("pass 1: calculating buffer required for all names and values\n");
3039 cbBufSize
= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
3041 TRACE ("%li bytes required for %li headers\n", cbBufSize
, cValues
);
3043 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
3045 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
3046 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
3047 NULL
, NULL
, lpValue
, &cbValueLen
);
3048 if (ret
!= ERROR_SUCCESS
)
3050 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3051 WARN ("HeapFree failed with code %li\n", GetLastError ());
3052 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3053 WARN ("HeapFree failed with code %li\n", GetLastError ());
3054 r
= RegCloseKey (hkSubKey
);
3055 if (r
!= ERROR_SUCCESS
)
3056 WARN ("RegCloseKey returned %li\n", r
);
3057 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
3061 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
3062 debugstr_w (lpValueName
), dwIndex
,
3063 (cbValueNameLen
+ 1) * sizeof (WCHAR
), cbValueLen
);
3065 cbBufSize
+= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
3066 cbBufSize
+= cbValueLen
;
3069 TRACE ("%li bytes required for all %li values\n", cbBufSize
, cValues
);
3071 *pcbEnumValues
= cbBufSize
;
3072 *pnEnumValues
= cValues
;
3074 if (cbEnumValues
< cbBufSize
) /* buffer too small */
3076 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3077 WARN ("HeapFree failed with code %li\n", GetLastError ());
3078 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3079 WARN ("HeapFree failed with code %li\n", GetLastError ());
3080 r
= RegCloseKey (hkSubKey
);
3081 if (r
!= ERROR_SUCCESS
)
3082 WARN ("RegCloseKey returned %li\n", r
);
3083 TRACE ("%li byte buffer is not large enough\n", cbEnumValues
);
3084 return ERROR_MORE_DATA
;
3087 TRACE ("pass 2: copying all names and values to buffer\n");
3089 ppev
= (PPRINTER_ENUM_VALUESW
) pEnumValues
; /* array of structs */
3090 pEnumValues
+= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
3092 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
3094 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
3095 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
3096 NULL
, &dwType
, lpValue
, &cbValueLen
);
3097 if (ret
!= ERROR_SUCCESS
)
3099 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3100 WARN ("HeapFree failed with code %li\n", GetLastError ());
3101 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3102 WARN ("HeapFree failed with code %li\n", GetLastError ());
3103 r
= RegCloseKey (hkSubKey
);
3104 if (r
!= ERROR_SUCCESS
)
3105 WARN ("RegCloseKey returned %li\n", r
);
3106 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
3110 cbValueNameLen
= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
3111 memcpy (pEnumValues
, lpValueName
, cbValueNameLen
);
3112 ppev
[dwIndex
].pValueName
= (LPWSTR
) pEnumValues
;
3113 pEnumValues
+= cbValueNameLen
;
3115 /* return # of *bytes* (including trailing \0), not # of chars */
3116 ppev
[dwIndex
].cbValueName
= cbValueNameLen
;
3118 ppev
[dwIndex
].dwType
= dwType
;
3120 memcpy (pEnumValues
, lpValue
, cbValueLen
);
3121 ppev
[dwIndex
].pData
= pEnumValues
;
3122 pEnumValues
+= cbValueLen
;
3124 ppev
[dwIndex
].cbData
= cbValueLen
;
3126 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
3127 debugstr_w (lpValueName
), dwIndex
, cbValueNameLen
, cbValueLen
);
3130 if (HeapFree (hHeap
, 0, lpValue
) == 0)
3132 ret
= GetLastError ();
3133 ERR ("HeapFree failed with code %li\n", ret
);
3134 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3135 WARN ("HeapFree failed with code %li\n", GetLastError ());
3136 r
= RegCloseKey (hkSubKey
);
3137 if (r
!= ERROR_SUCCESS
)
3138 WARN ("RegCloseKey returned %li\n", r
);
3142 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
3144 ret
= GetLastError ();
3145 ERR ("HeapFree failed with code %li\n", ret
);
3146 r
= RegCloseKey (hkSubKey
);
3147 if (r
!= ERROR_SUCCESS
)
3148 WARN ("RegCloseKey returned %li\n", r
);
3152 ret
= RegCloseKey (hkSubKey
);
3153 if (ret
!= ERROR_SUCCESS
)
3155 ERR ("RegCloseKey returned %li\n", ret
);
3159 return ERROR_SUCCESS
;
3162 /*******************************************************************************
3163 * EnumPrinterDataExA [WINSPOOL.@]
3165 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
3166 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
3167 * what Windows 2000 SP1 does.
3170 DWORD WINAPI
EnumPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
,
3171 LPBYTE pEnumValues
, DWORD cbEnumValues
,
3172 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
3176 DWORD ret
, dwIndex
, dwBufSize
;
3180 TRACE ("%08x %s\n", hPrinter
, pKeyName
);
3182 if (pKeyName
== NULL
|| *pKeyName
== 0)
3183 return ERROR_INVALID_PARAMETER
;
3185 len
= MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, NULL
, 0);
3188 ret
= GetLastError ();
3189 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
3193 hHeap
= GetProcessHeap ();
3194 if (hHeap
== (HANDLE
) NULL
)
3196 ERR ("GetProcessHeap failed\n");
3197 return ERROR_OUTOFMEMORY
;
3200 pKeyNameW
= HeapAlloc (hHeap
, 0, len
* sizeof (WCHAR
));
3201 if (pKeyNameW
== NULL
)
3203 ERR ("Failed to allocate %li bytes from process heap\n",
3204 (LONG
) len
* sizeof (WCHAR
));
3205 return ERROR_OUTOFMEMORY
;
3208 if (MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, pKeyNameW
, len
) == 0)
3210 ret
= GetLastError ();
3211 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
3212 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3213 WARN ("HeapFree failed with code %li\n", GetLastError ());
3217 ret
= EnumPrinterDataExW (hPrinter
, pKeyNameW
, pEnumValues
, cbEnumValues
,
3218 pcbEnumValues
, pnEnumValues
);
3219 if (ret
!= ERROR_SUCCESS
)
3221 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3222 WARN ("HeapFree failed with code %li\n", GetLastError ());
3223 TRACE ("EnumPrinterDataExW returned %li\n", ret
);
3227 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
3229 ret
= GetLastError ();
3230 ERR ("HeapFree failed with code %li\n", ret
);
3234 if (*pnEnumValues
== 0) /* empty key */
3235 return ERROR_SUCCESS
;
3238 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
3240 PPRINTER_ENUM_VALUESW ppev
=
3241 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
3243 if (dwBufSize
< ppev
->cbValueName
)
3244 dwBufSize
= ppev
->cbValueName
;
3246 if (dwBufSize
< ppev
->cbData
&& (ppev
->dwType
== REG_SZ
||
3247 ppev
->dwType
== REG_EXPAND_SZ
|| ppev
->dwType
== REG_MULTI_SZ
))
3248 dwBufSize
= ppev
->cbData
;
3251 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize
);
3253 pBuffer
= HeapAlloc (hHeap
, 0, dwBufSize
);
3254 if (pBuffer
== NULL
)
3256 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize
);
3257 return ERROR_OUTOFMEMORY
;
3260 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
3262 PPRINTER_ENUM_VALUESW ppev
=
3263 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
3265 len
= WideCharToMultiByte (CP_ACP
, 0, ppev
->pValueName
,
3266 ppev
->cbValueName
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
,
3270 ret
= GetLastError ();
3271 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
3272 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3273 WARN ("HeapFree failed with code %li\n", GetLastError ());
3277 memcpy (ppev
->pValueName
, pBuffer
, len
);
3279 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
3281 if (ppev
->dwType
!= REG_SZ
&& ppev
->dwType
!= REG_EXPAND_SZ
&&
3282 ppev
->dwType
!= REG_MULTI_SZ
)
3285 len
= WideCharToMultiByte (CP_ACP
, 0, (LPWSTR
) ppev
->pData
,
3286 ppev
->cbData
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
, NULL
);
3289 ret
= GetLastError ();
3290 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
3291 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3292 WARN ("HeapFree failed with code %li\n", GetLastError ());
3296 memcpy (ppev
->pData
, pBuffer
, len
);
3298 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
3299 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
3302 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
3304 ret
= GetLastError ();
3305 ERR ("HeapFree failed with code %li\n", ret
);
3309 return ERROR_SUCCESS
;