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("%s not added by AddPrinterA (%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 s = strchr(pent,':');
179 if (!s) return FALSE;
185 /* Determine whether this is a postscript printer. */
187 /* 1. Check if name or aliases contain trigger phrases like 'ps' */
188 if (strstr(name,"ps") ||
189 strstr(name,"pd") || /* postscript double page */
190 strstr(name,"postscript") ||
191 strstr(name,"PostScript")
193 TRACE("%s has 'ps' style name, assuming postscript.\n",name);
196 /* 2. Check if this is a remote printer. These usually are postscript
199 if (strstr(pent,":rm")) {
201 TRACE("%s is remote, assuming postscript.\n",name);
203 /* 3. Check if we have an input filter program. If we have one, it
204 * most likely is one capable of converting postscript.
205 * (Could probably check for occurrence of 'gs' or 'ghostscript'
206 * in the if file itself.)
208 if (strstr(pent,":if=/")) {
210 TRACE("%s has inputfilter program, assuming postscript.\n",name);
213 /* If it is not a postscript printer, we cannot use it. */
218 /* Get longest name, usually the one at the right for later display. */
219 while ((s=strchr(prettyname,'|'))) prettyname = s+1;
220 s=strchr(name,'|');if (s) *s='\0';
222 /* prettyname must fit into the dmDeviceName member of DEVMODE struct,
223 * if it is too long, we use it as comment below. */
224 devname = prettyname;
225 if (strlen(devname)>=CCHDEVICENAME-1)
227 if (strlen(devname)>=CCHDEVICENAME-1)
230 if (isfirst) /* set first entry as default */
231 WINSPOOL_SetDefaultPrinter(devname,name,FALSE);
233 memset(&pinfo2a,0,sizeof(pinfo2a));
234 pinfo2a.pPrinterName = devname;
235 pinfo2a.pDatatype = "RAW";
236 pinfo2a.pPrintProcessor = "WinPrint";
237 pinfo2a.pDriverName = "PS Driver";
238 pinfo2a.pComment = "WINEPS Printer using LPR";
239 pinfo2a.pLocation = prettyname;
240 port = HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(name)+1);
241 sprintf(port,"LPR:%s",name);
242 pinfo2a.pPortName = port;
243 pinfo2a.pParameters = "<parameters?>";
244 pinfo2a.pShareName = "<share name?>";
245 pinfo2a.pSepFile = "<sep file?>";
247 devline=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port)+1);
248 sprintf(devline,"WINEPS,%s",port);
249 WriteProfileStringA("devices",devname,devline);
250 HeapFree(GetProcessHeap(),0,devline);
252 if (!AddPrinterA(NULL,2,(LPBYTE)&pinfo2a)) {
253 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS)
254 ERR("%s not added by AddPrinterA (%ld)\n",name,GetLastError());
256 HeapFree(GetProcessHeap(),0,port);
261 PRINTCAP_LoadPrinters(void) {
262 BOOL hadprinter = FALSE, isfirst = TRUE;
266 f = fopen("/etc/printcap","r");
270 while (fgets(buf,sizeof(buf),f)) {
274 s=strchr(buf,'\n'); if (s) *s='\0';
275 if ((buf[0]=='#') || (buf[0]=='\0'))
279 pent=HeapReAlloc(GetProcessHeap(),0,pent,strlen(pent)+strlen(buf)+2);
282 pent=HeapAlloc(GetProcessHeap(),0,strlen(buf)+1);
286 if (strlen(pent) && (pent[strlen(pent)-1] == '\\'))
287 pent[strlen(pent)-1] = '\0';
290 } while (fgets(buf,sizeof(buf),f));
292 hadprinter |= PRINTCAP_ParseEntry(pent,isfirst);
294 if (pent) HeapFree(GetProcessHeap(),0,pent);
302 static inline DWORD set_reg_szW(HKEY hkey, WCHAR *keyname, WCHAR *value)
304 return RegSetValueExW(hkey, keyname, 0, REG_SZ, (LPBYTE)value,
305 lstrlenW(value) * sizeof(WCHAR));
309 WINSPOOL_LoadSystemPrinters() {
312 di3a.cVersion = 0x400;
313 di3a.pName = "PS Driver";
314 di3a.pEnvironment = NULL; /* NULL means auto */
315 di3a.pDriverPath = "wineps.drv";
316 di3a.pDataFile = "<datafile?>";
317 di3a.pConfigFile = "wineps.drv";
318 di3a.pHelpFile = "<helpfile?>";
319 di3a.pDependentFiles = "<dependend files?>";
320 di3a.pMonitorName = "<monitor name?>";
321 di3a.pDefaultDataType = "RAW";
323 if (!AddPrinterDriverA(NULL,3,(LPBYTE)&di3a)) {
324 ERR("Failed adding PS Driver (%ld)\n",GetLastError());
328 /* If we have any CUPS based printers, skip looking for printcap printers */
329 if (CUPS_LoadPrinters())
333 /* Check for [ppd] section in config file before parsing /etc/printcap */
335 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\ppd",
336 &hkPPD) == ERROR_SUCCESS)
339 PRINTCAP_LoadPrinters();
344 /******************************************************************
345 * WINSPOOL_GetOpenedPrinterEntry
346 * Get the first place empty in the opened printer table
348 static HANDLE WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name )
352 for (i = 0; i < nb_printers; i++) if (!printer_array[i]) break;
354 if (i >= nb_printers)
356 LPWSTR *new_array = HeapReAlloc( GetProcessHeap(), 0, printer_array,
357 (nb_printers + 16) * sizeof(*new_array) );
358 if (!new_array) return 0;
359 printer_array = new_array;
363 if ((printer_array[i] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name)+1)*sizeof(WCHAR) )))
365 strcpyW( printer_array[i], name );
366 return (HANDLE)(i + 1);
371 /******************************************************************
372 * WINSPOOL_GetOpenedPrinter
373 * Get the pointer to the opened printer referred by the handle
375 static LPCWSTR WINSPOOL_GetOpenedPrinter(HANDLE printerHandle)
377 int idx = (int)printerHandle;
378 if ((idx <= 0) || (idx > nb_printers))
380 SetLastError(ERROR_INVALID_HANDLE);
383 return printer_array[idx - 1];
386 /******************************************************************
387 * WINSPOOL_GetOpenedPrinterRegKey
390 static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey)
392 LPCWSTR name = WINSPOOL_GetOpenedPrinter(hPrinter);
396 if(!name) return ERROR_INVALID_HANDLE;
398 if((ret = RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters)) !=
402 if(RegOpenKeyW(hkeyPrinters, name, phkey) != ERROR_SUCCESS)
404 ERR("Can't find opened printer %s in registry\n",
406 RegCloseKey(hkeyPrinters);
407 return ERROR_INVALID_PRINTER_NAME; /* ? */
409 RegCloseKey(hkeyPrinters);
410 return ERROR_SUCCESS;
413 /***********************************************************
416 static LPDEVMODEW DEVMODEcpyAtoW(DEVMODEW *dmW, const DEVMODEA *dmA)
419 ptrdiff_t off_formname = (char *)dmA->dmFormName - (char *)dmA;
422 Formname = (dmA->dmSize > off_formname);
423 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
424 MultiByteToWideChar(CP_ACP, 0, dmA->dmDeviceName, -1, dmW->dmDeviceName,
427 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
428 dmA->dmSize - CCHDEVICENAME);
430 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
431 off_formname - CCHDEVICENAME);
432 MultiByteToWideChar(CP_ACP, 0, dmA->dmFormName, -1, dmW->dmFormName,
434 memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA->dmSize -
435 (off_formname + CCHFORMNAME));
438 memcpy((char *)dmW + dmW->dmSize, (char *)dmA + dmA->dmSize,
443 /***********************************************************
445 * Creates a unicode copy of supplied devmode on heap
447 static LPDEVMODEW DEVMODEdupAtoW(HANDLE heap, const DEVMODEA *dmA)
452 ptrdiff_t off_formname;
455 if(!dmA) return NULL;
457 off_formname = (char *)dmA->dmFormName - (char *)dmA;
458 Formname = (dmA->dmSize > off_formname);
459 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
460 dmW = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmA->dmDriverExtra);
461 return DEVMODEcpyAtoW(dmW, dmA);
464 /***********************************************************
466 * Creates an ascii copy of supplied devmode on heap
468 static LPDEVMODEA DEVMODEdupWtoA(HANDLE heap, const DEVMODEW *dmW)
473 ptrdiff_t off_formname = (char *)dmW->dmFormName - (char *)dmW;
475 if(!dmW) return NULL;
476 Formname = (dmW->dmSize > off_formname);
477 size = dmW->dmSize - CCHDEVICENAME - (Formname ? CCHFORMNAME : 0);
478 dmA = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmW->dmDriverExtra);
479 WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, dmA->dmDeviceName,
480 CCHDEVICENAME, NULL, NULL);
482 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
483 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR));
485 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
486 off_formname - CCHDEVICENAME * sizeof(WCHAR));
487 WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, dmA->dmFormName,
488 CCHFORMNAME, NULL, NULL);
489 memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize -
490 (off_formname + CCHFORMNAME * sizeof(WCHAR)));
493 memcpy((char *)dmA + dmA->dmSize, (char *)dmW + dmW->dmSize,
498 /***********************************************************
500 * Creates a unicode copy of PRINTER_INFO_2A on heap
502 static LPPRINTER_INFO_2W PRINTER_INFO_2AtoW(HANDLE heap, LPPRINTER_INFO_2A piA)
504 LPPRINTER_INFO_2W piW;
505 if(!piA) return NULL;
506 piW = HeapAlloc(heap, 0, sizeof(*piW));
507 memcpy(piW, piA, sizeof(*piW)); /* copy everything first */
508 piW->pServerName = HEAP_strdupAtoW(heap, 0, piA->pServerName);
509 piW->pPrinterName = HEAP_strdupAtoW(heap, 0, piA->pPrinterName);
510 piW->pShareName = HEAP_strdupAtoW(heap, 0, piA->pShareName);
511 piW->pPortName = HEAP_strdupAtoW(heap, 0, piA->pPortName);
512 piW->pDriverName = HEAP_strdupAtoW(heap, 0, piA->pDriverName);
513 piW->pComment = HEAP_strdupAtoW(heap, 0, piA->pComment);
514 piW->pLocation = HEAP_strdupAtoW(heap, 0, piA->pLocation);
515 piW->pDevMode = DEVMODEdupAtoW(heap, piA->pDevMode);
516 piW->pSepFile = HEAP_strdupAtoW(heap, 0, piA->pSepFile);
517 piW->pPrintProcessor = HEAP_strdupAtoW(heap, 0, piA->pPrintProcessor);
518 piW->pDatatype = HEAP_strdupAtoW(heap, 0, piA->pDatatype);
519 piW->pParameters = HEAP_strdupAtoW(heap, 0, piA->pParameters);
523 /***********************************************************
524 * FREE_PRINTER_INFO_2W
525 * Free PRINTER_INFO_2W and all strings
527 static void FREE_PRINTER_INFO_2W(HANDLE heap, LPPRINTER_INFO_2W piW)
531 HeapFree(heap,0,piW->pServerName);
532 HeapFree(heap,0,piW->pPrinterName);
533 HeapFree(heap,0,piW->pShareName);
534 HeapFree(heap,0,piW->pPortName);
535 HeapFree(heap,0,piW->pDriverName);
536 HeapFree(heap,0,piW->pComment);
537 HeapFree(heap,0,piW->pLocation);
538 HeapFree(heap,0,piW->pDevMode);
539 HeapFree(heap,0,piW->pSepFile);
540 HeapFree(heap,0,piW->pPrintProcessor);
541 HeapFree(heap,0,piW->pDatatype);
542 HeapFree(heap,0,piW->pParameters);
543 HeapFree(heap,0,piW);
547 /******************************************************************
548 * DeviceCapabilities [WINSPOOL.@]
549 * DeviceCapabilitiesA [WINSPOOL.@]
552 INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap,
553 LPSTR pOutput, LPDEVMODEA lpdm)
557 if (!GDI_CallDeviceCapabilities16)
559 GDI_CallDeviceCapabilities16 = (void*)GetProcAddress( GetModuleHandleA("gdi32"),
561 if (!GDI_CallDeviceCapabilities16) return -1;
563 ret = GDI_CallDeviceCapabilities16(pDevice, pPort, cap, pOutput, lpdm);
565 /* If DC_PAPERSIZE map POINT16s to POINTs */
566 if(ret != -1 && cap == DC_PAPERSIZE && pOutput) {
567 POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) );
568 POINT *pt = (POINT *)pOutput;
570 memcpy(tmp, pOutput, ret * sizeof(POINT16));
571 for(i = 0; i < ret; i++, pt++)
576 HeapFree( GetProcessHeap(), 0, tmp );
582 /*****************************************************************************
583 * DeviceCapabilitiesW [WINSPOOL.@]
585 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
588 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
589 WORD fwCapability, LPWSTR pOutput,
590 const DEVMODEW *pDevMode)
592 LPDEVMODEA dmA = DEVMODEdupWtoA(GetProcessHeap(), pDevMode);
593 LPSTR pDeviceA = HEAP_strdupWtoA(GetProcessHeap(),0,pDevice);
594 LPSTR pPortA = HEAP_strdupWtoA(GetProcessHeap(),0,pPort);
597 if(pOutput && (fwCapability == DC_BINNAMES ||
598 fwCapability == DC_FILEDEPENDENCIES ||
599 fwCapability == DC_PAPERNAMES)) {
600 /* These need A -> W translation */
603 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, NULL,
607 switch(fwCapability) {
612 case DC_FILEDEPENDENCIES:
616 pOutputA = HeapAlloc(GetProcessHeap(), 0, size * ret);
617 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, pOutputA,
619 for(i = 0; i < ret; i++)
620 MultiByteToWideChar(CP_ACP, 0, pOutputA + (i * size), -1,
621 pOutput + (i * size), size);
622 HeapFree(GetProcessHeap(), 0, pOutputA);
624 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability,
625 (LPSTR)pOutput, dmA);
627 HeapFree(GetProcessHeap(),0,pPortA);
628 HeapFree(GetProcessHeap(),0,pDeviceA);
629 HeapFree(GetProcessHeap(),0,dmA);
633 /******************************************************************
634 * DocumentPropertiesA [WINSPOOL.@]
637 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
638 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
639 LPDEVMODEA pDevModeInput,DWORD fMode )
641 LPSTR lpName = pDeviceName;
644 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
645 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
649 LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
651 ERR("no name from hPrinter?\n");
654 lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
657 if (!GDI_CallExtDeviceMode16)
659 GDI_CallExtDeviceMode16 = (void*)GetProcAddress( GetModuleHandleA("gdi32"),
661 if (!GDI_CallExtDeviceMode16) {
662 ERR("No CallExtDeviceMode16?\n");
666 ret = GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
667 pDevModeInput, NULL, fMode);
670 HeapFree(GetProcessHeap(),0,lpName);
675 /*****************************************************************************
676 * DocumentPropertiesW (WINSPOOL.@)
678 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
680 LPDEVMODEW pDevModeOutput,
681 LPDEVMODEW pDevModeInput, DWORD fMode)
684 LPSTR pDeviceNameA = HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName);
685 LPDEVMODEA pDevModeInputA = DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput);
686 LPDEVMODEA pDevModeOutputA = NULL;
689 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
690 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
693 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, NULL, NULL, 0);
694 if(ret < 0) return ret;
695 pDevModeOutputA = HeapAlloc(GetProcessHeap(), 0, ret);
697 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, pDevModeOutputA,
698 pDevModeInputA, fMode);
700 DEVMODEcpyAtoW(pDevModeOutput, pDevModeOutputA);
701 HeapFree(GetProcessHeap(),0,pDevModeOutputA);
703 if(fMode == 0 && ret > 0)
704 ret += (CCHDEVICENAME + CCHFORMNAME);
705 HeapFree(GetProcessHeap(),0,pDevModeInputA);
706 HeapFree(GetProcessHeap(),0,pDeviceNameA);
710 /******************************************************************
711 * OpenPrinterA [WINSPOOL.@]
714 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
715 LPPRINTER_DEFAULTSA pDefault)
717 LPWSTR lpPrinterNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName);
718 PRINTER_DEFAULTSW DefaultW, *pDefaultW = NULL;
722 DefaultW.pDatatype = HEAP_strdupAtoW(GetProcessHeap(), 0,
723 pDefault->pDatatype);
724 DefaultW.pDevMode = DEVMODEdupAtoW(GetProcessHeap(),
726 DefaultW.DesiredAccess = pDefault->DesiredAccess;
727 pDefaultW = &DefaultW;
729 ret = OpenPrinterW(lpPrinterNameW, phPrinter, pDefaultW);
731 HeapFree(GetProcessHeap(), 0, DefaultW.pDatatype);
732 HeapFree(GetProcessHeap(), 0, DefaultW.pDevMode);
734 HeapFree(GetProcessHeap(), 0, lpPrinterNameW);
738 /******************************************************************
739 * OpenPrinterW [WINSPOOL.@]
742 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
743 LPPRINTER_DEFAULTSW pDefault)
745 HKEY hkeyPrinters, hkeyPrinter;
747 if (!lpPrinterName) {
748 FIXME("(printerName: NULL, pDefault %p Ret: False\n", pDefault);
749 SetLastError(ERROR_INVALID_PARAMETER);
753 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName),
756 /* Check Printer exists */
757 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
759 ERR("Can't create Printers key\n");
760 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
764 if(lpPrinterName[0] == '\0' || /* explicitly exclude "" */
765 RegOpenKeyW(hkeyPrinters, lpPrinterName, &hkeyPrinter)
767 TRACE("Can't find printer %s in registry\n",
768 debugstr_w(lpPrinterName));
769 RegCloseKey(hkeyPrinters);
770 SetLastError(ERROR_INVALID_PRINTER_NAME);
773 RegCloseKey(hkeyPrinter);
774 RegCloseKey(hkeyPrinters);
776 if(!phPrinter) /* This seems to be what win95 does anyway */
779 /* Get the unique handle of the printer*/
780 *phPrinter = WINSPOOL_GetOpenedPrinterEntry( lpPrinterName );
782 if (pDefault != NULL)
783 FIXME("Not handling pDefault\n");
788 /******************************************************************
789 * AddMonitorA [WINSPOOL.@]
792 BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors)
794 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
795 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
799 /******************************************************************
800 * DeletePrinterDriverA [WINSPOOL.@]
804 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
806 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
807 debugstr_a(pDriverName));
808 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
813 /******************************************************************
814 * DeleteMonitorA [WINSPOOL.@]
818 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
820 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
821 debugstr_a(pMonitorName));
822 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
827 /******************************************************************
828 * DeletePortA [WINSPOOL.@]
832 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
834 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
835 debugstr_a(pPortName));
836 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
840 /******************************************************************************
841 * SetPrinterW [WINSPOOL.@]
851 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
855 /******************************************************************************
856 * WritePrinter [WINSPOOL.@]
866 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
870 /*****************************************************************************
871 * AddFormA [WINSPOOL.@]
873 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
875 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
879 /*****************************************************************************
880 * AddFormW [WINSPOOL.@]
882 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
884 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
888 /*****************************************************************************
889 * AddJobA [WINSPOOL.@]
891 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
892 DWORD cbBuf, LPDWORD pcbNeeded)
894 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
899 /*****************************************************************************
900 * AddJobW [WINSPOOL.@]
902 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
905 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
910 /*****************************************************************************
911 * WINSPOOL_OpenDriverReg [internal]
913 * opens the registry for the printer drivers depending on the given input
914 * variable pEnvironment
917 * the opened hkey on success
920 static HKEY WINSPOOL_OpenDriverReg( LPVOID pEnvironment, BOOL unicode)
922 LPSTR lpKey, p = NULL;
925 (unicode) ? debugstr_w(pEnvironment) : debugstr_a(pEnvironment));
928 p = (unicode) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment) :
932 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
934 if(!GetVersionExA( &ver))
937 switch (ver.dwPlatformId) {
938 case VER_PLATFORM_WIN32s:
939 ERR("win32 style printing used with 16 bits app, try -winver win95\n");
942 case VER_PLATFORM_WIN32_NT:
943 p = "Windows NT x86";
949 TRACE("set environment to %s\n", p);
952 lpKey = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
953 strlen(p) + strlen(Drivers));
954 sprintf( lpKey, Drivers, p);
956 TRACE("%s\n", lpKey);
958 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, lpKey, &retval) !=
962 if(pEnvironment && unicode)
963 HeapFree( GetProcessHeap(), 0, p);
964 HeapFree( GetProcessHeap(), 0, lpKey);
969 /*****************************************************************************
970 * AddPrinterW [WINSPOOL.@]
972 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
974 PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
978 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
981 TRACE("(%s,%ld,%p)\n", debugstr_w(pName), Level, pPrinter);
984 ERR("pName = %s - unsupported\n", debugstr_w(pName));
985 SetLastError(ERROR_INVALID_PARAMETER);
989 ERR("Level = %ld, unsupported!\n", Level);
990 SetLastError(ERROR_INVALID_LEVEL);
993 if (strlenW(pi->pPrinterName) >= CCHDEVICENAME) {
994 ERR("Printername %s must not exceed length of DEVMODE.dmDeviceName !\n",
995 debugstr_w(pi->pPrinterName)
997 SetLastError(ERROR_INVALID_LEVEL);
1001 SetLastError(ERROR_INVALID_PARAMETER);
1004 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1006 ERR("Can't create Printers key\n");
1009 if(!RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter)) {
1010 if (!RegQueryValueA(hkeyPrinter,"Attributes",NULL,NULL)) {
1011 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
1012 RegCloseKey(hkeyPrinter);
1013 RegCloseKey(hkeyPrinters);
1016 RegCloseKey(hkeyPrinter);
1018 hkeyDrivers = WINSPOOL_OpenDriverReg( NULL, TRUE);
1020 ERR("Can't create Drivers key\n");
1021 RegCloseKey(hkeyPrinters);
1024 if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
1026 WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
1027 RegCloseKey(hkeyPrinters);
1028 RegCloseKey(hkeyDrivers);
1029 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
1032 RegCloseKey(hkeyDriver);
1033 RegCloseKey(hkeyDrivers);
1035 if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) { /* FIXME */
1036 FIXME("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
1037 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
1038 RegCloseKey(hkeyPrinters);
1042 if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
1044 FIXME("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
1045 SetLastError(ERROR_INVALID_PRINTER_NAME);
1046 RegCloseKey(hkeyPrinters);
1049 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
1050 (LPBYTE)&pi->Attributes, sizeof(DWORD));
1051 set_reg_szW(hkeyPrinter, DatatypeW, pi->pDatatype);
1053 /* See if we can load the driver. We may need the devmode structure anyway
1056 * Note that DocumentPropertiesW will briefly try to open the printer we
1057 * just create to find a DEVMODEA struct (it will use the WINEPS default
1058 * one in case it is not there, so we are ok).
1060 size = DocumentPropertiesW(0, -1, pi->pPrinterName, NULL, NULL, 0);
1062 FIXME("DocumentProperties fails\n");
1063 size = sizeof(DEVMODEW);
1068 dmW = HeapAlloc(GetProcessHeap(), 0, size);
1070 if (0>DocumentPropertiesW(0,-1,pi->pPrinterName,dmW,NULL,DM_OUT_BUFFER)) {
1071 ERR("DocumentPropertiesW failed!\n");
1072 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
1075 /* set devmode to printer name */
1076 strcpyW(dmW->dmDeviceName,pi->pPrinterName);
1079 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
1080 and we support these drivers. NT writes DEVMODEW so somehow
1081 we'll need to distinguish between these when we support NT
1083 dmA = DEVMODEdupWtoA(GetProcessHeap(), dmW);
1084 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, (LPBYTE)dmA,
1085 dmA->dmSize + dmA->dmDriverExtra);
1086 HeapFree(GetProcessHeap(), 0, dmA);
1088 HeapFree(GetProcessHeap(), 0, dmW);
1089 set_reg_szW(hkeyPrinter, DescriptionW, pi->pComment);
1090 set_reg_szW(hkeyPrinter, LocationW, pi->pLocation);
1091 set_reg_szW(hkeyPrinter, NameW, pi->pPrinterName);
1092 set_reg_szW(hkeyPrinter, ParametersW, pi->pParameters);
1094 set_reg_szW(hkeyPrinter, PortW, pi->pPortName);
1095 set_reg_szW(hkeyPrinter, Print_ProcessorW, pi->pPrintProcessor);
1096 set_reg_szW(hkeyPrinter, Printer_DriverW, pi->pDriverName);
1097 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
1098 (LPBYTE)&pi->Priority, sizeof(DWORD));
1099 set_reg_szW(hkeyPrinter, Separator_FileW, pi->pSepFile);
1100 set_reg_szW(hkeyPrinter, Share_NameW, pi->pShareName);
1101 RegSetValueExA(hkeyPrinter, "StartTime", 0, REG_DWORD,
1102 (LPBYTE)&pi->StartTime, sizeof(DWORD));
1103 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
1104 (LPBYTE)&pi->Status, sizeof(DWORD));
1105 RegSetValueExA(hkeyPrinter, "UntilTime", 0, REG_DWORD,
1106 (LPBYTE)&pi->UntilTime, sizeof(DWORD));
1108 RegCloseKey(hkeyPrinter);
1109 RegCloseKey(hkeyPrinters);
1110 if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
1111 ERR("OpenPrinter failing\n");
1117 /*****************************************************************************
1118 * AddPrinterA [WINSPOOL.@]
1120 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
1123 PRINTER_INFO_2W *piW;
1124 PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter;
1127 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName), Level, pPrinter);
1129 ERR("Level = %ld, unsupported!\n", Level);
1130 SetLastError(ERROR_INVALID_LEVEL);
1133 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
1134 piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA);
1136 ret = AddPrinterW(pNameW, Level, (LPBYTE)piW);
1138 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW);
1139 HeapFree(GetProcessHeap(),0,pNameW);
1144 /*****************************************************************************
1145 * ClosePrinter [WINSPOOL.@]
1147 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
1149 int i = (int)hPrinter;
1151 TRACE("Handle %d\n", hPrinter);
1153 if ((i <= 0) || (i > nb_printers)) return FALSE;
1154 HeapFree( GetProcessHeap(), 0, printer_array[i - 1] );
1155 printer_array[i - 1] = NULL;
1159 /*****************************************************************************
1160 * DeleteFormA [WINSPOOL.@]
1162 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
1164 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
1168 /*****************************************************************************
1169 * DeleteFormW [WINSPOOL.@]
1171 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
1173 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
1177 /*****************************************************************************
1178 * DeletePrinter [WINSPOOL.@]
1180 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
1182 LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
1185 if(!lpNameW) return FALSE;
1186 if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1188 ERR("Can't open Printers key\n");
1192 /* This should use a recursive delete see Q142491 or SHDeleteKey */
1193 if(RegDeleteKeyW(hkeyPrinters, lpNameW) == ERROR_SUCCESS) {
1194 SetLastError(ERROR_PRINTER_NOT_FOUND); /* ?? */
1195 RegCloseKey(hkeyPrinters);
1199 ClosePrinter(hPrinter);
1203 /*****************************************************************************
1204 * SetPrinterA [WINSPOOL.@]
1206 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1209 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
1213 /*****************************************************************************
1214 * SetJobA [WINSPOOL.@]
1216 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
1217 LPBYTE pJob, DWORD Command)
1219 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1224 /*****************************************************************************
1225 * SetJobW [WINSPOOL.@]
1227 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
1228 LPBYTE pJob, DWORD Command)
1230 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1235 /*****************************************************************************
1236 * GetFormA [WINSPOOL.@]
1238 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1239 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1241 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
1242 Level,pForm,cbBuf,pcbNeeded);
1246 /*****************************************************************************
1247 * GetFormW [WINSPOOL.@]
1249 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1250 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1252 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
1253 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
1257 /*****************************************************************************
1258 * SetFormA [WINSPOOL.@]
1260 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1263 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1267 /*****************************************************************************
1268 * SetFormW [WINSPOOL.@]
1270 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1273 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1277 /*****************************************************************************
1278 * ReadPrinter [WINSPOOL.@]
1280 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1281 LPDWORD pNoBytesRead)
1283 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1287 /*****************************************************************************
1288 * ResetPrinterA [WINSPOOL.@]
1290 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1292 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1296 /*****************************************************************************
1297 * ResetPrinterW [WINSPOOL.@]
1299 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1301 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1305 /*****************************************************************************
1306 * WINSPOOL_GetDWORDFromReg
1308 * Return DWORD associated with ValueName from hkey.
1310 static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName)
1312 DWORD sz = sizeof(DWORD), type, value = 0;
1315 ret = RegQueryValueExA(hkey, ValueName, 0, &type, (LPBYTE)&value, &sz);
1317 if(ret != ERROR_SUCCESS) {
1318 WARN("Got ret = %ld on name %s\n", ret, ValueName);
1321 if(type != REG_DWORD) {
1322 ERR("Got type %ld\n", type);
1328 /*****************************************************************************
1329 * WINSPOOL_GetStringFromReg
1331 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1332 * String is stored either as unicode or ascii.
1333 * Bit of a hack here to get the ValueName if we want ascii.
1335 static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr,
1336 DWORD buflen, DWORD *needed,
1339 DWORD sz = buflen, type;
1343 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1345 LPSTR ValueNameA = HEAP_strdupWtoA(GetProcessHeap(),0,ValueName);
1346 ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz);
1347 HeapFree(GetProcessHeap(),0,ValueNameA);
1349 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1350 WARN("Got ret = %ld\n", ret);
1358 /*****************************************************************************
1359 * WINSPOOL_GetDefaultDevMode
1361 * Get a default DevMode values for wineps.
1365 static void WINSPOOL_GetDefaultDevMode(
1367 DWORD buflen, DWORD *needed,
1372 /* fill default DEVMODE - should be read from ppd... */
1373 ZeroMemory( &dm, sizeof(dm) );
1374 strcpy(dm.dmDeviceName,"wineps");
1375 dm.dmSpecVersion = DM_SPECVERSION;
1376 dm.dmDriverVersion = 1;
1377 dm.dmSize = sizeof(DEVMODEA);
1378 dm.dmDriverExtra = 0;
1380 DM_ORIENTATION | DM_PAPERSIZE |
1381 DM_PAPERLENGTH | DM_PAPERWIDTH |
1384 DM_DEFAULTSOURCE | DM_PRINTQUALITY |
1385 DM_YRESOLUTION | DM_TTOPTION;
1387 dm.u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1388 dm.u1.s1.dmPaperSize = DMPAPER_A4;
1389 dm.u1.s1.dmPaperLength = 2970;
1390 dm.u1.s1.dmPaperWidth = 2100;
1394 dm.dmDefaultSource = DMBIN_AUTO;
1395 dm.dmPrintQuality = DMRES_MEDIUM;
1398 dm.dmYResolution = 300; /* 300dpi */
1399 dm.dmTTOption = DMTT_BITMAP;
1402 /* dm.dmLogPixels */
1403 /* dm.dmBitsPerPel */
1404 /* dm.dmPelsWidth */
1405 /* dm.dmPelsHeight */
1406 /* dm.dmDisplayFlags */
1407 /* dm.dmDisplayFrequency */
1408 /* dm.dmICMMethod */
1409 /* dm.dmICMIntent */
1410 /* dm.dmMediaType */
1411 /* dm.dmDitherType */
1412 /* dm.dmReserved1 */
1413 /* dm.dmReserved2 */
1414 /* dm.dmPanningWidth */
1415 /* dm.dmPanningHeight */
1418 if(buflen >= sizeof(DEVMODEW)) {
1419 DEVMODEW *pdmW = DEVMODEdupAtoW(GetProcessHeap(), &dm );
1420 memcpy(ptr, pdmW, sizeof(DEVMODEW));
1421 HeapFree(GetProcessHeap(),0,pdmW);
1423 *needed = sizeof(DEVMODEW);
1427 if(buflen >= sizeof(DEVMODEA)) {
1428 memcpy(ptr, &dm, sizeof(DEVMODEA));
1430 *needed = sizeof(DEVMODEA);
1434 /*****************************************************************************
1435 * WINSPOOL_GetDevModeFromReg
1437 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1438 * DevMode is stored either as unicode or ascii.
1440 static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
1442 DWORD buflen, DWORD *needed,
1445 DWORD sz = buflen, type;
1448 if (ptr && buflen>=sizeof(DEVMODEA)) memset(ptr, 0, sizeof(DEVMODEA));
1449 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1450 if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
1451 if (sz < sizeof(DEVMODEA))
1453 ERR("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName),sz);
1456 /* ensures that dmSize is not erratically bogus if registry is invalid */
1457 if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA))
1458 ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA);
1460 sz += (CCHDEVICENAME + CCHFORMNAME);
1462 DEVMODEW *dmW = DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA*)ptr);
1463 memcpy(ptr, dmW, sz);
1464 HeapFree(GetProcessHeap(),0,dmW);
1471 /*********************************************************************
1472 * WINSPOOL_GetPrinter_2
1474 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1475 * The strings are either stored as unicode or ascii.
1477 static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2,
1478 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1481 DWORD size, left = cbBuf;
1482 BOOL space = (cbBuf > 0);
1487 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1489 if(space && size <= left) {
1490 pi2->pPrinterName = (LPWSTR)ptr;
1497 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size,
1499 if(space && size <= left) {
1500 pi2->pShareName = (LPWSTR)ptr;
1507 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1509 if(space && size <= left) {
1510 pi2->pPortName = (LPWSTR)ptr;
1517 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left,
1519 if(space && size <= left) {
1520 pi2->pDriverName = (LPWSTR)ptr;
1527 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size,
1529 if(space && size <= left) {
1530 pi2->pComment = (LPWSTR)ptr;
1537 if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size,
1539 if(space && size <= left) {
1540 pi2->pLocation = (LPWSTR)ptr;
1547 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left,
1549 if(space && size <= left) {
1550 pi2->pDevMode = (LPDEVMODEW)ptr;
1559 MESSAGE( "no DevMode in registry. please setup your printer again.\n"
1560 "use the default hard-coded DevMode(wineps/A4/300dpi).\n" );
1561 WINSPOOL_GetDefaultDevMode(ptr, left, &size, unicode);
1562 if(space && size <= left) {
1563 pi2->pDevMode = (LPDEVMODEW)ptr;
1570 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left,
1572 if(space && size <= left) {
1573 pi2->pSepFile = (LPWSTR)ptr;
1580 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left,
1582 if(space && size <= left) {
1583 pi2->pPrintProcessor = (LPWSTR)ptr;
1590 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left,
1592 if(space && size <= left) {
1593 pi2->pDatatype = (LPWSTR)ptr;
1600 if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left,
1602 if(space && size <= left) {
1603 pi2->pParameters = (LPWSTR)ptr;
1611 pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1612 pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority");
1613 pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1614 "Default Priority");
1615 pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime");
1616 pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime");
1619 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
1620 memset(pi2, 0, sizeof(*pi2));
1625 /*********************************************************************
1626 * WINSPOOL_GetPrinter_4
1628 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1630 static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4,
1631 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1634 DWORD size, left = cbBuf;
1635 BOOL space = (cbBuf > 0);
1640 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1642 if(space && size <= left) {
1643 pi4->pPrinterName = (LPWSTR)ptr;
1651 pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1654 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
1655 memset(pi4, 0, sizeof(*pi4));
1660 /*********************************************************************
1661 * WINSPOOL_GetPrinter_5
1663 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1665 static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5,
1666 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1669 DWORD size, left = cbBuf;
1670 BOOL space = (cbBuf > 0);
1675 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1677 if(space && size <= left) {
1678 pi5->pPrinterName = (LPWSTR)ptr;
1685 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1687 if(space && size <= left) {
1688 pi5->pPortName = (LPWSTR)ptr;
1696 pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1697 pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1699 pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1703 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
1704 memset(pi5, 0, sizeof(*pi5));
1709 /*****************************************************************************
1710 * WINSPOOL_GetPrinter
1712 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1713 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1714 * just a collection of pointers to strings.
1716 static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1717 DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
1720 DWORD size, needed = 0;
1722 HKEY hkeyPrinter, hkeyPrinters;
1725 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1727 if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE;
1729 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1731 ERR("Can't create Printers key\n");
1734 if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter) != ERROR_SUCCESS)
1736 ERR("Can't find opened printer %s in registry\n", debugstr_w(name));
1737 RegCloseKey(hkeyPrinters);
1738 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1745 PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter;
1747 size = sizeof(PRINTER_INFO_2W);
1749 ptr = pPrinter + size;
1751 memset(pPrinter, 0, size);
1756 ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed,
1764 PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter;
1766 size = sizeof(PRINTER_INFO_4W);
1768 ptr = pPrinter + size;
1770 memset(pPrinter, 0, size);
1775 ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed,
1784 PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter;
1786 size = sizeof(PRINTER_INFO_5W);
1788 ptr = pPrinter + size;
1790 memset(pPrinter, 0, size);
1796 ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed,
1803 FIXME("Unimplemented level %ld\n", Level);
1804 SetLastError(ERROR_INVALID_LEVEL);
1805 RegCloseKey(hkeyPrinters);
1806 RegCloseKey(hkeyPrinter);
1810 RegCloseKey(hkeyPrinter);
1811 RegCloseKey(hkeyPrinters);
1813 TRACE("returing %d needed = %ld\n", ret, needed);
1814 if(pcbNeeded) *pcbNeeded = needed;
1816 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1820 /*****************************************************************************
1821 * GetPrinterW [WINSPOOL.@]
1823 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1824 DWORD cbBuf, LPDWORD pcbNeeded)
1826 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1830 /*****************************************************************************
1831 * GetPrinterA [WINSPOOL.@]
1833 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1834 DWORD cbBuf, LPDWORD pcbNeeded)
1836 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1840 /*****************************************************************************
1841 * WINSPOOL_EnumPrinters
1843 * Implementation of EnumPrintersA|W
1845 static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName,
1846 DWORD dwLevel, LPBYTE lpbPrinters,
1847 DWORD cbBuf, LPDWORD lpdwNeeded,
1848 LPDWORD lpdwReturned, BOOL unicode)
1851 HKEY hkeyPrinters, hkeyPrinter;
1852 WCHAR PrinterName[255];
1853 DWORD needed = 0, number = 0;
1854 DWORD used, i, left;
1858 memset(lpbPrinters, 0, cbBuf);
1864 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1865 if(dwType == PRINTER_ENUM_DEFAULT)
1868 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1869 FIXME("dwType = %08lx\n", dwType);
1870 SetLastError(ERROR_INVALID_FLAGS);
1874 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1876 ERR("Can't create Printers key\n");
1880 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1881 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1882 RegCloseKey(hkeyPrinters);
1883 ERR("Can't query Printers key\n");
1886 TRACE("Found %ld printers\n", number);
1890 RegCloseKey(hkeyPrinters);
1892 *lpdwReturned = number;
1896 used = number * sizeof(PRINTER_INFO_2W);
1899 used = number * sizeof(PRINTER_INFO_4W);
1902 used = number * sizeof(PRINTER_INFO_5W);
1906 SetLastError(ERROR_INVALID_LEVEL);
1907 RegCloseKey(hkeyPrinters);
1910 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1912 for(i = 0; i < number; i++) {
1913 if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1915 ERR("Can't enum key number %ld\n", i);
1916 RegCloseKey(hkeyPrinters);
1919 TRACE("Printer %ld is %s\n", i, debugstr_w(PrinterName));
1920 if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1922 ERR("Can't open key %s\n", debugstr_w(PrinterName));
1923 RegCloseKey(hkeyPrinters);
1928 buf = lpbPrinters + used;
1929 left = cbBuf - used;
1937 WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf,
1938 left, &needed, unicode);
1940 if(pi) pi += sizeof(PRINTER_INFO_2W);
1943 WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf,
1944 left, &needed, unicode);
1946 if(pi) pi += sizeof(PRINTER_INFO_4W);
1949 WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf,
1950 left, &needed, unicode);
1952 if(pi) pi += sizeof(PRINTER_INFO_5W);
1955 ERR("Shouldn't be here!\n");
1956 RegCloseKey(hkeyPrinter);
1957 RegCloseKey(hkeyPrinters);
1960 RegCloseKey(hkeyPrinter);
1962 RegCloseKey(hkeyPrinters);
1969 memset(lpbPrinters, 0, cbBuf);
1970 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1974 *lpdwReturned = number;
1975 SetLastError(ERROR_SUCCESS);
1980 /******************************************************************
1981 * EnumPrintersW [WINSPOOL.@]
1983 * Enumerates the available printers, print servers and print
1984 * providers, depending on the specified flags, name and level.
1988 * If level is set to 1:
1989 * Not implemented yet!
1990 * Returns TRUE with an empty list.
1992 * If level is set to 2:
1993 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1994 * Returns an array of PRINTER_INFO_2 data structures in the
1995 * lpbPrinters buffer. Note that according to MSDN also an
1996 * OpenPrinter should be performed on every remote printer.
1998 * If level is set to 4 (officially WinNT only):
1999 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
2000 * Fast: Only the registry is queried to retrieve printer names,
2001 * no connection to the driver is made.
2002 * Returns an array of PRINTER_INFO_4 data structures in the
2003 * lpbPrinters buffer.
2005 * If level is set to 5 (officially WinNT4/Win9x only):
2006 * Fast: Only the registry is queried to retrieve printer names,
2007 * no connection to the driver is made.
2008 * Returns an array of PRINTER_INFO_5 data structures in the
2009 * lpbPrinters buffer.
2011 * If level set to 3 or 6+:
2012 * returns zero (failure!)
2014 * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
2018 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
2019 * - Only levels 2, 4 and 5 are implemented at the moment.
2020 * - 16-bit printer drivers are not enumerated.
2021 * - Returned amount of bytes used/needed does not match the real Windoze
2022 * implementation (as in this implementation, all strings are part
2023 * of the buffer, whereas Win32 keeps them somewhere else)
2024 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
2027 * - In a regular Wine installation, no registry settings for printers
2028 * exist, which makes this function return an empty list.
2030 BOOL WINAPI EnumPrintersW(
2031 DWORD dwType, /* [in] Types of print objects to enumerate */
2032 LPWSTR lpszName, /* [in] name of objects to enumerate */
2033 DWORD dwLevel, /* [in] type of printer info structure */
2034 LPBYTE lpbPrinters, /* [out] buffer which receives info */
2035 DWORD cbBuf, /* [in] max size of buffer in bytes */
2036 LPDWORD lpdwNeeded, /* [out] pointer to var: # bytes used/needed */
2037 LPDWORD lpdwReturned /* [out] number of entries returned */
2040 return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf,
2041 lpdwNeeded, lpdwReturned, TRUE);
2044 /******************************************************************
2045 * EnumPrintersA [WINSPOOL.@]
2048 BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
2049 DWORD dwLevel, LPBYTE lpbPrinters,
2050 DWORD cbBuf, LPDWORD lpdwNeeded,
2051 LPDWORD lpdwReturned)
2054 LPWSTR lpszNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpszName);
2056 ret = WINSPOOL_EnumPrinters(dwType, lpszNameW, dwLevel, lpbPrinters, cbBuf,
2057 lpdwNeeded, lpdwReturned, FALSE);
2058 HeapFree(GetProcessHeap(),0,lpszNameW);
2062 /*****************************************************************************
2063 * WINSPOOL_GetDriverInfoFromReg [internal]
2065 * Enters the information from the registry into the DRIVER_INFO struct
2068 * zero if the printer driver does not exist in the registry
2069 * (only if Level > 1) otherwise nonzero
2071 static BOOL WINSPOOL_GetDriverInfoFromReg(
2074 LPWSTR pEnvironment,
2076 LPBYTE ptr, /* DRIVER_INFO */
2077 LPBYTE pDriverStrings, /* strings buffer */
2078 DWORD cbBuf, /* size of string buffer */
2079 LPDWORD pcbNeeded, /* space needed for str. */
2080 BOOL unicode) /* type of strings */
2081 { DWORD dw, size, tmp, type;
2083 LPBYTE strPtr = pDriverStrings;
2085 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
2086 debugstr_w(DriverName), debugstr_w(pEnvironment),
2087 Level, ptr, pDriverStrings, cbBuf, unicode);
2090 *pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
2091 if (*pcbNeeded <= cbBuf)
2092 strcpyW((LPWSTR)strPtr, DriverName);
2094 *pcbNeeded = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0,
2096 if(*pcbNeeded <= cbBuf)
2097 WideCharToMultiByte(CP_ACP, 0, DriverName, -1, strPtr, *pcbNeeded,
2102 ((PDRIVER_INFO_1W) ptr)->pName = (LPWSTR) strPtr;
2106 ((PDRIVER_INFO_3W) ptr)->pName = (LPWSTR) strPtr;
2107 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
2110 if(!DriverName[0] || RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) {
2111 ERR("Can't find driver '%s' in registry\n", debugstr_w(DriverName));
2112 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
2117 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw, &size) !=
2119 WARN("Can't get Version\n");
2121 ((PDRIVER_INFO_3A) ptr)->cVersion = dw;
2124 pEnvironment = DefaultEnvironmentW;
2126 size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
2128 size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
2131 if(*pcbNeeded <= cbBuf) {
2133 strcpyW((LPWSTR)strPtr, pEnvironment);
2135 WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, strPtr, size,
2138 ((PDRIVER_INFO_3W) ptr)->pEnvironment = (LPWSTR)strPtr;
2139 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
2142 if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, 0, &size,
2145 if(*pcbNeeded <= cbBuf)
2146 WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, size, &tmp,
2149 ((PDRIVER_INFO_3W) ptr)->pDriverPath = (LPWSTR)strPtr;
2150 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
2153 if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, 0, &size,
2156 if(*pcbNeeded <= cbBuf)
2157 WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, size,
2160 ((PDRIVER_INFO_3W) ptr)->pDataFile = (LPWSTR)strPtr;
2161 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2164 if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
2165 0, &size, unicode)) {
2167 if(*pcbNeeded <= cbBuf)
2168 WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
2169 size, &tmp, unicode);
2171 ((PDRIVER_INFO_3W) ptr)->pConfigFile = (LPWSTR)strPtr;
2172 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2176 RegCloseKey(hkeyDriver);
2177 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
2181 if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, 0, &size,
2184 if(*pcbNeeded <= cbBuf)
2185 WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr,
2186 size, &tmp, unicode);
2188 ((PDRIVER_INFO_3W) ptr)->pHelpFile = (LPWSTR)strPtr;
2189 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2192 if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, 0,
2195 if(*pcbNeeded <= cbBuf)
2196 WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr,
2197 size, &tmp, unicode);
2199 ((PDRIVER_INFO_3W) ptr)->pDependentFiles = (LPWSTR)strPtr;
2200 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2203 if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size,
2206 if(*pcbNeeded <= cbBuf)
2207 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
2208 size, &tmp, unicode);
2210 ((PDRIVER_INFO_3W) ptr)->pMonitorName = (LPWSTR)strPtr;
2211 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2214 if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size,
2217 if(*pcbNeeded <= cbBuf)
2218 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
2219 size, &tmp, unicode);
2221 ((PDRIVER_INFO_3W) ptr)->pDefaultDataType = (LPWSTR)strPtr;
2222 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2225 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
2226 RegCloseKey(hkeyDriver);
2230 /*****************************************************************************
2231 * WINSPOOL_GetPrinterDriver
2233 static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
2234 DWORD Level, LPBYTE pDriverInfo,
2235 DWORD cbBuf, LPDWORD pcbNeeded,
2239 WCHAR DriverName[100];
2240 DWORD ret, type, size, needed = 0;
2242 HKEY hkeyPrinter, hkeyPrinters, hkeyDrivers;
2244 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
2245 Level,pDriverInfo,cbBuf, pcbNeeded);
2247 ZeroMemory(pDriverInfo, cbBuf);
2249 if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE;
2251 if(Level < 1 || Level > 3) {
2252 SetLastError(ERROR_INVALID_LEVEL);
2255 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
2257 ERR("Can't create Printers key\n");
2260 if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter)
2262 ERR("Can't find opened printer %s in registry\n", debugstr_w(name));
2263 RegCloseKey(hkeyPrinters);
2264 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
2267 size = sizeof(DriverName);
2269 ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type,
2270 (LPBYTE)DriverName, &size);
2271 RegCloseKey(hkeyPrinter);
2272 RegCloseKey(hkeyPrinters);
2273 if(ret != ERROR_SUCCESS) {
2274 ERR("Can't get DriverName for printer %s\n", debugstr_w(name));
2278 hkeyDrivers = WINSPOOL_OpenDriverReg( pEnvironment, TRUE);
2280 ERR("Can't create Drivers key\n");
2286 size = sizeof(DRIVER_INFO_1W);
2289 size = sizeof(DRIVER_INFO_2W);
2292 size = sizeof(DRIVER_INFO_3W);
2295 ERR("Invalid level\n");
2300 ptr = pDriverInfo + size;
2302 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName,
2303 pEnvironment, Level, pDriverInfo,
2304 (cbBuf < size) ? NULL : ptr,
2305 (cbBuf < size) ? 0 : cbBuf - size,
2306 &needed, unicode)) {
2307 RegCloseKey(hkeyDrivers);
2311 RegCloseKey(hkeyDrivers);
2313 if(pcbNeeded) *pcbNeeded = size + needed;
2314 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
2315 if(cbBuf >= needed) return TRUE;
2316 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2320 /*****************************************************************************
2321 * GetPrinterDriverA [WINSPOOL.@]
2323 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
2324 DWORD Level, LPBYTE pDriverInfo,
2325 DWORD cbBuf, LPDWORD pcbNeeded)
2328 LPWSTR pEnvW = HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment);
2329 ret = WINSPOOL_GetPrinterDriver(hPrinter, pEnvW, Level, pDriverInfo,
2330 cbBuf, pcbNeeded, FALSE);
2331 HeapFree(GetProcessHeap(),0,pEnvW);
2334 /*****************************************************************************
2335 * GetPrinterDriverW [WINSPOOL.@]
2337 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
2338 DWORD Level, LPBYTE pDriverInfo,
2339 DWORD cbBuf, LPDWORD pcbNeeded)
2341 return WINSPOOL_GetPrinterDriver(hPrinter, pEnvironment, Level,
2342 pDriverInfo, cbBuf, pcbNeeded, TRUE);
2345 /*****************************************************************************
2346 * GetPrinterDriverDirectoryA [WINSPOOL.@]
2348 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
2349 DWORD Level, LPBYTE pDriverDirectory,
2350 DWORD cbBuf, LPDWORD pcbNeeded)
2354 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
2355 pDriverDirectory, cbBuf, pcbNeeded);
2357 FIXME("pName = `%s' - unsupported\n", pName);
2358 SetLastError(ERROR_INVALID_PARAMETER);
2361 if(pEnvironment != NULL) {
2362 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
2363 SetLastError(ERROR_INVALID_ENVIRONMENT);
2366 if(Level != 1) /* win95 ignores this so we just carry on */
2367 WARN("Level = %ld - assuming 1\n", Level);
2369 /* FIXME should read from registry */
2370 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
2373 *pcbNeeded = needed;
2374 if(needed > cbBuf) {
2375 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2382 /*****************************************************************************
2383 * GetPrinterDriverDirectoryW [WINSPOOL.@]
2385 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
2386 DWORD Level, LPBYTE pDriverDirectory,
2387 DWORD cbBuf, LPDWORD pcbNeeded)
2389 LPSTR pNameA = NULL, pEnvironmentA = NULL;
2393 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
2395 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
2396 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
2397 pDriverDirectory, cbBuf, pcbNeeded );
2399 HeapFree( GetProcessHeap(), 0, pNameA );
2401 HeapFree( GetProcessHeap(), 0, pEnvironmentA );
2406 /*****************************************************************************
2407 * AddPrinterDriverA [WINSPOOL.@]
2409 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
2412 HKEY hkeyDrivers, hkeyName;
2414 TRACE("(%s,%ld,%p)\n",debugstr_a(pName),level,pDriverInfo);
2416 if(level != 2 && level != 3) {
2417 SetLastError(ERROR_INVALID_LEVEL);
2421 FIXME("pName= %s - unsupported\n", debugstr_a(pName));
2422 SetLastError(ERROR_INVALID_PARAMETER);
2426 WARN("pDriverInfo == NULL\n");
2427 SetLastError(ERROR_INVALID_PARAMETER);
2432 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
2434 memset(&di3, 0, sizeof(di3));
2435 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
2438 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
2440 SetLastError(ERROR_INVALID_PARAMETER);
2443 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
2444 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
2445 if(!di3.pHelpFile) di3.pHelpFile = "";
2446 if(!di3.pMonitorName) di3.pMonitorName = "";
2448 hkeyDrivers = WINSPOOL_OpenDriverReg(di3.pEnvironment, FALSE);
2451 ERR("Can't create Drivers key\n");
2455 if(level == 2) { /* apparently can't overwrite with level2 */
2456 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
2457 RegCloseKey(hkeyName);
2458 RegCloseKey(hkeyDrivers);
2459 WARN("Trying to create existing printer driver %s\n", debugstr_a(di3.pName));
2460 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
2464 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
2465 RegCloseKey(hkeyDrivers);
2466 ERR("Can't create Name key\n");
2469 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
2471 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
2472 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
2473 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
2475 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
2476 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
2477 di3.pDependentFiles, 0);
2478 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
2479 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
2480 RegCloseKey(hkeyName);
2481 RegCloseKey(hkeyDrivers);
2485 /*****************************************************************************
2486 * AddPrinterDriverW [WINSPOOL.@]
2488 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
2491 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
2497 /*****************************************************************************
2498 * PrinterProperties [WINSPOOL.@]
2500 * Displays a dialog to set the properties of the printer.
2503 * nonzero on success or zero on failure
2506 * implemented as stub only
2508 BOOL WINAPI PrinterProperties(HWND hWnd, /* [in] handle to parent window */
2509 HANDLE hPrinter /* [in] handle to printer object */
2511 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
2512 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2516 /*****************************************************************************
2517 * EnumJobsA [WINSPOOL.@]
2520 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2521 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2525 if(pcbNeeded) *pcbNeeded = 0;
2526 if(pcReturned) *pcReturned = 0;
2531 /*****************************************************************************
2532 * EnumJobsW [WINSPOOL.@]
2535 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2536 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2540 if(pcbNeeded) *pcbNeeded = 0;
2541 if(pcReturned) *pcReturned = 0;
2545 /*****************************************************************************
2546 * WINSPOOL_EnumPrinterDrivers [internal]
2548 * Delivers information about all printer drivers installed on the
2549 * localhost or a given server
2552 * nonzero on success or zero on failure. If the buffer for the returned
2553 * information is too small the function will return an error
2556 * - only implemented for localhost, foreign hosts will return an error
2558 static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPWSTR pEnvironment,
2559 DWORD Level, LPBYTE pDriverInfo,
2560 DWORD cbBuf, LPDWORD pcbNeeded,
2561 LPDWORD pcReturned, BOOL unicode)
2564 DWORD i, needed, number = 0, size = 0;
2565 WCHAR DriverNameW[255];
2568 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2569 debugstr_w(pName), debugstr_w(pEnvironment),
2570 Level, pDriverInfo, cbBuf, unicode);
2572 /* check for local drivers */
2574 ERR("remote drivers unsupported! Current remote host is %s\n",
2579 /* check input parameter */
2580 if((Level < 1) || (Level > 3)) {
2581 ERR("unsupported level %ld \n", Level);
2585 /* initialize return values */
2587 memset( pDriverInfo, 0, cbBuf);
2591 hkeyDrivers = WINSPOOL_OpenDriverReg(pEnvironment, TRUE);
2593 ERR("Can't open Drivers key\n");
2597 if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, &number, NULL, NULL,
2598 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
2599 RegCloseKey(hkeyDrivers);
2600 ERR("Can't query Drivers key\n");
2603 TRACE("Found %ld Drivers\n", number);
2605 /* get size of single struct
2606 * unicode and ascii structure have the same size
2610 size = sizeof(DRIVER_INFO_1A);
2613 size = sizeof(DRIVER_INFO_2A);
2616 size = sizeof(DRIVER_INFO_3A);
2620 /* calculate required buffer size */
2621 *pcbNeeded = size * number;
2623 for( i = 0, ptr = (pDriverInfo && (cbBuf >= size)) ? pDriverInfo : NULL ;
2625 i++, ptr = (ptr && (cbBuf >= size * i)) ? ptr + size : NULL) {
2626 if(RegEnumKeyW(hkeyDrivers, i, DriverNameW, sizeof(DriverNameW))
2628 ERR("Can't enum key number %ld\n", i);
2629 RegCloseKey(hkeyDrivers);
2632 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW,
2633 pEnvironment, Level, ptr,
2634 (cbBuf < *pcbNeeded) ? NULL : pDriverInfo + *pcbNeeded,
2635 (cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded,
2636 &needed, unicode)) {
2637 RegCloseKey(hkeyDrivers);
2640 (*pcbNeeded) += needed;
2643 RegCloseKey(hkeyDrivers);
2645 if(cbBuf < *pcbNeeded){
2646 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2653 /*****************************************************************************
2654 * EnumPrinterDriversW [WINSPOOL.@]
2656 * see function EnumPrinterDrivers for RETURNS, BUGS
2658 BOOL WINAPI EnumPrinterDriversW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
2659 LPBYTE pDriverInfo, DWORD cbBuf,
2660 LPDWORD pcbNeeded, LPDWORD pcReturned)
2662 return WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo,
2663 cbBuf, pcbNeeded, pcReturned, TRUE);
2666 /*****************************************************************************
2667 * EnumPrinterDriversA [WINSPOOL.@]
2669 * see function EnumPrinterDrivers for RETURNS, BUGS
2671 BOOL WINAPI EnumPrinterDriversA(LPSTR pName, LPSTR pEnvironment, DWORD Level,
2672 LPBYTE pDriverInfo, DWORD cbBuf,
2673 LPDWORD pcbNeeded, LPDWORD pcReturned)
2675 WCHAR *pNameW = NULL, *pEnvironmentW = NULL;
2678 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
2680 pEnvironmentW = HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment);
2682 ret = WINSPOOL_EnumPrinterDrivers(pNameW, pEnvironmentW, Level, pDriverInfo,
2683 cbBuf, pcbNeeded, pcReturned, FALSE);
2685 HeapFree(GetProcessHeap(), 0, pNameW);
2687 HeapFree(GetProcessHeap(), 0, pEnvironmentW);
2693 /******************************************************************************
2694 * EnumPortsA (WINSPOOL.@)
2696 BOOL WINAPI EnumPortsA(LPSTR name,DWORD level,LPBYTE ports,DWORD bufsize,
2697 LPDWORD bufneeded,LPDWORD bufreturned)
2699 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name,level,ports,bufsize,bufneeded,bufreturned);
2703 /******************************************************************************
2704 * GetDefaultPrinterA (WINSPOOL.@)
2706 * Based on PRINTDLG_GetDefaultPrinterName in dlls/commdlg/printdlg.c
2708 BOOL WINAPI GetDefaultPrinterA(LPSTR name, LPDWORD namesize)
2714 SetLastError (ERROR_INSUFFICIENT_BUFFER);
2718 if (!GetProfileStringA ("windows", "device", "", name, *namesize))
2720 SetLastError (ERROR_FILE_NOT_FOUND);
2724 if ((ptr = strchr (name, ',')) == NULL)
2726 SetLastError (ERROR_FILE_NOT_FOUND);
2731 *namesize = strlen (name) + 1;
2736 /******************************************************************************
2737 * GetDefaultPrinterW (WINSPOOL.@)
2739 BOOL WINAPI GetDefaultPrinterW(LPWSTR name, LPDWORD namesize)
2746 SetLastError (ERROR_INSUFFICIENT_BUFFER);
2750 buf = HeapAlloc (GetProcessHeap (), 0, *namesize);
2751 ret = GetDefaultPrinterA (buf, namesize);
2754 DWORD len = MultiByteToWideChar (CP_ACP, 0, buf, -1, name, *namesize);
2757 SetLastError (ERROR_INSUFFICIENT_BUFFER);
2760 else *namesize = len;
2763 HeapFree (GetProcessHeap (), 0, buf);
2768 /******************************************************************************
2769 * SetPrinterDataExA (WINSPOOL.@)
2771 DWORD WINAPI SetPrinterDataExA(HANDLE hPrinter, LPSTR pKeyName,
2772 LPSTR pValueName, DWORD Type,
2773 LPBYTE pData, DWORD cbData)
2775 HKEY hkeyPrinter, hkeySubkey;
2778 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter, debugstr_a(pKeyName),
2779 debugstr_a(pValueName), Type, pData, cbData);
2781 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2785 if((ret = RegCreateKeyA(hkeyPrinter, pKeyName, &hkeySubkey))
2787 ERR("Can't create subkey %s\n", debugstr_a(pKeyName));
2788 RegCloseKey(hkeyPrinter);
2791 ret = RegSetValueExA(hkeySubkey, pValueName, 0, Type, pData, cbData);
2792 RegCloseKey(hkeySubkey);
2793 RegCloseKey(hkeyPrinter);
2797 /******************************************************************************
2798 * SetPrinterDataExW (WINSPOOL.@)
2800 DWORD WINAPI SetPrinterDataExW(HANDLE hPrinter, LPWSTR pKeyName,
2801 LPWSTR pValueName, DWORD Type,
2802 LPBYTE pData, DWORD cbData)
2804 HKEY hkeyPrinter, hkeySubkey;
2807 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter, debugstr_w(pKeyName),
2808 debugstr_w(pValueName), Type, pData, cbData);
2810 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2814 if((ret = RegCreateKeyW(hkeyPrinter, pKeyName, &hkeySubkey))
2816 ERR("Can't create subkey %s\n", debugstr_w(pKeyName));
2817 RegCloseKey(hkeyPrinter);
2820 ret = RegSetValueExW(hkeySubkey, pValueName, 0, Type, pData, cbData);
2821 RegCloseKey(hkeySubkey);
2822 RegCloseKey(hkeyPrinter);
2826 /******************************************************************************
2827 * SetPrinterDataA (WINSPOOL.@)
2829 DWORD WINAPI SetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, DWORD Type,
2830 LPBYTE pData, DWORD cbData)
2832 return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type,
2836 /******************************************************************************
2837 * SetPrinterDataW (WINSPOOL.@)
2839 DWORD WINAPI SetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, DWORD Type,
2840 LPBYTE pData, DWORD cbData)
2842 return SetPrinterDataExW(hPrinter, PrinterDriverDataW, pValueName, Type,
2846 /******************************************************************************
2847 * GetPrinterDataExA (WINSPOOL.@)
2849 DWORD WINAPI GetPrinterDataExA(HANDLE hPrinter, LPSTR pKeyName,
2850 LPSTR pValueName, LPDWORD pType,
2851 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2853 HKEY hkeyPrinter, hkeySubkey;
2856 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter,
2857 debugstr_a(pKeyName), debugstr_a(pValueName), pType, pData, nSize,
2860 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2864 if((ret = RegOpenKeyA(hkeyPrinter, pKeyName, &hkeySubkey))
2866 WARN("Can't open subkey %s\n", debugstr_a(pKeyName));
2867 RegCloseKey(hkeyPrinter);
2871 ret = RegQueryValueExA(hkeySubkey, pValueName, 0, pType, pData, pcbNeeded);
2872 RegCloseKey(hkeySubkey);
2873 RegCloseKey(hkeyPrinter);
2877 /******************************************************************************
2878 * GetPrinterDataExW (WINSPOOL.@)
2880 DWORD WINAPI GetPrinterDataExW(HANDLE hPrinter, LPWSTR pKeyName,
2881 LPWSTR pValueName, LPDWORD pType,
2882 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2884 HKEY hkeyPrinter, hkeySubkey;
2887 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter,
2888 debugstr_w(pKeyName), debugstr_w(pValueName), pType, pData, nSize,
2891 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2895 if((ret = RegOpenKeyW(hkeyPrinter, pKeyName, &hkeySubkey))
2897 WARN("Can't open subkey %s\n", debugstr_w(pKeyName));
2898 RegCloseKey(hkeyPrinter);
2902 ret = RegQueryValueExW(hkeySubkey, pValueName, 0, pType, pData, pcbNeeded);
2903 RegCloseKey(hkeySubkey);
2904 RegCloseKey(hkeyPrinter);
2908 /******************************************************************************
2909 * GetPrinterDataA (WINSPOOL.@)
2911 DWORD WINAPI GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType,
2912 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2914 return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType,
2915 pData, nSize, pcbNeeded);
2918 /******************************************************************************
2919 * GetPrinterDataW (WINSPOOL.@)
2921 DWORD WINAPI GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType,
2922 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2924 return GetPrinterDataExW(hPrinter, PrinterDriverDataW, pValueName, pType,
2925 pData, nSize, pcbNeeded);
2928 /*******************************************************************************
2929 * EnumPrinterDataExW [WINSPOOL.@]
2931 DWORD WINAPI EnumPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName,
2932 LPBYTE pEnumValues, DWORD cbEnumValues,
2933 LPDWORD pcbEnumValues, LPDWORD pnEnumValues)
2935 HKEY hkPrinter, hkSubKey;
2936 DWORD r, ret, dwIndex, cValues, cbMaxValueNameLen,
2937 cbValueNameLen, cbMaxValueLen, cbValueLen,
2942 PPRINTER_ENUM_VALUESW ppev;
2944 TRACE ("%08x %s\n", hPrinter, debugstr_w (pKeyName));
2946 if (pKeyName == NULL || *pKeyName == 0)
2947 return ERROR_INVALID_PARAMETER;
2949 ret = WINSPOOL_GetOpenedPrinterRegKey (hPrinter, &hkPrinter);
2950 if (ret != ERROR_SUCCESS)
2952 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%08x) returned %li\n",
2957 ret = RegOpenKeyExW (hkPrinter, pKeyName, 0, KEY_READ, &hkSubKey);
2958 if (ret != ERROR_SUCCESS)
2960 r = RegCloseKey (hkPrinter);
2961 if (r != ERROR_SUCCESS)
2962 WARN ("RegCloseKey returned %li\n", r);
2963 TRACE ("RegOpenKeyExW (%08x, %s) returned %li\n", hPrinter,
2964 debugstr_w (pKeyName), ret);
2968 ret = RegCloseKey (hkPrinter);
2969 if (ret != ERROR_SUCCESS)
2971 ERR ("RegCloseKey returned %li\n", ret);
2972 r = RegCloseKey (hkSubKey);
2973 if (r != ERROR_SUCCESS)
2974 WARN ("RegCloseKey returned %li\n", r);
2978 ret = RegQueryInfoKeyW (hkSubKey, NULL, NULL, NULL, NULL, NULL, NULL,
2979 &cValues, &cbMaxValueNameLen, &cbMaxValueLen, NULL, NULL);
2980 if (ret != ERROR_SUCCESS)
2982 r = RegCloseKey (hkSubKey);
2983 if (r != ERROR_SUCCESS)
2984 WARN ("RegCloseKey returned %li\n", r);
2985 TRACE ("RegQueryInfoKeyW (%08x) returned %li\n", hkSubKey, ret);
2989 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
2990 "cbMaxValueLen = %li\n", cValues, cbMaxValueNameLen, cbMaxValueLen);
2992 if (cValues == 0) /* empty key */
2994 r = RegCloseKey (hkSubKey);
2995 if (r != ERROR_SUCCESS)
2996 WARN ("RegCloseKey returned %li\n", r);
2997 *pcbEnumValues = *pnEnumValues = 0;
2998 return ERROR_SUCCESS;
3001 ++cbMaxValueNameLen; /* allow for trailing '\0' */
3003 hHeap = GetProcessHeap ();
3004 if (hHeap == (HANDLE) NULL)
3006 ERR ("GetProcessHeap failed\n");
3007 r = RegCloseKey (hkSubKey);
3008 if (r != ERROR_SUCCESS)
3009 WARN ("RegCloseKey returned %li\n", r);
3010 return ERROR_OUTOFMEMORY;
3013 lpValueName = HeapAlloc (hHeap, 0, cbMaxValueNameLen * sizeof (WCHAR));
3014 if (lpValueName == NULL)
3016 ERR ("Failed to allocate %li bytes from process heap\n",
3017 cbMaxValueNameLen * sizeof (WCHAR));
3018 r = RegCloseKey (hkSubKey);
3019 if (r != ERROR_SUCCESS)
3020 WARN ("RegCloseKey returned %li\n", r);
3021 return ERROR_OUTOFMEMORY;
3024 lpValue = HeapAlloc (hHeap, 0, cbMaxValueLen);
3025 if (lpValue == NULL)
3027 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen);
3028 if (HeapFree (hHeap, 0, lpValueName) == 0)
3029 WARN ("HeapFree failed with code %li\n", GetLastError ());
3030 r = RegCloseKey (hkSubKey);
3031 if (r != ERROR_SUCCESS)
3032 WARN ("RegCloseKey returned %li\n", r);
3033 return ERROR_OUTOFMEMORY;
3036 TRACE ("pass 1: calculating buffer required for all names and values\n");
3038 cbBufSize = cValues * sizeof (PRINTER_ENUM_VALUESW);
3040 TRACE ("%li bytes required for %li headers\n", cbBufSize, cValues);
3042 for (dwIndex = 0; dwIndex < cValues; ++dwIndex)
3044 cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen;
3045 ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen,
3046 NULL, NULL, lpValue, &cbValueLen);
3047 if (ret != ERROR_SUCCESS)
3049 if (HeapFree (hHeap, 0, lpValue) == 0)
3050 WARN ("HeapFree failed with code %li\n", GetLastError ());
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 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex, ret);
3060 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
3061 debugstr_w (lpValueName), dwIndex,
3062 (cbValueNameLen + 1) * sizeof (WCHAR), cbValueLen);
3064 cbBufSize += (cbValueNameLen + 1) * sizeof (WCHAR);
3065 cbBufSize += cbValueLen;
3068 TRACE ("%li bytes required for all %li values\n", cbBufSize, cValues);
3070 *pcbEnumValues = cbBufSize;
3071 *pnEnumValues = cValues;
3073 if (cbEnumValues < cbBufSize) /* buffer too small */
3075 if (HeapFree (hHeap, 0, lpValue) == 0)
3076 WARN ("HeapFree failed with code %li\n", GetLastError ());
3077 if (HeapFree (hHeap, 0, lpValueName) == 0)
3078 WARN ("HeapFree failed with code %li\n", GetLastError ());
3079 r = RegCloseKey (hkSubKey);
3080 if (r != ERROR_SUCCESS)
3081 WARN ("RegCloseKey returned %li\n", r);
3082 TRACE ("%li byte buffer is not large enough\n", cbEnumValues);
3083 return ERROR_MORE_DATA;
3086 TRACE ("pass 2: copying all names and values to buffer\n");
3088 ppev = (PPRINTER_ENUM_VALUESW) pEnumValues; /* array of structs */
3089 pEnumValues += cValues * sizeof (PRINTER_ENUM_VALUESW);
3091 for (dwIndex = 0; dwIndex < cValues; ++dwIndex)
3093 cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen;
3094 ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen,
3095 NULL, &dwType, lpValue, &cbValueLen);
3096 if (ret != ERROR_SUCCESS)
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 ("RegEnumValueW (%li) returned %li\n", dwIndex, ret);
3109 cbValueNameLen = (cbValueNameLen + 1) * sizeof (WCHAR);
3110 memcpy (pEnumValues, lpValueName, cbValueNameLen);
3111 ppev[dwIndex].pValueName = (LPWSTR) pEnumValues;
3112 pEnumValues += cbValueNameLen;
3114 /* return # of *bytes* (including trailing \0), not # of chars */
3115 ppev[dwIndex].cbValueName = cbValueNameLen;
3117 ppev[dwIndex].dwType = dwType;
3119 memcpy (pEnumValues, lpValue, cbValueLen);
3120 ppev[dwIndex].pData = pEnumValues;
3121 pEnumValues += cbValueLen;
3123 ppev[dwIndex].cbData = cbValueLen;
3125 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
3126 debugstr_w (lpValueName), dwIndex, cbValueNameLen, cbValueLen);
3129 if (HeapFree (hHeap, 0, lpValue) == 0)
3131 ret = GetLastError ();
3132 ERR ("HeapFree failed with code %li\n", ret);
3133 if (HeapFree (hHeap, 0, lpValueName) == 0)
3134 WARN ("HeapFree failed with code %li\n", GetLastError ());
3135 r = RegCloseKey (hkSubKey);
3136 if (r != ERROR_SUCCESS)
3137 WARN ("RegCloseKey returned %li\n", r);
3141 if (HeapFree (hHeap, 0, lpValueName) == 0)
3143 ret = GetLastError ();
3144 ERR ("HeapFree failed with code %li\n", ret);
3145 r = RegCloseKey (hkSubKey);
3146 if (r != ERROR_SUCCESS)
3147 WARN ("RegCloseKey returned %li\n", r);
3151 ret = RegCloseKey (hkSubKey);
3152 if (ret != ERROR_SUCCESS)
3154 ERR ("RegCloseKey returned %li\n", ret);
3158 return ERROR_SUCCESS;
3161 /*******************************************************************************
3162 * EnumPrinterDataExA [WINSPOOL.@]
3164 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
3165 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
3166 * what Windows 2000 SP1 does.
3169 DWORD WINAPI EnumPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName,
3170 LPBYTE pEnumValues, DWORD cbEnumValues,
3171 LPDWORD pcbEnumValues, LPDWORD pnEnumValues)
3175 DWORD ret, dwIndex, dwBufSize;
3179 TRACE ("%08x %s\n", hPrinter, pKeyName);
3181 if (pKeyName == NULL || *pKeyName == 0)
3182 return ERROR_INVALID_PARAMETER;
3184 len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0);
3187 ret = GetLastError ();
3188 ERR ("MultiByteToWideChar failed with code %li\n", ret);
3192 hHeap = GetProcessHeap ();
3193 if (hHeap == (HANDLE) NULL)
3195 ERR ("GetProcessHeap failed\n");
3196 return ERROR_OUTOFMEMORY;
3199 pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR));
3200 if (pKeyNameW == NULL)
3202 ERR ("Failed to allocate %li bytes from process heap\n",
3203 (LONG) len * sizeof (WCHAR));
3204 return ERROR_OUTOFMEMORY;
3207 if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0)
3209 ret = GetLastError ();
3210 ERR ("MultiByteToWideChar failed with code %li\n", ret);
3211 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
3212 WARN ("HeapFree failed with code %li\n", GetLastError ());
3216 ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues,
3217 pcbEnumValues, pnEnumValues);
3218 if (ret != ERROR_SUCCESS)
3220 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
3221 WARN ("HeapFree failed with code %li\n", GetLastError ());
3222 TRACE ("EnumPrinterDataExW returned %li\n", ret);
3226 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
3228 ret = GetLastError ();
3229 ERR ("HeapFree failed with code %li\n", ret);
3233 if (*pnEnumValues == 0) /* empty key */
3234 return ERROR_SUCCESS;
3237 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
3239 PPRINTER_ENUM_VALUESW ppev =
3240 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
3242 if (dwBufSize < ppev->cbValueName)
3243 dwBufSize = ppev->cbValueName;
3245 if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ ||
3246 ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
3247 dwBufSize = ppev->cbData;
3250 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize);
3252 pBuffer = HeapAlloc (hHeap, 0, dwBufSize);
3253 if (pBuffer == NULL)
3255 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize);
3256 return ERROR_OUTOFMEMORY;
3259 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
3261 PPRINTER_ENUM_VALUESW ppev =
3262 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
3264 len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName,
3265 ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL,
3269 ret = GetLastError ();
3270 ERR ("WideCharToMultiByte failed with code %li\n", ret);
3271 if (HeapFree (hHeap, 0, pBuffer) == 0)
3272 WARN ("HeapFree failed with code %li\n", GetLastError ());
3276 memcpy (ppev->pValueName, pBuffer, len);
3278 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
3280 if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ &&
3281 ppev->dwType != REG_MULTI_SZ)
3284 len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData,
3285 ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL);
3288 ret = GetLastError ();
3289 ERR ("WideCharToMultiByte failed with code %li\n", ret);
3290 if (HeapFree (hHeap, 0, pBuffer) == 0)
3291 WARN ("HeapFree failed with code %li\n", GetLastError ());
3295 memcpy (ppev->pData, pBuffer, len);
3297 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
3298 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
3301 if (HeapFree (hHeap, 0, pBuffer) == 0)
3303 ret = GetLastError ();
3304 ERR ("HeapFree failed with code %li\n", ret);
3308 return ERROR_SUCCESS;