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 if (def && !strcmp(def,"none")) /* CUPS has "none" for no default printer */
131 for (i=0;i<nrofdests;i++) {
132 const char *ppd = cupsGetPPD(printers[i]);
136 WARN("No ppd file for %s.\n",printers[i]);
137 /* If this was going to be the default printer,
138 * forget it and use another one.
140 if (def && !strcmp(def,printers[i]))
148 if (def && !strcmp(def,printers[i]))
149 WINSPOOL_SetDefaultPrinter(printers[i],printers[i],FALSE);
151 /* The default printer has no PPD file, just use the first one
155 WINSPOOL_SetDefaultPrinter(printers[i],printers[i],FALSE);
158 memset(&pinfo2a,0,sizeof(pinfo2a));
159 pinfo2a.pPrinterName = printers[i];
160 pinfo2a.pDatatype = "RAW";
161 pinfo2a.pPrintProcessor = "WinPrint";
162 pinfo2a.pDriverName = "PS Driver";
163 pinfo2a.pComment = "WINEPS Printer using CUPS";
164 pinfo2a.pLocation = "<physical location of printer>";
165 port = HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(printers[i])+1);
166 sprintf(port,"LPR:%s",printers[i]);
167 pinfo2a.pPortName = port;
168 pinfo2a.pParameters = "<parameters?>";
169 pinfo2a.pShareName = "<share name?>";
170 pinfo2a.pSepFile = "<sep file?>";
172 devline=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port)+1);
173 sprintf(devline,"WINEPS,%s",port);
174 WriteProfileStringA("devices",printers[i],devline);
175 HeapFree(GetProcessHeap(),0,devline);
177 if (!AddPrinterA(NULL,2,(LPBYTE)&pinfo2a)) {
178 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS)
179 ERR("printer '%s' not added by AddPrinterA (error %ld)\n",printers[i],GetLastError());
181 HeapFree(GetProcessHeap(),0,port);
188 PRINTCAP_ParseEntry(char *pent,BOOL isfirst) {
189 PRINTER_INFO_2A pinfo2a;
190 char *s,*name,*prettyname,*devname;
194 while (isspace(*pent)) pent++;
195 s = strchr(pent,':');
196 if (!s) return FALSE;
202 /* Determine whether this is a postscript printer. */
204 /* 1. Check if name or aliases contain trigger phrases like 'ps' */
205 if (strstr(name,"ps") ||
206 strstr(name,"pd") || /* postscript double page */
207 strstr(name,"postscript") ||
208 strstr(name,"PostScript")
210 TRACE("%s has 'ps' style name, assuming postscript.\n",name);
213 /* 2. Check if this is a remote printer. These usually are postscript
216 if (strstr(pent,":rm")) {
218 TRACE("%s is remote, assuming postscript.\n",name);
220 /* 3. Check if we have an input filter program. If we have one, it
221 * most likely is one capable of converting postscript.
222 * (Could probably check for occurrence of 'gs' or 'ghostscript'
223 * in the if file itself.)
225 if (strstr(pent,":if=/")) {
227 TRACE("%s has inputfilter program, assuming postscript.\n",name);
230 /* If it is not a postscript printer, we cannot use it. */
235 /* Get longest name, usually the one at the right for later display. */
236 while ((s=strchr(prettyname,'|'))) prettyname = s+1;
237 s=strchr(name,'|');if (s) *s='\0';
239 /* prettyname must fit into the dmDeviceName member of DEVMODE struct,
240 * if it is too long, we use it as comment below. */
241 devname = prettyname;
242 if (strlen(devname)>=CCHDEVICENAME-1)
244 if (strlen(devname)>=CCHDEVICENAME-1)
247 if (isfirst) /* set first entry as default */
248 WINSPOOL_SetDefaultPrinter(devname,name,FALSE);
250 memset(&pinfo2a,0,sizeof(pinfo2a));
251 pinfo2a.pPrinterName = devname;
252 pinfo2a.pDatatype = "RAW";
253 pinfo2a.pPrintProcessor = "WinPrint";
254 pinfo2a.pDriverName = "PS Driver";
255 pinfo2a.pComment = "WINEPS Printer using LPR";
256 pinfo2a.pLocation = prettyname;
257 port = HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(name)+1);
258 sprintf(port,"LPR:%s",name);
259 pinfo2a.pPortName = port;
260 pinfo2a.pParameters = "<parameters?>";
261 pinfo2a.pShareName = "<share name?>";
262 pinfo2a.pSepFile = "<sep file?>";
264 devline=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port)+1);
265 sprintf(devline,"WINEPS,%s",port);
266 WriteProfileStringA("devices",devname,devline);
267 HeapFree(GetProcessHeap(),0,devline);
269 if (!AddPrinterA(NULL,2,(LPBYTE)&pinfo2a)) {
270 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS)
271 ERR("%s not added by AddPrinterA (%ld)\n",name,GetLastError());
273 HeapFree(GetProcessHeap(),0,port);
278 PRINTCAP_LoadPrinters(void) {
279 BOOL hadprinter = FALSE, isfirst = TRUE;
283 f = fopen("/etc/printcap","r");
287 while (fgets(buf,sizeof(buf),f)) {
291 s=strchr(buf,'\n'); if (s) *s='\0';
292 if ((buf[0]=='#') || (buf[0]=='\0'))
296 pent=HeapReAlloc(GetProcessHeap(),0,pent,strlen(pent)+strlen(buf)+2);
299 pent=HeapAlloc(GetProcessHeap(),0,strlen(buf)+1);
303 if (strlen(pent) && (pent[strlen(pent)-1] == '\\'))
304 pent[strlen(pent)-1] = '\0';
307 } while (fgets(buf,sizeof(buf),f));
309 hadprinter |= PRINTCAP_ParseEntry(pent,isfirst);
311 if (pent) HeapFree(GetProcessHeap(),0,pent);
319 static inline DWORD set_reg_szW(HKEY hkey, WCHAR *keyname, WCHAR *value)
321 return RegSetValueExW(hkey, keyname, 0, REG_SZ, (LPBYTE)value,
322 lstrlenW(value) * sizeof(WCHAR));
326 WINSPOOL_LoadSystemPrinters() {
329 di3a.cVersion = 0x400;
330 di3a.pName = "PS Driver";
331 di3a.pEnvironment = NULL; /* NULL means auto */
332 di3a.pDriverPath = "wineps.drv";
333 di3a.pDataFile = "<datafile?>";
334 di3a.pConfigFile = "wineps.drv";
335 di3a.pHelpFile = "<helpfile?>";
336 di3a.pDependentFiles = "<dependend files?>";
337 di3a.pMonitorName = "<monitor name?>";
338 di3a.pDefaultDataType = "RAW";
340 if (!AddPrinterDriverA(NULL,3,(LPBYTE)&di3a)) {
341 ERR("Failed adding PS Driver (%ld)\n",GetLastError());
345 /* If we have any CUPS based printers, skip looking for printcap printers */
346 if (CUPS_LoadPrinters())
350 /* Check for [ppd] section in config file before parsing /etc/printcap */
352 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\ppd",
353 &hkPPD) == ERROR_SUCCESS)
356 PRINTCAP_LoadPrinters();
361 /******************************************************************
362 * WINSPOOL_GetOpenedPrinterEntry
363 * Get the first place empty in the opened printer table
365 static HANDLE WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name )
369 for (i = 0; i < nb_printers; i++) if (!printer_array[i]) break;
371 if (i >= nb_printers)
373 LPWSTR *new_array = HeapReAlloc( GetProcessHeap(), 0, printer_array,
374 (nb_printers + 16) * sizeof(*new_array) );
375 if (!new_array) return 0;
376 printer_array = new_array;
380 if ((printer_array[i] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name)+1)*sizeof(WCHAR) )))
382 strcpyW( printer_array[i], name );
383 return (HANDLE)(i + 1);
388 /******************************************************************
389 * WINSPOOL_GetOpenedPrinter
390 * Get the pointer to the opened printer referred by the handle
392 static LPCWSTR WINSPOOL_GetOpenedPrinter(HANDLE printerHandle)
394 int idx = (int)printerHandle;
395 if ((idx <= 0) || (idx > nb_printers))
397 SetLastError(ERROR_INVALID_HANDLE);
400 return printer_array[idx - 1];
403 /******************************************************************
404 * WINSPOOL_GetOpenedPrinterRegKey
407 static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey)
409 LPCWSTR name = WINSPOOL_GetOpenedPrinter(hPrinter);
413 if(!name) return ERROR_INVALID_HANDLE;
415 if((ret = RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters)) !=
419 if(RegOpenKeyW(hkeyPrinters, name, phkey) != ERROR_SUCCESS)
421 ERR("Can't find opened printer %s in registry\n",
423 RegCloseKey(hkeyPrinters);
424 return ERROR_INVALID_PRINTER_NAME; /* ? */
426 RegCloseKey(hkeyPrinters);
427 return ERROR_SUCCESS;
430 /***********************************************************
433 static LPDEVMODEW DEVMODEcpyAtoW(DEVMODEW *dmW, const DEVMODEA *dmA)
436 ptrdiff_t off_formname = (char *)dmA->dmFormName - (char *)dmA;
439 Formname = (dmA->dmSize > off_formname);
440 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
441 MultiByteToWideChar(CP_ACP, 0, dmA->dmDeviceName, -1, dmW->dmDeviceName,
444 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
445 dmA->dmSize - CCHDEVICENAME);
447 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
448 off_formname - CCHDEVICENAME);
449 MultiByteToWideChar(CP_ACP, 0, dmA->dmFormName, -1, dmW->dmFormName,
451 memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA->dmSize -
452 (off_formname + CCHFORMNAME));
455 memcpy((char *)dmW + dmW->dmSize, (char *)dmA + dmA->dmSize,
460 /***********************************************************
462 * Creates a unicode copy of supplied devmode on heap
464 static LPDEVMODEW DEVMODEdupAtoW(HANDLE heap, const DEVMODEA *dmA)
469 ptrdiff_t off_formname;
472 if(!dmA) return NULL;
474 off_formname = (char *)dmA->dmFormName - (char *)dmA;
475 Formname = (dmA->dmSize > off_formname);
476 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
477 dmW = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmA->dmDriverExtra);
478 return DEVMODEcpyAtoW(dmW, dmA);
481 /***********************************************************
483 * Creates an ascii copy of supplied devmode on heap
485 static LPDEVMODEA DEVMODEdupWtoA(HANDLE heap, const DEVMODEW *dmW)
490 ptrdiff_t off_formname = (char *)dmW->dmFormName - (char *)dmW;
492 if(!dmW) return NULL;
493 Formname = (dmW->dmSize > off_formname);
494 size = dmW->dmSize - CCHDEVICENAME - (Formname ? CCHFORMNAME : 0);
495 dmA = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmW->dmDriverExtra);
496 WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, dmA->dmDeviceName,
497 CCHDEVICENAME, NULL, NULL);
499 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
500 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR));
502 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
503 off_formname - CCHDEVICENAME * sizeof(WCHAR));
504 WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, dmA->dmFormName,
505 CCHFORMNAME, NULL, NULL);
506 memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize -
507 (off_formname + CCHFORMNAME * sizeof(WCHAR)));
510 memcpy((char *)dmA + dmA->dmSize, (char *)dmW + dmW->dmSize,
515 /***********************************************************
517 * Creates a unicode copy of PRINTER_INFO_2A on heap
519 static LPPRINTER_INFO_2W PRINTER_INFO_2AtoW(HANDLE heap, LPPRINTER_INFO_2A piA)
521 LPPRINTER_INFO_2W piW;
522 if(!piA) return NULL;
523 piW = HeapAlloc(heap, 0, sizeof(*piW));
524 memcpy(piW, piA, sizeof(*piW)); /* copy everything first */
525 piW->pServerName = HEAP_strdupAtoW(heap, 0, piA->pServerName);
526 piW->pPrinterName = HEAP_strdupAtoW(heap, 0, piA->pPrinterName);
527 piW->pShareName = HEAP_strdupAtoW(heap, 0, piA->pShareName);
528 piW->pPortName = HEAP_strdupAtoW(heap, 0, piA->pPortName);
529 piW->pDriverName = HEAP_strdupAtoW(heap, 0, piA->pDriverName);
530 piW->pComment = HEAP_strdupAtoW(heap, 0, piA->pComment);
531 piW->pLocation = HEAP_strdupAtoW(heap, 0, piA->pLocation);
532 piW->pDevMode = DEVMODEdupAtoW(heap, piA->pDevMode);
533 piW->pSepFile = HEAP_strdupAtoW(heap, 0, piA->pSepFile);
534 piW->pPrintProcessor = HEAP_strdupAtoW(heap, 0, piA->pPrintProcessor);
535 piW->pDatatype = HEAP_strdupAtoW(heap, 0, piA->pDatatype);
536 piW->pParameters = HEAP_strdupAtoW(heap, 0, piA->pParameters);
540 /***********************************************************
541 * FREE_PRINTER_INFO_2W
542 * Free PRINTER_INFO_2W and all strings
544 static void FREE_PRINTER_INFO_2W(HANDLE heap, LPPRINTER_INFO_2W piW)
548 HeapFree(heap,0,piW->pServerName);
549 HeapFree(heap,0,piW->pPrinterName);
550 HeapFree(heap,0,piW->pShareName);
551 HeapFree(heap,0,piW->pPortName);
552 HeapFree(heap,0,piW->pDriverName);
553 HeapFree(heap,0,piW->pComment);
554 HeapFree(heap,0,piW->pLocation);
555 HeapFree(heap,0,piW->pDevMode);
556 HeapFree(heap,0,piW->pSepFile);
557 HeapFree(heap,0,piW->pPrintProcessor);
558 HeapFree(heap,0,piW->pDatatype);
559 HeapFree(heap,0,piW->pParameters);
560 HeapFree(heap,0,piW);
564 /******************************************************************
565 * DeviceCapabilities [WINSPOOL.@]
566 * DeviceCapabilitiesA [WINSPOOL.@]
569 INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap,
570 LPSTR pOutput, LPDEVMODEA lpdm)
574 if (!GDI_CallDeviceCapabilities16)
576 GDI_CallDeviceCapabilities16 = (void*)GetProcAddress( GetModuleHandleA("gdi32"),
578 if (!GDI_CallDeviceCapabilities16) return -1;
580 ret = GDI_CallDeviceCapabilities16(pDevice, pPort, cap, pOutput, lpdm);
582 /* If DC_PAPERSIZE map POINT16s to POINTs */
583 if(ret != -1 && cap == DC_PAPERSIZE && pOutput) {
584 POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) );
585 POINT *pt = (POINT *)pOutput;
587 memcpy(tmp, pOutput, ret * sizeof(POINT16));
588 for(i = 0; i < ret; i++, pt++)
593 HeapFree( GetProcessHeap(), 0, tmp );
599 /*****************************************************************************
600 * DeviceCapabilitiesW [WINSPOOL.@]
602 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
605 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
606 WORD fwCapability, LPWSTR pOutput,
607 const DEVMODEW *pDevMode)
609 LPDEVMODEA dmA = DEVMODEdupWtoA(GetProcessHeap(), pDevMode);
610 LPSTR pDeviceA = HEAP_strdupWtoA(GetProcessHeap(),0,pDevice);
611 LPSTR pPortA = HEAP_strdupWtoA(GetProcessHeap(),0,pPort);
614 if(pOutput && (fwCapability == DC_BINNAMES ||
615 fwCapability == DC_FILEDEPENDENCIES ||
616 fwCapability == DC_PAPERNAMES)) {
617 /* These need A -> W translation */
620 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, NULL,
624 switch(fwCapability) {
629 case DC_FILEDEPENDENCIES:
633 pOutputA = HeapAlloc(GetProcessHeap(), 0, size * ret);
634 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, pOutputA,
636 for(i = 0; i < ret; i++)
637 MultiByteToWideChar(CP_ACP, 0, pOutputA + (i * size), -1,
638 pOutput + (i * size), size);
639 HeapFree(GetProcessHeap(), 0, pOutputA);
641 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability,
642 (LPSTR)pOutput, dmA);
644 HeapFree(GetProcessHeap(),0,pPortA);
645 HeapFree(GetProcessHeap(),0,pDeviceA);
646 HeapFree(GetProcessHeap(),0,dmA);
650 /******************************************************************
651 * DocumentPropertiesA [WINSPOOL.@]
654 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
655 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
656 LPDEVMODEA pDevModeInput,DWORD fMode )
658 LPSTR lpName = pDeviceName;
661 TRACE("(%p,%p,%s,%p,%p,%ld)\n",
662 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
666 LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
668 ERR("no name from hPrinter?\n");
671 lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
674 if (!GDI_CallExtDeviceMode16)
676 GDI_CallExtDeviceMode16 = (void*)GetProcAddress( GetModuleHandleA("gdi32"),
678 if (!GDI_CallExtDeviceMode16) {
679 ERR("No CallExtDeviceMode16?\n");
683 ret = GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
684 pDevModeInput, NULL, fMode);
687 HeapFree(GetProcessHeap(),0,lpName);
692 /*****************************************************************************
693 * DocumentPropertiesW (WINSPOOL.@)
695 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
697 LPDEVMODEW pDevModeOutput,
698 LPDEVMODEW pDevModeInput, DWORD fMode)
701 LPSTR pDeviceNameA = HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName);
702 LPDEVMODEA pDevModeInputA = DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput);
703 LPDEVMODEA pDevModeOutputA = NULL;
706 TRACE("(%p,%p,%s,%p,%p,%ld)\n",
707 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
710 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, NULL, NULL, 0);
711 if(ret < 0) return ret;
712 pDevModeOutputA = HeapAlloc(GetProcessHeap(), 0, ret);
714 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, pDevModeOutputA,
715 pDevModeInputA, fMode);
717 DEVMODEcpyAtoW(pDevModeOutput, pDevModeOutputA);
718 HeapFree(GetProcessHeap(),0,pDevModeOutputA);
720 if(fMode == 0 && ret > 0)
721 ret += (CCHDEVICENAME + CCHFORMNAME);
722 HeapFree(GetProcessHeap(),0,pDevModeInputA);
723 HeapFree(GetProcessHeap(),0,pDeviceNameA);
727 /******************************************************************
728 * OpenPrinterA [WINSPOOL.@]
731 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
732 LPPRINTER_DEFAULTSA pDefault)
734 LPWSTR lpPrinterNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName);
735 PRINTER_DEFAULTSW DefaultW, *pDefaultW = NULL;
739 DefaultW.pDatatype = HEAP_strdupAtoW(GetProcessHeap(), 0,
740 pDefault->pDatatype);
741 DefaultW.pDevMode = DEVMODEdupAtoW(GetProcessHeap(),
743 DefaultW.DesiredAccess = pDefault->DesiredAccess;
744 pDefaultW = &DefaultW;
746 ret = OpenPrinterW(lpPrinterNameW, phPrinter, pDefaultW);
748 HeapFree(GetProcessHeap(), 0, DefaultW.pDatatype);
749 HeapFree(GetProcessHeap(), 0, DefaultW.pDevMode);
751 HeapFree(GetProcessHeap(), 0, lpPrinterNameW);
755 /******************************************************************
756 * OpenPrinterW [WINSPOOL.@]
759 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
760 LPPRINTER_DEFAULTSW pDefault)
762 HKEY hkeyPrinters, hkeyPrinter;
764 if (!lpPrinterName) {
765 FIXME("(printerName: NULL, pDefault %p Ret: False\n", pDefault);
766 SetLastError(ERROR_INVALID_PARAMETER);
770 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName),
773 /* Check Printer exists */
774 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
776 ERR("Can't create Printers key\n");
777 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
781 if(lpPrinterName[0] == '\0' || /* explicitly exclude "" */
782 RegOpenKeyW(hkeyPrinters, lpPrinterName, &hkeyPrinter)
784 TRACE("Can't find printer %s in registry\n",
785 debugstr_w(lpPrinterName));
786 RegCloseKey(hkeyPrinters);
787 SetLastError(ERROR_INVALID_PRINTER_NAME);
790 RegCloseKey(hkeyPrinter);
791 RegCloseKey(hkeyPrinters);
793 if(!phPrinter) /* This seems to be what win95 does anyway */
796 /* Get the unique handle of the printer*/
797 *phPrinter = WINSPOOL_GetOpenedPrinterEntry( lpPrinterName );
799 if (pDefault != NULL)
800 FIXME("Not handling pDefault\n");
805 /******************************************************************
806 * AddMonitorA [WINSPOOL.@]
809 BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors)
811 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
812 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
816 /******************************************************************
817 * DeletePrinterDriverA [WINSPOOL.@]
821 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
823 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
824 debugstr_a(pDriverName));
825 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
830 /******************************************************************
831 * DeleteMonitorA [WINSPOOL.@]
835 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
837 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
838 debugstr_a(pMonitorName));
839 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
844 /******************************************************************
845 * DeletePortA [WINSPOOL.@]
849 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
851 FIXME("(%s,%p,%s):stub\n",debugstr_a(pName),hWnd,
852 debugstr_a(pPortName));
853 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
857 /******************************************************************************
858 * SetPrinterW [WINSPOOL.@]
868 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
872 /******************************************************************************
873 * WritePrinter [WINSPOOL.@]
883 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
887 /*****************************************************************************
888 * AddFormA [WINSPOOL.@]
890 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
892 FIXME("(%p,%ld,%p): stub\n", hPrinter, Level, pForm);
896 /*****************************************************************************
897 * AddFormW [WINSPOOL.@]
899 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
901 FIXME("(%p,%ld,%p): stub\n", hPrinter, Level, pForm);
905 /*****************************************************************************
906 * AddJobA [WINSPOOL.@]
908 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
909 DWORD cbBuf, LPDWORD pcbNeeded)
911 FIXME("(%p,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
916 /*****************************************************************************
917 * AddJobW [WINSPOOL.@]
919 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
922 FIXME("(%p,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
927 /*****************************************************************************
928 * WINSPOOL_OpenDriverReg [internal]
930 * opens the registry for the printer drivers depending on the given input
931 * variable pEnvironment
934 * the opened hkey on success
937 static HKEY WINSPOOL_OpenDriverReg( LPVOID pEnvironment, BOOL unicode)
939 LPSTR lpKey, p = NULL;
942 (unicode) ? debugstr_w(pEnvironment) : debugstr_a(pEnvironment));
945 p = (unicode) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment) :
949 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
951 if(!GetVersionExA( &ver))
954 switch (ver.dwPlatformId) {
955 case VER_PLATFORM_WIN32s:
956 ERR("win32 style printing used with 16 bits app, try specifying 'win95' Windows version\n");
959 case VER_PLATFORM_WIN32_NT:
960 p = "Windows NT x86";
966 TRACE("set environment to %s\n", p);
969 lpKey = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
970 strlen(p) + strlen(Drivers));
971 sprintf( lpKey, Drivers, p);
973 TRACE("%s\n", lpKey);
975 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, lpKey, &retval) !=
979 if(pEnvironment && unicode)
980 HeapFree( GetProcessHeap(), 0, p);
981 HeapFree( GetProcessHeap(), 0, lpKey);
986 /*****************************************************************************
987 * AddPrinterW [WINSPOOL.@]
989 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
991 PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
995 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
998 TRACE("(%s,%ld,%p)\n", debugstr_w(pName), Level, pPrinter);
1001 ERR("pName = %s - unsupported\n", debugstr_w(pName));
1002 SetLastError(ERROR_INVALID_PARAMETER);
1006 ERR("Level = %ld, unsupported!\n", Level);
1007 SetLastError(ERROR_INVALID_LEVEL);
1010 if (strlenW(pi->pPrinterName) >= CCHDEVICENAME) {
1011 ERR("Printername %s must not exceed length of DEVMODE.dmDeviceName !\n",
1012 debugstr_w(pi->pPrinterName)
1014 SetLastError(ERROR_INVALID_LEVEL);
1018 SetLastError(ERROR_INVALID_PARAMETER);
1021 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1023 ERR("Can't create Printers key\n");
1026 if(!RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter)) {
1027 if (!RegQueryValueA(hkeyPrinter,"Attributes",NULL,NULL)) {
1028 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
1029 RegCloseKey(hkeyPrinter);
1030 RegCloseKey(hkeyPrinters);
1033 RegCloseKey(hkeyPrinter);
1035 hkeyDrivers = WINSPOOL_OpenDriverReg( NULL, TRUE);
1037 ERR("Can't create Drivers key\n");
1038 RegCloseKey(hkeyPrinters);
1041 if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
1043 WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
1044 RegCloseKey(hkeyPrinters);
1045 RegCloseKey(hkeyDrivers);
1046 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
1049 RegCloseKey(hkeyDriver);
1050 RegCloseKey(hkeyDrivers);
1052 if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) { /* FIXME */
1053 FIXME("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
1054 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
1055 RegCloseKey(hkeyPrinters);
1059 if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
1061 FIXME("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
1062 SetLastError(ERROR_INVALID_PRINTER_NAME);
1063 RegCloseKey(hkeyPrinters);
1066 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
1067 (LPBYTE)&pi->Attributes, sizeof(DWORD));
1068 set_reg_szW(hkeyPrinter, DatatypeW, pi->pDatatype);
1070 /* See if we can load the driver. We may need the devmode structure anyway
1073 * Note that DocumentPropertiesW will briefly try to open the printer we
1074 * just create to find a DEVMODEA struct (it will use the WINEPS default
1075 * one in case it is not there, so we are ok).
1077 size = DocumentPropertiesW(0, 0, pi->pPrinterName, NULL, NULL, 0);
1079 FIXME("DocumentPropertiesW on printer '%s' fails\n", debugstr_w(pi->pPrinterName));
1080 size = sizeof(DEVMODEW);
1085 dmW = HeapAlloc(GetProcessHeap(), 0, size);
1087 if (0>DocumentPropertiesW(0,0,pi->pPrinterName,dmW,NULL,DM_OUT_BUFFER)) {
1088 ERR("DocumentPropertiesW on printer '%s' failed!\n", debugstr_w(pi->pPrinterName));
1089 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
1092 /* set devmode to printer name */
1093 strcpyW(dmW->dmDeviceName,pi->pPrinterName);
1096 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
1097 and we support these drivers. NT writes DEVMODEW so somehow
1098 we'll need to distinguish between these when we support NT
1100 dmA = DEVMODEdupWtoA(GetProcessHeap(), dmW);
1101 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, (LPBYTE)dmA,
1102 dmA->dmSize + dmA->dmDriverExtra);
1103 HeapFree(GetProcessHeap(), 0, dmA);
1105 HeapFree(GetProcessHeap(), 0, dmW);
1106 set_reg_szW(hkeyPrinter, DescriptionW, pi->pComment);
1107 set_reg_szW(hkeyPrinter, LocationW, pi->pLocation);
1108 set_reg_szW(hkeyPrinter, NameW, pi->pPrinterName);
1109 set_reg_szW(hkeyPrinter, ParametersW, pi->pParameters);
1111 set_reg_szW(hkeyPrinter, PortW, pi->pPortName);
1112 set_reg_szW(hkeyPrinter, Print_ProcessorW, pi->pPrintProcessor);
1113 set_reg_szW(hkeyPrinter, Printer_DriverW, pi->pDriverName);
1114 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
1115 (LPBYTE)&pi->Priority, sizeof(DWORD));
1116 set_reg_szW(hkeyPrinter, Separator_FileW, pi->pSepFile);
1117 set_reg_szW(hkeyPrinter, Share_NameW, pi->pShareName);
1118 RegSetValueExA(hkeyPrinter, "StartTime", 0, REG_DWORD,
1119 (LPBYTE)&pi->StartTime, sizeof(DWORD));
1120 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
1121 (LPBYTE)&pi->Status, sizeof(DWORD));
1122 RegSetValueExA(hkeyPrinter, "UntilTime", 0, REG_DWORD,
1123 (LPBYTE)&pi->UntilTime, sizeof(DWORD));
1125 RegCloseKey(hkeyPrinter);
1126 RegCloseKey(hkeyPrinters);
1127 if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
1128 ERR("OpenPrinter failing\n");
1134 /*****************************************************************************
1135 * AddPrinterA [WINSPOOL.@]
1137 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
1140 PRINTER_INFO_2W *piW;
1141 PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter;
1144 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName), Level, pPrinter);
1146 ERR("Level = %ld, unsupported!\n", Level);
1147 SetLastError(ERROR_INVALID_LEVEL);
1150 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
1151 piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA);
1153 ret = AddPrinterW(pNameW, Level, (LPBYTE)piW);
1155 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW);
1156 HeapFree(GetProcessHeap(),0,pNameW);
1161 /*****************************************************************************
1162 * ClosePrinter [WINSPOOL.@]
1164 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
1166 int i = (int)hPrinter;
1168 TRACE("Handle %p\n", hPrinter);
1170 if ((i <= 0) || (i > nb_printers)) return FALSE;
1171 HeapFree( GetProcessHeap(), 0, printer_array[i - 1] );
1172 printer_array[i - 1] = NULL;
1176 /*****************************************************************************
1177 * DeleteFormA [WINSPOOL.@]
1179 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
1181 FIXME("(%p,%s): stub\n", hPrinter, pFormName);
1185 /*****************************************************************************
1186 * DeleteFormW [WINSPOOL.@]
1188 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
1190 FIXME("(%p,%s): stub\n", hPrinter, debugstr_w(pFormName));
1194 /*****************************************************************************
1195 * DeletePrinter [WINSPOOL.@]
1197 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
1199 LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
1202 if(!lpNameW) return FALSE;
1203 if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1205 ERR("Can't open Printers key\n");
1209 /* This should use a recursive delete see Q142491 or SHDeleteKey */
1210 if(RegDeleteKeyW(hkeyPrinters, lpNameW) == ERROR_SUCCESS) {
1211 SetLastError(ERROR_PRINTER_NOT_FOUND); /* ?? */
1212 RegCloseKey(hkeyPrinters);
1216 ClosePrinter(hPrinter);
1220 /*****************************************************************************
1221 * SetPrinterA [WINSPOOL.@]
1223 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1226 FIXME("(%p,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
1230 /*****************************************************************************
1231 * SetJobA [WINSPOOL.@]
1233 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
1234 LPBYTE pJob, DWORD Command)
1236 FIXME("(%p,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1241 /*****************************************************************************
1242 * SetJobW [WINSPOOL.@]
1244 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
1245 LPBYTE pJob, DWORD Command)
1247 FIXME("(%p,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1252 /*****************************************************************************
1253 * GetFormA [WINSPOOL.@]
1255 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1256 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1258 FIXME("(%p,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
1259 Level,pForm,cbBuf,pcbNeeded);
1263 /*****************************************************************************
1264 * GetFormW [WINSPOOL.@]
1266 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1267 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1269 FIXME("(%p,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
1270 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
1274 /*****************************************************************************
1275 * SetFormA [WINSPOOL.@]
1277 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1280 FIXME("(%p,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1284 /*****************************************************************************
1285 * SetFormW [WINSPOOL.@]
1287 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1290 FIXME("(%p,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1294 /*****************************************************************************
1295 * ReadPrinter [WINSPOOL.@]
1297 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1298 LPDWORD pNoBytesRead)
1300 FIXME("(%p,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1304 /*****************************************************************************
1305 * ResetPrinterA [WINSPOOL.@]
1307 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1309 FIXME("(%p, %p): stub\n", hPrinter, pDefault);
1313 /*****************************************************************************
1314 * ResetPrinterW [WINSPOOL.@]
1316 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1318 FIXME("(%p, %p): stub\n", hPrinter, pDefault);
1322 /*****************************************************************************
1323 * WINSPOOL_GetDWORDFromReg
1325 * Return DWORD associated with ValueName from hkey.
1327 static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName)
1329 DWORD sz = sizeof(DWORD), type, value = 0;
1332 ret = RegQueryValueExA(hkey, ValueName, 0, &type, (LPBYTE)&value, &sz);
1334 if(ret != ERROR_SUCCESS) {
1335 WARN("Got ret = %ld on name %s\n", ret, ValueName);
1338 if(type != REG_DWORD) {
1339 ERR("Got type %ld\n", type);
1345 /*****************************************************************************
1346 * WINSPOOL_GetStringFromReg
1348 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1349 * String is stored either as unicode or ascii.
1350 * Bit of a hack here to get the ValueName if we want ascii.
1352 static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr,
1353 DWORD buflen, DWORD *needed,
1356 DWORD sz = buflen, type;
1360 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1362 LPSTR ValueNameA = HEAP_strdupWtoA(GetProcessHeap(),0,ValueName);
1363 ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz);
1364 HeapFree(GetProcessHeap(),0,ValueNameA);
1366 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1367 WARN("Got ret = %ld\n", ret);
1375 /*****************************************************************************
1376 * WINSPOOL_GetDefaultDevMode
1378 * Get a default DevMode values for wineps.
1382 static void WINSPOOL_GetDefaultDevMode(
1384 DWORD buflen, DWORD *needed,
1389 /* fill default DEVMODE - should be read from ppd... */
1390 ZeroMemory( &dm, sizeof(dm) );
1391 strcpy(dm.dmDeviceName,"wineps");
1392 dm.dmSpecVersion = DM_SPECVERSION;
1393 dm.dmDriverVersion = 1;
1394 dm.dmSize = sizeof(DEVMODEA);
1395 dm.dmDriverExtra = 0;
1397 DM_ORIENTATION | DM_PAPERSIZE |
1398 DM_PAPERLENGTH | DM_PAPERWIDTH |
1401 DM_DEFAULTSOURCE | DM_PRINTQUALITY |
1402 DM_YRESOLUTION | DM_TTOPTION;
1404 dm.u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1405 dm.u1.s1.dmPaperSize = DMPAPER_A4;
1406 dm.u1.s1.dmPaperLength = 2970;
1407 dm.u1.s1.dmPaperWidth = 2100;
1411 dm.dmDefaultSource = DMBIN_AUTO;
1412 dm.dmPrintQuality = DMRES_MEDIUM;
1415 dm.dmYResolution = 300; /* 300dpi */
1416 dm.dmTTOption = DMTT_BITMAP;
1419 /* dm.dmLogPixels */
1420 /* dm.dmBitsPerPel */
1421 /* dm.dmPelsWidth */
1422 /* dm.dmPelsHeight */
1423 /* dm.dmDisplayFlags */
1424 /* dm.dmDisplayFrequency */
1425 /* dm.dmICMMethod */
1426 /* dm.dmICMIntent */
1427 /* dm.dmMediaType */
1428 /* dm.dmDitherType */
1429 /* dm.dmReserved1 */
1430 /* dm.dmReserved2 */
1431 /* dm.dmPanningWidth */
1432 /* dm.dmPanningHeight */
1435 if(buflen >= sizeof(DEVMODEW)) {
1436 DEVMODEW *pdmW = DEVMODEdupAtoW(GetProcessHeap(), &dm );
1437 memcpy(ptr, pdmW, sizeof(DEVMODEW));
1438 HeapFree(GetProcessHeap(),0,pdmW);
1440 *needed = sizeof(DEVMODEW);
1444 if(buflen >= sizeof(DEVMODEA)) {
1445 memcpy(ptr, &dm, sizeof(DEVMODEA));
1447 *needed = sizeof(DEVMODEA);
1451 /*****************************************************************************
1452 * WINSPOOL_GetDevModeFromReg
1454 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1455 * DevMode is stored either as unicode or ascii.
1457 static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
1459 DWORD buflen, DWORD *needed,
1462 DWORD sz = buflen, type;
1465 if (ptr && buflen>=sizeof(DEVMODEA)) memset(ptr, 0, sizeof(DEVMODEA));
1466 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1467 if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
1468 if (sz < sizeof(DEVMODEA))
1470 ERR("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName),sz);
1473 /* ensures that dmSize is not erratically bogus if registry is invalid */
1474 if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA))
1475 ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA);
1477 sz += (CCHDEVICENAME + CCHFORMNAME);
1479 DEVMODEW *dmW = DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA*)ptr);
1480 memcpy(ptr, dmW, sz);
1481 HeapFree(GetProcessHeap(),0,dmW);
1488 /*********************************************************************
1489 * WINSPOOL_GetPrinter_2
1491 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1492 * The strings are either stored as unicode or ascii.
1494 static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2,
1495 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1498 DWORD size, left = cbBuf;
1499 BOOL space = (cbBuf > 0);
1504 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1506 if(space && size <= left) {
1507 pi2->pPrinterName = (LPWSTR)ptr;
1514 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size,
1516 if(space && size <= left) {
1517 pi2->pShareName = (LPWSTR)ptr;
1524 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1526 if(space && size <= left) {
1527 pi2->pPortName = (LPWSTR)ptr;
1534 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left,
1536 if(space && size <= left) {
1537 pi2->pDriverName = (LPWSTR)ptr;
1544 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size,
1546 if(space && size <= left) {
1547 pi2->pComment = (LPWSTR)ptr;
1554 if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size,
1556 if(space && size <= left) {
1557 pi2->pLocation = (LPWSTR)ptr;
1564 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left,
1566 if(space && size <= left) {
1567 pi2->pDevMode = (LPDEVMODEW)ptr;
1576 MESSAGE( "no DevMode in registry. please setup your printer again.\n"
1577 "use the default hard-coded DevMode(wineps/A4/300dpi).\n" );
1578 WINSPOOL_GetDefaultDevMode(ptr, left, &size, unicode);
1579 if(space && size <= left) {
1580 pi2->pDevMode = (LPDEVMODEW)ptr;
1587 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left,
1589 if(space && size <= left) {
1590 pi2->pSepFile = (LPWSTR)ptr;
1597 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left,
1599 if(space && size <= left) {
1600 pi2->pPrintProcessor = (LPWSTR)ptr;
1607 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left,
1609 if(space && size <= left) {
1610 pi2->pDatatype = (LPWSTR)ptr;
1617 if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left,
1619 if(space && size <= left) {
1620 pi2->pParameters = (LPWSTR)ptr;
1628 pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1629 pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority");
1630 pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1631 "Default Priority");
1632 pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime");
1633 pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime");
1636 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
1637 memset(pi2, 0, sizeof(*pi2));
1642 /*********************************************************************
1643 * WINSPOOL_GetPrinter_4
1645 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1647 static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4,
1648 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1651 DWORD size, left = cbBuf;
1652 BOOL space = (cbBuf > 0);
1657 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1659 if(space && size <= left) {
1660 pi4->pPrinterName = (LPWSTR)ptr;
1668 pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1671 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
1672 memset(pi4, 0, sizeof(*pi4));
1677 /*********************************************************************
1678 * WINSPOOL_GetPrinter_5
1680 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1682 static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5,
1683 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1686 DWORD size, left = cbBuf;
1687 BOOL space = (cbBuf > 0);
1692 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1694 if(space && size <= left) {
1695 pi5->pPrinterName = (LPWSTR)ptr;
1702 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1704 if(space && size <= left) {
1705 pi5->pPortName = (LPWSTR)ptr;
1713 pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1714 pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1716 pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1720 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
1721 memset(pi5, 0, sizeof(*pi5));
1726 /*****************************************************************************
1727 * WINSPOOL_GetPrinter
1729 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1730 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1731 * just a collection of pointers to strings.
1733 static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1734 DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
1737 DWORD size, needed = 0;
1739 HKEY hkeyPrinter, hkeyPrinters;
1742 TRACE("(%p,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1744 if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE;
1746 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1748 ERR("Can't create Printers key\n");
1751 if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter) != ERROR_SUCCESS)
1753 ERR("Can't find opened printer %s in registry\n", debugstr_w(name));
1754 RegCloseKey(hkeyPrinters);
1755 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1762 PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter;
1764 size = sizeof(PRINTER_INFO_2W);
1766 ptr = pPrinter + size;
1768 memset(pPrinter, 0, size);
1773 ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed,
1781 PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter;
1783 size = sizeof(PRINTER_INFO_4W);
1785 ptr = pPrinter + size;
1787 memset(pPrinter, 0, size);
1792 ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed,
1801 PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter;
1803 size = sizeof(PRINTER_INFO_5W);
1805 ptr = pPrinter + size;
1807 memset(pPrinter, 0, size);
1813 ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed,
1820 FIXME("Unimplemented level %ld\n", Level);
1821 SetLastError(ERROR_INVALID_LEVEL);
1822 RegCloseKey(hkeyPrinters);
1823 RegCloseKey(hkeyPrinter);
1827 RegCloseKey(hkeyPrinter);
1828 RegCloseKey(hkeyPrinters);
1830 TRACE("returing %d needed = %ld\n", ret, needed);
1831 if(pcbNeeded) *pcbNeeded = needed;
1833 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1837 /*****************************************************************************
1838 * GetPrinterW [WINSPOOL.@]
1840 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1841 DWORD cbBuf, LPDWORD pcbNeeded)
1843 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1847 /*****************************************************************************
1848 * GetPrinterA [WINSPOOL.@]
1850 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1851 DWORD cbBuf, LPDWORD pcbNeeded)
1853 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1857 /*****************************************************************************
1858 * WINSPOOL_EnumPrinters
1860 * Implementation of EnumPrintersA|W
1862 static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName,
1863 DWORD dwLevel, LPBYTE lpbPrinters,
1864 DWORD cbBuf, LPDWORD lpdwNeeded,
1865 LPDWORD lpdwReturned, BOOL unicode)
1868 HKEY hkeyPrinters, hkeyPrinter;
1869 WCHAR PrinterName[255];
1870 DWORD needed = 0, number = 0;
1871 DWORD used, i, left;
1875 memset(lpbPrinters, 0, cbBuf);
1881 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1882 if(dwType == PRINTER_ENUM_DEFAULT)
1885 if (dwType & PRINTER_ENUM_CONNECTIONS) {
1886 FIXME("We dont handle PRINTER_ENUM_CONNECTIONS\n");
1887 dwType &= ~PRINTER_ENUM_CONNECTIONS; /* we dont handle that */
1888 dwType |= PRINTER_ENUM_LOCAL;
1891 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1892 FIXME("dwType = %08lx\n", dwType);
1893 SetLastError(ERROR_INVALID_FLAGS);
1897 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1899 ERR("Can't create Printers key\n");
1903 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1904 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1905 RegCloseKey(hkeyPrinters);
1906 ERR("Can't query Printers key\n");
1909 TRACE("Found %ld printers\n", number);
1913 RegCloseKey(hkeyPrinters);
1915 *lpdwReturned = number;
1919 used = number * sizeof(PRINTER_INFO_2W);
1922 used = number * sizeof(PRINTER_INFO_4W);
1925 used = number * sizeof(PRINTER_INFO_5W);
1929 SetLastError(ERROR_INVALID_LEVEL);
1930 RegCloseKey(hkeyPrinters);
1933 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1935 for(i = 0; i < number; i++) {
1936 if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1938 ERR("Can't enum key number %ld\n", i);
1939 RegCloseKey(hkeyPrinters);
1942 TRACE("Printer %ld is %s\n", i, debugstr_w(PrinterName));
1943 if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1945 ERR("Can't open key %s\n", debugstr_w(PrinterName));
1946 RegCloseKey(hkeyPrinters);
1951 buf = lpbPrinters + used;
1952 left = cbBuf - used;
1960 WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf,
1961 left, &needed, unicode);
1963 if(pi) pi += sizeof(PRINTER_INFO_2W);
1966 WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf,
1967 left, &needed, unicode);
1969 if(pi) pi += sizeof(PRINTER_INFO_4W);
1972 WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf,
1973 left, &needed, unicode);
1975 if(pi) pi += sizeof(PRINTER_INFO_5W);
1978 ERR("Shouldn't be here!\n");
1979 RegCloseKey(hkeyPrinter);
1980 RegCloseKey(hkeyPrinters);
1983 RegCloseKey(hkeyPrinter);
1985 RegCloseKey(hkeyPrinters);
1992 memset(lpbPrinters, 0, cbBuf);
1993 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1997 *lpdwReturned = number;
1998 SetLastError(ERROR_SUCCESS);
2003 /******************************************************************
2004 * EnumPrintersW [WINSPOOL.@]
2006 * Enumerates the available printers, print servers and print
2007 * providers, depending on the specified flags, name and level.
2011 * If level is set to 1:
2012 * Not implemented yet!
2013 * Returns TRUE with an empty list.
2015 * If level is set to 2:
2016 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2017 * Returns an array of PRINTER_INFO_2 data structures in the
2018 * lpbPrinters buffer. Note that according to MSDN also an
2019 * OpenPrinter should be performed on every remote printer.
2021 * If level is set to 4 (officially WinNT only):
2022 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2023 * Fast: Only the registry is queried to retrieve printer names,
2024 * no connection to the driver is made.
2025 * Returns an array of PRINTER_INFO_4 data structures in the
2026 * lpbPrinters buffer.
2028 * If level is set to 5 (officially WinNT4/Win9x only):
2029 * Fast: Only the registry is queried to retrieve printer names,
2030 * no connection to the driver is made.
2031 * Returns an array of PRINTER_INFO_5 data structures in the
2032 * lpbPrinters buffer.
2034 * If level set to 3 or 6+:
2035 * returns zero (failure!)
2037 * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
2041 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
2042 * - Only levels 2, 4 and 5 are implemented at the moment.
2043 * - 16-bit printer drivers are not enumerated.
2044 * - Returned amount of bytes used/needed does not match the real Windoze
2045 * implementation (as in this implementation, all strings are part
2046 * of the buffer, whereas Win32 keeps them somewhere else)
2047 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
2050 * - In a regular Wine installation, no registry settings for printers
2051 * exist, which makes this function return an empty list.
2053 BOOL WINAPI EnumPrintersW(
2054 DWORD dwType, /* [in] Types of print objects to enumerate */
2055 LPWSTR lpszName, /* [in] name of objects to enumerate */
2056 DWORD dwLevel, /* [in] type of printer info structure */
2057 LPBYTE lpbPrinters, /* [out] buffer which receives info */
2058 DWORD cbBuf, /* [in] max size of buffer in bytes */
2059 LPDWORD lpdwNeeded, /* [out] pointer to var: # bytes used/needed */
2060 LPDWORD lpdwReturned /* [out] number of entries returned */
2063 return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf,
2064 lpdwNeeded, lpdwReturned, TRUE);
2067 /******************************************************************
2068 * EnumPrintersA [WINSPOOL.@]
2071 BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
2072 DWORD dwLevel, LPBYTE lpbPrinters,
2073 DWORD cbBuf, LPDWORD lpdwNeeded,
2074 LPDWORD lpdwReturned)
2077 LPWSTR lpszNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpszName);
2079 ret = WINSPOOL_EnumPrinters(dwType, lpszNameW, dwLevel, lpbPrinters, cbBuf,
2080 lpdwNeeded, lpdwReturned, FALSE);
2081 HeapFree(GetProcessHeap(),0,lpszNameW);
2085 /*****************************************************************************
2086 * WINSPOOL_GetDriverInfoFromReg [internal]
2088 * Enters the information from the registry into the DRIVER_INFO struct
2091 * zero if the printer driver does not exist in the registry
2092 * (only if Level > 1) otherwise nonzero
2094 static BOOL WINSPOOL_GetDriverInfoFromReg(
2097 LPWSTR pEnvironment,
2099 LPBYTE ptr, /* DRIVER_INFO */
2100 LPBYTE pDriverStrings, /* strings buffer */
2101 DWORD cbBuf, /* size of string buffer */
2102 LPDWORD pcbNeeded, /* space needed for str. */
2103 BOOL unicode) /* type of strings */
2104 { DWORD dw, size, tmp, type;
2106 LPBYTE strPtr = pDriverStrings;
2108 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
2109 debugstr_w(DriverName), debugstr_w(pEnvironment),
2110 Level, ptr, pDriverStrings, cbBuf, unicode);
2113 *pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
2114 if (*pcbNeeded <= cbBuf)
2115 strcpyW((LPWSTR)strPtr, DriverName);
2117 *pcbNeeded = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0,
2119 if(*pcbNeeded <= cbBuf)
2120 WideCharToMultiByte(CP_ACP, 0, DriverName, -1, strPtr, *pcbNeeded,
2125 ((PDRIVER_INFO_1W) ptr)->pName = (LPWSTR) strPtr;
2129 ((PDRIVER_INFO_3W) ptr)->pName = (LPWSTR) strPtr;
2130 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
2133 if(!DriverName[0] || RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) {
2134 ERR("Can't find driver '%s' in registry\n", debugstr_w(DriverName));
2135 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
2140 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw, &size) !=
2142 WARN("Can't get Version\n");
2144 ((PDRIVER_INFO_3A) ptr)->cVersion = dw;
2147 pEnvironment = DefaultEnvironmentW;
2149 size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
2151 size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
2154 if(*pcbNeeded <= cbBuf) {
2156 strcpyW((LPWSTR)strPtr, pEnvironment);
2158 WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, strPtr, size,
2161 ((PDRIVER_INFO_3W) ptr)->pEnvironment = (LPWSTR)strPtr;
2162 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
2165 if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, 0, &size,
2168 if(*pcbNeeded <= cbBuf)
2169 WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, size, &tmp,
2172 ((PDRIVER_INFO_3W) ptr)->pDriverPath = (LPWSTR)strPtr;
2173 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
2176 if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, 0, &size,
2179 if(*pcbNeeded <= cbBuf)
2180 WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, size,
2183 ((PDRIVER_INFO_3W) ptr)->pDataFile = (LPWSTR)strPtr;
2184 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2187 if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
2188 0, &size, unicode)) {
2190 if(*pcbNeeded <= cbBuf)
2191 WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
2192 size, &tmp, unicode);
2194 ((PDRIVER_INFO_3W) ptr)->pConfigFile = (LPWSTR)strPtr;
2195 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2199 RegCloseKey(hkeyDriver);
2200 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
2204 if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, 0, &size,
2207 if(*pcbNeeded <= cbBuf)
2208 WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr,
2209 size, &tmp, unicode);
2211 ((PDRIVER_INFO_3W) ptr)->pHelpFile = (LPWSTR)strPtr;
2212 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2215 if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, 0,
2218 if(*pcbNeeded <= cbBuf)
2219 WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr,
2220 size, &tmp, unicode);
2222 ((PDRIVER_INFO_3W) ptr)->pDependentFiles = (LPWSTR)strPtr;
2223 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2226 if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size,
2229 if(*pcbNeeded <= cbBuf)
2230 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
2231 size, &tmp, unicode);
2233 ((PDRIVER_INFO_3W) ptr)->pMonitorName = (LPWSTR)strPtr;
2234 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2237 if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size,
2240 if(*pcbNeeded <= cbBuf)
2241 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
2242 size, &tmp, unicode);
2244 ((PDRIVER_INFO_3W) ptr)->pDefaultDataType = (LPWSTR)strPtr;
2245 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2248 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
2249 RegCloseKey(hkeyDriver);
2253 /*****************************************************************************
2254 * WINSPOOL_GetPrinterDriver
2256 static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
2257 DWORD Level, LPBYTE pDriverInfo,
2258 DWORD cbBuf, LPDWORD pcbNeeded,
2262 WCHAR DriverName[100];
2263 DWORD ret, type, size, needed = 0;
2265 HKEY hkeyPrinter, hkeyPrinters, hkeyDrivers;
2267 TRACE("(%p,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
2268 Level,pDriverInfo,cbBuf, pcbNeeded);
2270 ZeroMemory(pDriverInfo, cbBuf);
2272 if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE;
2274 if(Level < 1 || Level > 3) {
2275 SetLastError(ERROR_INVALID_LEVEL);
2278 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
2280 ERR("Can't create Printers key\n");
2283 if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter)
2285 ERR("Can't find opened printer %s in registry\n", debugstr_w(name));
2286 RegCloseKey(hkeyPrinters);
2287 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
2290 size = sizeof(DriverName);
2292 ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type,
2293 (LPBYTE)DriverName, &size);
2294 RegCloseKey(hkeyPrinter);
2295 RegCloseKey(hkeyPrinters);
2296 if(ret != ERROR_SUCCESS) {
2297 ERR("Can't get DriverName for printer %s\n", debugstr_w(name));
2301 hkeyDrivers = WINSPOOL_OpenDriverReg( pEnvironment, TRUE);
2303 ERR("Can't create Drivers key\n");
2309 size = sizeof(DRIVER_INFO_1W);
2312 size = sizeof(DRIVER_INFO_2W);
2315 size = sizeof(DRIVER_INFO_3W);
2318 ERR("Invalid level\n");
2323 ptr = pDriverInfo + size;
2325 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName,
2326 pEnvironment, Level, pDriverInfo,
2327 (cbBuf < size) ? NULL : ptr,
2328 (cbBuf < size) ? 0 : cbBuf - size,
2329 &needed, unicode)) {
2330 RegCloseKey(hkeyDrivers);
2334 RegCloseKey(hkeyDrivers);
2336 if(pcbNeeded) *pcbNeeded = size + needed;
2337 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
2338 if(cbBuf >= needed) return TRUE;
2339 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2343 /*****************************************************************************
2344 * GetPrinterDriverA [WINSPOOL.@]
2346 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
2347 DWORD Level, LPBYTE pDriverInfo,
2348 DWORD cbBuf, LPDWORD pcbNeeded)
2351 LPWSTR pEnvW = HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment);
2352 ret = WINSPOOL_GetPrinterDriver(hPrinter, pEnvW, Level, pDriverInfo,
2353 cbBuf, pcbNeeded, FALSE);
2354 HeapFree(GetProcessHeap(),0,pEnvW);
2357 /*****************************************************************************
2358 * GetPrinterDriverW [WINSPOOL.@]
2360 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
2361 DWORD Level, LPBYTE pDriverInfo,
2362 DWORD cbBuf, LPDWORD pcbNeeded)
2364 return WINSPOOL_GetPrinterDriver(hPrinter, pEnvironment, Level,
2365 pDriverInfo, cbBuf, pcbNeeded, TRUE);
2368 /*****************************************************************************
2369 * GetPrinterDriverDirectoryA [WINSPOOL.@]
2371 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
2372 DWORD Level, LPBYTE pDriverDirectory,
2373 DWORD cbBuf, LPDWORD pcbNeeded)
2377 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
2378 pDriverDirectory, cbBuf, pcbNeeded);
2380 FIXME("pName = `%s' - unsupported\n", pName);
2381 SetLastError(ERROR_INVALID_PARAMETER);
2384 if(pEnvironment != NULL) {
2385 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
2386 SetLastError(ERROR_INVALID_ENVIRONMENT);
2389 if(Level != 1) /* win95 ignores this so we just carry on */
2390 WARN("Level = %ld - assuming 1\n", Level);
2392 /* FIXME should read from registry */
2393 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
2396 *pcbNeeded = needed;
2397 if(needed > cbBuf) {
2398 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2405 /*****************************************************************************
2406 * GetPrinterDriverDirectoryW [WINSPOOL.@]
2408 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
2409 DWORD Level, LPBYTE pDriverDirectory,
2410 DWORD cbBuf, LPDWORD pcbNeeded)
2412 LPSTR pNameA = NULL, pEnvironmentA = NULL;
2416 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
2418 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
2419 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
2420 pDriverDirectory, cbBuf, pcbNeeded );
2422 HeapFree( GetProcessHeap(), 0, pNameA );
2424 HeapFree( GetProcessHeap(), 0, pEnvironmentA );
2429 /*****************************************************************************
2430 * AddPrinterDriverA [WINSPOOL.@]
2432 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
2435 HKEY hkeyDrivers, hkeyName;
2437 TRACE("(%s,%ld,%p)\n",debugstr_a(pName),level,pDriverInfo);
2439 if(level != 2 && level != 3) {
2440 SetLastError(ERROR_INVALID_LEVEL);
2444 FIXME("pName= %s - unsupported\n", debugstr_a(pName));
2445 SetLastError(ERROR_INVALID_PARAMETER);
2449 WARN("pDriverInfo == NULL\n");
2450 SetLastError(ERROR_INVALID_PARAMETER);
2455 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
2457 memset(&di3, 0, sizeof(di3));
2458 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
2461 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
2463 SetLastError(ERROR_INVALID_PARAMETER);
2466 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
2467 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
2468 if(!di3.pHelpFile) di3.pHelpFile = "";
2469 if(!di3.pMonitorName) di3.pMonitorName = "";
2471 hkeyDrivers = WINSPOOL_OpenDriverReg(di3.pEnvironment, FALSE);
2474 ERR("Can't create Drivers key\n");
2478 if(level == 2) { /* apparently can't overwrite with level2 */
2479 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
2480 RegCloseKey(hkeyName);
2481 RegCloseKey(hkeyDrivers);
2482 WARN("Trying to create existing printer driver %s\n", debugstr_a(di3.pName));
2483 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
2487 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
2488 RegCloseKey(hkeyDrivers);
2489 ERR("Can't create Name key\n");
2492 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
2494 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
2495 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
2496 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
2498 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
2499 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
2500 di3.pDependentFiles, 0);
2501 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
2502 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
2503 RegCloseKey(hkeyName);
2504 RegCloseKey(hkeyDrivers);
2508 /*****************************************************************************
2509 * AddPrinterDriverW [WINSPOOL.@]
2511 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
2514 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
2520 /*****************************************************************************
2521 * PrinterProperties [WINSPOOL.@]
2523 * Displays a dialog to set the properties of the printer.
2526 * nonzero on success or zero on failure
2529 * implemented as stub only
2531 BOOL WINAPI PrinterProperties(HWND hWnd, /* [in] handle to parent window */
2532 HANDLE hPrinter /* [in] handle to printer object */
2534 FIXME("(%p,%p): stub\n", hWnd, hPrinter);
2535 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2539 /*****************************************************************************
2540 * EnumJobsA [WINSPOOL.@]
2543 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2544 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2548 if(pcbNeeded) *pcbNeeded = 0;
2549 if(pcReturned) *pcReturned = 0;
2554 /*****************************************************************************
2555 * EnumJobsW [WINSPOOL.@]
2558 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2559 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2563 if(pcbNeeded) *pcbNeeded = 0;
2564 if(pcReturned) *pcReturned = 0;
2568 /*****************************************************************************
2569 * WINSPOOL_EnumPrinterDrivers [internal]
2571 * Delivers information about all printer drivers installed on the
2572 * localhost or a given server
2575 * nonzero on success or zero on failure. If the buffer for the returned
2576 * information is too small the function will return an error
2579 * - only implemented for localhost, foreign hosts will return an error
2581 static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPWSTR pEnvironment,
2582 DWORD Level, LPBYTE pDriverInfo,
2583 DWORD cbBuf, LPDWORD pcbNeeded,
2584 LPDWORD pcReturned, BOOL unicode)
2587 DWORD i, needed, number = 0, size = 0;
2588 WCHAR DriverNameW[255];
2591 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2592 debugstr_w(pName), debugstr_w(pEnvironment),
2593 Level, pDriverInfo, cbBuf, unicode);
2595 /* check for local drivers */
2597 ERR("remote drivers unsupported! Current remote host is %s\n",
2602 /* check input parameter */
2603 if((Level < 1) || (Level > 3)) {
2604 ERR("unsupported level %ld \n", Level);
2608 /* initialize return values */
2610 memset( pDriverInfo, 0, cbBuf);
2614 hkeyDrivers = WINSPOOL_OpenDriverReg(pEnvironment, TRUE);
2616 ERR("Can't open Drivers key\n");
2620 if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, &number, NULL, NULL,
2621 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
2622 RegCloseKey(hkeyDrivers);
2623 ERR("Can't query Drivers key\n");
2626 TRACE("Found %ld Drivers\n", number);
2628 /* get size of single struct
2629 * unicode and ascii structure have the same size
2633 size = sizeof(DRIVER_INFO_1A);
2636 size = sizeof(DRIVER_INFO_2A);
2639 size = sizeof(DRIVER_INFO_3A);
2643 /* calculate required buffer size */
2644 *pcbNeeded = size * number;
2646 for( i = 0, ptr = (pDriverInfo && (cbBuf >= size)) ? pDriverInfo : NULL ;
2648 i++, ptr = (ptr && (cbBuf >= size * i)) ? ptr + size : NULL) {
2649 if(RegEnumKeyW(hkeyDrivers, i, DriverNameW, sizeof(DriverNameW))
2651 ERR("Can't enum key number %ld\n", i);
2652 RegCloseKey(hkeyDrivers);
2655 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW,
2656 pEnvironment, Level, ptr,
2657 (cbBuf < *pcbNeeded) ? NULL : pDriverInfo + *pcbNeeded,
2658 (cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded,
2659 &needed, unicode)) {
2660 RegCloseKey(hkeyDrivers);
2663 (*pcbNeeded) += needed;
2666 RegCloseKey(hkeyDrivers);
2668 if(cbBuf < *pcbNeeded){
2669 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2676 /*****************************************************************************
2677 * EnumPrinterDriversW [WINSPOOL.@]
2679 * see function EnumPrinterDrivers for RETURNS, BUGS
2681 BOOL WINAPI EnumPrinterDriversW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
2682 LPBYTE pDriverInfo, DWORD cbBuf,
2683 LPDWORD pcbNeeded, LPDWORD pcReturned)
2685 return WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo,
2686 cbBuf, pcbNeeded, pcReturned, TRUE);
2689 /*****************************************************************************
2690 * EnumPrinterDriversA [WINSPOOL.@]
2692 * see function EnumPrinterDrivers for RETURNS, BUGS
2694 BOOL WINAPI EnumPrinterDriversA(LPSTR pName, LPSTR pEnvironment, DWORD Level,
2695 LPBYTE pDriverInfo, DWORD cbBuf,
2696 LPDWORD pcbNeeded, LPDWORD pcReturned)
2698 WCHAR *pNameW = NULL, *pEnvironmentW = NULL;
2701 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
2703 pEnvironmentW = HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment);
2705 ret = WINSPOOL_EnumPrinterDrivers(pNameW, pEnvironmentW, Level, pDriverInfo,
2706 cbBuf, pcbNeeded, pcReturned, FALSE);
2708 HeapFree(GetProcessHeap(), 0, pNameW);
2710 HeapFree(GetProcessHeap(), 0, pEnvironmentW);
2716 /******************************************************************************
2717 * EnumPortsA (WINSPOOL.@)
2719 BOOL WINAPI EnumPortsA(LPSTR name,DWORD level,LPBYTE ports,DWORD bufsize,
2720 LPDWORD bufneeded,LPDWORD bufreturned)
2722 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name,level,ports,bufsize,bufneeded,bufreturned);
2726 /******************************************************************************
2727 * GetDefaultPrinterA (WINSPOOL.@)
2729 * Based on PRINTDLG_GetDefaultPrinterName in dlls/commdlg/printdlg.c
2731 BOOL WINAPI GetDefaultPrinterA(LPSTR name, LPDWORD namesize)
2737 SetLastError (ERROR_INSUFFICIENT_BUFFER);
2741 if (!GetProfileStringA ("windows", "device", "", name, *namesize))
2743 SetLastError (ERROR_FILE_NOT_FOUND);
2747 if ((ptr = strchr (name, ',')) == NULL)
2749 SetLastError (ERROR_FILE_NOT_FOUND);
2754 *namesize = strlen (name) + 1;
2759 /******************************************************************************
2760 * GetDefaultPrinterW (WINSPOOL.@)
2762 BOOL WINAPI GetDefaultPrinterW(LPWSTR name, LPDWORD namesize)
2769 SetLastError (ERROR_INSUFFICIENT_BUFFER);
2773 buf = HeapAlloc (GetProcessHeap (), 0, *namesize);
2774 ret = GetDefaultPrinterA (buf, namesize);
2777 DWORD len = MultiByteToWideChar (CP_ACP, 0, buf, -1, name, *namesize);
2780 SetLastError (ERROR_INSUFFICIENT_BUFFER);
2783 else *namesize = len;
2786 HeapFree (GetProcessHeap (), 0, buf);
2791 /******************************************************************************
2792 * SetPrinterDataExA (WINSPOOL.@)
2794 DWORD WINAPI SetPrinterDataExA(HANDLE hPrinter, LPSTR pKeyName,
2795 LPSTR pValueName, DWORD Type,
2796 LPBYTE pData, DWORD cbData)
2798 HKEY hkeyPrinter, hkeySubkey;
2801 TRACE("(%p, %s, %s %08lx, %p, %08lx)\n", hPrinter, debugstr_a(pKeyName),
2802 debugstr_a(pValueName), Type, pData, cbData);
2804 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2808 if((ret = RegCreateKeyA(hkeyPrinter, pKeyName, &hkeySubkey))
2810 ERR("Can't create subkey %s\n", debugstr_a(pKeyName));
2811 RegCloseKey(hkeyPrinter);
2814 ret = RegSetValueExA(hkeySubkey, pValueName, 0, Type, pData, cbData);
2815 RegCloseKey(hkeySubkey);
2816 RegCloseKey(hkeyPrinter);
2820 /******************************************************************************
2821 * SetPrinterDataExW (WINSPOOL.@)
2823 DWORD WINAPI SetPrinterDataExW(HANDLE hPrinter, LPWSTR pKeyName,
2824 LPWSTR pValueName, DWORD Type,
2825 LPBYTE pData, DWORD cbData)
2827 HKEY hkeyPrinter, hkeySubkey;
2830 TRACE("(%p, %s, %s %08lx, %p, %08lx)\n", hPrinter, debugstr_w(pKeyName),
2831 debugstr_w(pValueName), Type, pData, cbData);
2833 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2837 if((ret = RegCreateKeyW(hkeyPrinter, pKeyName, &hkeySubkey))
2839 ERR("Can't create subkey %s\n", debugstr_w(pKeyName));
2840 RegCloseKey(hkeyPrinter);
2843 ret = RegSetValueExW(hkeySubkey, pValueName, 0, Type, pData, cbData);
2844 RegCloseKey(hkeySubkey);
2845 RegCloseKey(hkeyPrinter);
2849 /******************************************************************************
2850 * SetPrinterDataA (WINSPOOL.@)
2852 DWORD WINAPI SetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, DWORD Type,
2853 LPBYTE pData, DWORD cbData)
2855 return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type,
2859 /******************************************************************************
2860 * SetPrinterDataW (WINSPOOL.@)
2862 DWORD WINAPI SetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, DWORD Type,
2863 LPBYTE pData, DWORD cbData)
2865 return SetPrinterDataExW(hPrinter, PrinterDriverDataW, pValueName, Type,
2869 /******************************************************************************
2870 * GetPrinterDataExA (WINSPOOL.@)
2872 DWORD WINAPI GetPrinterDataExA(HANDLE hPrinter, LPSTR pKeyName,
2873 LPSTR pValueName, LPDWORD pType,
2874 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2876 HKEY hkeyPrinter, hkeySubkey;
2879 TRACE("(%p, %s, %s %p, %p, %08lx, %p)\n", hPrinter,
2880 debugstr_a(pKeyName), debugstr_a(pValueName), pType, pData, nSize,
2883 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2887 if((ret = RegOpenKeyA(hkeyPrinter, pKeyName, &hkeySubkey))
2889 WARN("Can't open subkey %s\n", debugstr_a(pKeyName));
2890 RegCloseKey(hkeyPrinter);
2894 ret = RegQueryValueExA(hkeySubkey, pValueName, 0, pType, pData, pcbNeeded);
2895 RegCloseKey(hkeySubkey);
2896 RegCloseKey(hkeyPrinter);
2900 /******************************************************************************
2901 * GetPrinterDataExW (WINSPOOL.@)
2903 DWORD WINAPI GetPrinterDataExW(HANDLE hPrinter, LPWSTR pKeyName,
2904 LPWSTR pValueName, LPDWORD pType,
2905 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2907 HKEY hkeyPrinter, hkeySubkey;
2910 TRACE("(%p, %s, %s %p, %p, %08lx, %p)\n", hPrinter,
2911 debugstr_w(pKeyName), debugstr_w(pValueName), pType, pData, nSize,
2914 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2918 if((ret = RegOpenKeyW(hkeyPrinter, pKeyName, &hkeySubkey))
2920 WARN("Can't open subkey %s\n", debugstr_w(pKeyName));
2921 RegCloseKey(hkeyPrinter);
2925 ret = RegQueryValueExW(hkeySubkey, pValueName, 0, pType, pData, pcbNeeded);
2926 RegCloseKey(hkeySubkey);
2927 RegCloseKey(hkeyPrinter);
2931 /******************************************************************************
2932 * GetPrinterDataA (WINSPOOL.@)
2934 DWORD WINAPI GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType,
2935 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2937 return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType,
2938 pData, nSize, pcbNeeded);
2941 /******************************************************************************
2942 * GetPrinterDataW (WINSPOOL.@)
2944 DWORD WINAPI GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType,
2945 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2947 return GetPrinterDataExW(hPrinter, PrinterDriverDataW, pValueName, pType,
2948 pData, nSize, pcbNeeded);
2951 /*******************************************************************************
2952 * EnumPrinterDataExW [WINSPOOL.@]
2954 DWORD WINAPI EnumPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName,
2955 LPBYTE pEnumValues, DWORD cbEnumValues,
2956 LPDWORD pcbEnumValues, LPDWORD pnEnumValues)
2958 HKEY hkPrinter, hkSubKey;
2959 DWORD r, ret, dwIndex, cValues, cbMaxValueNameLen,
2960 cbValueNameLen, cbMaxValueLen, cbValueLen,
2965 PPRINTER_ENUM_VALUESW ppev;
2967 TRACE ("%p %s\n", hPrinter, debugstr_w (pKeyName));
2969 if (pKeyName == NULL || *pKeyName == 0)
2970 return ERROR_INVALID_PARAMETER;
2972 ret = WINSPOOL_GetOpenedPrinterRegKey (hPrinter, &hkPrinter);
2973 if (ret != ERROR_SUCCESS)
2975 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%p) returned %li\n",
2980 ret = RegOpenKeyExW (hkPrinter, pKeyName, 0, KEY_READ, &hkSubKey);
2981 if (ret != ERROR_SUCCESS)
2983 r = RegCloseKey (hkPrinter);
2984 if (r != ERROR_SUCCESS)
2985 WARN ("RegCloseKey returned %li\n", r);
2986 TRACE ("RegOpenKeyExW (%p, %s) returned %li\n", hPrinter,
2987 debugstr_w (pKeyName), ret);
2991 ret = RegCloseKey (hkPrinter);
2992 if (ret != ERROR_SUCCESS)
2994 ERR ("RegCloseKey returned %li\n", ret);
2995 r = RegCloseKey (hkSubKey);
2996 if (r != ERROR_SUCCESS)
2997 WARN ("RegCloseKey returned %li\n", r);
3001 ret = RegQueryInfoKeyW (hkSubKey, NULL, NULL, NULL, NULL, NULL, NULL,
3002 &cValues, &cbMaxValueNameLen, &cbMaxValueLen, NULL, NULL);
3003 if (ret != ERROR_SUCCESS)
3005 r = RegCloseKey (hkSubKey);
3006 if (r != ERROR_SUCCESS)
3007 WARN ("RegCloseKey returned %li\n", r);
3008 TRACE ("RegQueryInfoKeyW (%p) returned %li\n", hkSubKey, ret);
3012 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
3013 "cbMaxValueLen = %li\n", cValues, cbMaxValueNameLen, cbMaxValueLen);
3015 if (cValues == 0) /* empty key */
3017 r = RegCloseKey (hkSubKey);
3018 if (r != ERROR_SUCCESS)
3019 WARN ("RegCloseKey returned %li\n", r);
3020 *pcbEnumValues = *pnEnumValues = 0;
3021 return ERROR_SUCCESS;
3024 ++cbMaxValueNameLen; /* allow for trailing '\0' */
3026 hHeap = GetProcessHeap ();
3027 if (hHeap == (HANDLE) NULL)
3029 ERR ("GetProcessHeap failed\n");
3030 r = RegCloseKey (hkSubKey);
3031 if (r != ERROR_SUCCESS)
3032 WARN ("RegCloseKey returned %li\n", r);
3033 return ERROR_OUTOFMEMORY;
3036 lpValueName = HeapAlloc (hHeap, 0, cbMaxValueNameLen * sizeof (WCHAR));
3037 if (lpValueName == NULL)
3039 ERR ("Failed to allocate %li bytes from process heap\n",
3040 cbMaxValueNameLen * sizeof (WCHAR));
3041 r = RegCloseKey (hkSubKey);
3042 if (r != ERROR_SUCCESS)
3043 WARN ("RegCloseKey returned %li\n", r);
3044 return ERROR_OUTOFMEMORY;
3047 lpValue = HeapAlloc (hHeap, 0, cbMaxValueLen);
3048 if (lpValue == NULL)
3050 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen);
3051 if (HeapFree (hHeap, 0, lpValueName) == 0)
3052 WARN ("HeapFree failed with code %li\n", GetLastError ());
3053 r = RegCloseKey (hkSubKey);
3054 if (r != ERROR_SUCCESS)
3055 WARN ("RegCloseKey returned %li\n", r);
3056 return ERROR_OUTOFMEMORY;
3059 TRACE ("pass 1: calculating buffer required for all names and values\n");
3061 cbBufSize = cValues * sizeof (PRINTER_ENUM_VALUESW);
3063 TRACE ("%li bytes required for %li headers\n", cbBufSize, cValues);
3065 for (dwIndex = 0; dwIndex < cValues; ++dwIndex)
3067 cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen;
3068 ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen,
3069 NULL, NULL, lpValue, &cbValueLen);
3070 if (ret != ERROR_SUCCESS)
3072 if (HeapFree (hHeap, 0, lpValue) == 0)
3073 WARN ("HeapFree failed with code %li\n", GetLastError ());
3074 if (HeapFree (hHeap, 0, lpValueName) == 0)
3075 WARN ("HeapFree failed with code %li\n", GetLastError ());
3076 r = RegCloseKey (hkSubKey);
3077 if (r != ERROR_SUCCESS)
3078 WARN ("RegCloseKey returned %li\n", r);
3079 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex, ret);
3083 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
3084 debugstr_w (lpValueName), dwIndex,
3085 (cbValueNameLen + 1) * sizeof (WCHAR), cbValueLen);
3087 cbBufSize += (cbValueNameLen + 1) * sizeof (WCHAR);
3088 cbBufSize += cbValueLen;
3091 TRACE ("%li bytes required for all %li values\n", cbBufSize, cValues);
3093 *pcbEnumValues = cbBufSize;
3094 *pnEnumValues = cValues;
3096 if (cbEnumValues < cbBufSize) /* buffer too small */
3098 if (HeapFree (hHeap, 0, lpValue) == 0)
3099 WARN ("HeapFree failed with code %li\n", GetLastError ());
3100 if (HeapFree (hHeap, 0, lpValueName) == 0)
3101 WARN ("HeapFree failed with code %li\n", GetLastError ());
3102 r = RegCloseKey (hkSubKey);
3103 if (r != ERROR_SUCCESS)
3104 WARN ("RegCloseKey returned %li\n", r);
3105 TRACE ("%li byte buffer is not large enough\n", cbEnumValues);
3106 return ERROR_MORE_DATA;
3109 TRACE ("pass 2: copying all names and values to buffer\n");
3111 ppev = (PPRINTER_ENUM_VALUESW) pEnumValues; /* array of structs */
3112 pEnumValues += cValues * sizeof (PRINTER_ENUM_VALUESW);
3114 for (dwIndex = 0; dwIndex < cValues; ++dwIndex)
3116 cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen;
3117 ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen,
3118 NULL, &dwType, lpValue, &cbValueLen);
3119 if (ret != ERROR_SUCCESS)
3121 if (HeapFree (hHeap, 0, lpValue) == 0)
3122 WARN ("HeapFree failed with code %li\n", GetLastError ());
3123 if (HeapFree (hHeap, 0, lpValueName) == 0)
3124 WARN ("HeapFree failed with code %li\n", GetLastError ());
3125 r = RegCloseKey (hkSubKey);
3126 if (r != ERROR_SUCCESS)
3127 WARN ("RegCloseKey returned %li\n", r);
3128 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex, ret);
3132 cbValueNameLen = (cbValueNameLen + 1) * sizeof (WCHAR);
3133 memcpy (pEnumValues, lpValueName, cbValueNameLen);
3134 ppev[dwIndex].pValueName = (LPWSTR) pEnumValues;
3135 pEnumValues += cbValueNameLen;
3137 /* return # of *bytes* (including trailing \0), not # of chars */
3138 ppev[dwIndex].cbValueName = cbValueNameLen;
3140 ppev[dwIndex].dwType = dwType;
3142 memcpy (pEnumValues, lpValue, cbValueLen);
3143 ppev[dwIndex].pData = pEnumValues;
3144 pEnumValues += cbValueLen;
3146 ppev[dwIndex].cbData = cbValueLen;
3148 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
3149 debugstr_w (lpValueName), dwIndex, cbValueNameLen, cbValueLen);
3152 if (HeapFree (hHeap, 0, lpValue) == 0)
3154 ret = GetLastError ();
3155 ERR ("HeapFree failed with code %li\n", ret);
3156 if (HeapFree (hHeap, 0, lpValueName) == 0)
3157 WARN ("HeapFree failed with code %li\n", GetLastError ());
3158 r = RegCloseKey (hkSubKey);
3159 if (r != ERROR_SUCCESS)
3160 WARN ("RegCloseKey returned %li\n", r);
3164 if (HeapFree (hHeap, 0, lpValueName) == 0)
3166 ret = GetLastError ();
3167 ERR ("HeapFree failed with code %li\n", ret);
3168 r = RegCloseKey (hkSubKey);
3169 if (r != ERROR_SUCCESS)
3170 WARN ("RegCloseKey returned %li\n", r);
3174 ret = RegCloseKey (hkSubKey);
3175 if (ret != ERROR_SUCCESS)
3177 ERR ("RegCloseKey returned %li\n", ret);
3181 return ERROR_SUCCESS;
3184 /*******************************************************************************
3185 * EnumPrinterDataExA [WINSPOOL.@]
3187 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
3188 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
3189 * what Windows 2000 SP1 does.
3192 DWORD WINAPI EnumPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName,
3193 LPBYTE pEnumValues, DWORD cbEnumValues,
3194 LPDWORD pcbEnumValues, LPDWORD pnEnumValues)
3198 DWORD ret, dwIndex, dwBufSize;
3202 TRACE ("%p %s\n", hPrinter, pKeyName);
3204 if (pKeyName == NULL || *pKeyName == 0)
3205 return ERROR_INVALID_PARAMETER;
3207 len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0);
3210 ret = GetLastError ();
3211 ERR ("MultiByteToWideChar failed with code %li\n", ret);
3215 hHeap = GetProcessHeap ();
3216 if (hHeap == (HANDLE) NULL)
3218 ERR ("GetProcessHeap failed\n");
3219 return ERROR_OUTOFMEMORY;
3222 pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR));
3223 if (pKeyNameW == NULL)
3225 ERR ("Failed to allocate %li bytes from process heap\n",
3226 (LONG) len * sizeof (WCHAR));
3227 return ERROR_OUTOFMEMORY;
3230 if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0)
3232 ret = GetLastError ();
3233 ERR ("MultiByteToWideChar failed with code %li\n", ret);
3234 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
3235 WARN ("HeapFree failed with code %li\n", GetLastError ());
3239 ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues,
3240 pcbEnumValues, pnEnumValues);
3241 if (ret != ERROR_SUCCESS)
3243 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
3244 WARN ("HeapFree failed with code %li\n", GetLastError ());
3245 TRACE ("EnumPrinterDataExW returned %li\n", ret);
3249 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
3251 ret = GetLastError ();
3252 ERR ("HeapFree failed with code %li\n", ret);
3256 if (*pnEnumValues == 0) /* empty key */
3257 return ERROR_SUCCESS;
3260 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
3262 PPRINTER_ENUM_VALUESW ppev =
3263 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
3265 if (dwBufSize < ppev->cbValueName)
3266 dwBufSize = ppev->cbValueName;
3268 if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ ||
3269 ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
3270 dwBufSize = ppev->cbData;
3273 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize);
3275 pBuffer = HeapAlloc (hHeap, 0, dwBufSize);
3276 if (pBuffer == NULL)
3278 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize);
3279 return ERROR_OUTOFMEMORY;
3282 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
3284 PPRINTER_ENUM_VALUESW ppev =
3285 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
3287 len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName,
3288 ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL,
3292 ret = GetLastError ();
3293 ERR ("WideCharToMultiByte failed with code %li\n", ret);
3294 if (HeapFree (hHeap, 0, pBuffer) == 0)
3295 WARN ("HeapFree failed with code %li\n", GetLastError ());
3299 memcpy (ppev->pValueName, pBuffer, len);
3301 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
3303 if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ &&
3304 ppev->dwType != REG_MULTI_SZ)
3307 len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData,
3308 ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL);
3311 ret = GetLastError ();
3312 ERR ("WideCharToMultiByte failed with code %li\n", ret);
3313 if (HeapFree (hHeap, 0, pBuffer) == 0)
3314 WARN ("HeapFree failed with code %li\n", GetLastError ());
3318 memcpy (ppev->pData, pBuffer, len);
3320 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
3321 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
3324 if (HeapFree (hHeap, 0, pBuffer) == 0)
3326 ret = GetLastError ();
3327 ERR ("HeapFree failed with code %li\n", ret);
3331 return ERROR_SUCCESS;