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
19 # include <cups/cups.h>
25 #include "wine/windef16.h"
26 #include "wine/unicode.h"
27 #include "debugtools.h"
31 DEFAULT_DEBUG_CHANNEL(winspool);
33 static LPWSTR *printer_array;
34 static int nb_printers;
36 static DWORD (WINAPI *GDI_CallDeviceCapabilities16)( LPCSTR lpszDevice, LPCSTR lpszPort,
37 WORD fwCapability, LPSTR lpszOutput,
39 static INT (WINAPI *GDI_CallExtDeviceMode16)( HWND hwnd, LPDEVMODEA lpdmOutput,
40 LPSTR lpszDevice, LPSTR lpszPort,
41 LPDEVMODEA lpdmInput, LPSTR lpszProfile,
44 static char Printers[] =
45 "System\\CurrentControlSet\\control\\Print\\Printers\\";
46 static char Drivers[] =
47 "System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
49 static WCHAR DefaultEnvironmentW[] = {'W','i','n','e',0};
51 static WCHAR Configuration_FileW[] = {'C','o','n','f','i','g','u','r','a','t',
52 'i','o','n',' ','F','i','l','e',0};
53 static WCHAR DatatypeW[] = {'D','a','t','a','t','y','p','e',0};
54 static WCHAR Data_FileW[] = {'D','a','t','a',' ','F','i','l','e',0};
55 static WCHAR Default_DevModeW[] = {'D','e','f','a','u','l','t',' ','D','e','v',
57 static WCHAR Dependent_FilesW[] = {'D','e','p','e','n','d','e','n','t',' ','F',
59 static WCHAR DescriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
60 static WCHAR DriverW[] = {'D','r','i','v','e','r',0};
61 static WCHAR Help_FileW[] = {'H','e','l','p',' ','F','i','l','e',0};
62 static WCHAR LocationW[] = {'L','o','c','a','t','i','o','n',0};
63 static WCHAR MonitorW[] = {'M','o','n','i','t','o','r',0};
64 static WCHAR NameW[] = {'N','a','m','e',0};
65 static WCHAR ParametersW[] = {'P','a','r','a','m','e','t','e','r','s',0};
66 static WCHAR PortW[] = {'P','o','r','t',0};
67 static WCHAR Print_ProcessorW[] = {'P','r','i','n','t',' ','P','r','o','c','e',
69 static WCHAR Printer_DriverW[] = {'P','r','i','n','t','e','r',' ','D','r','i',
71 static WCHAR PrinterDriverDataW[] = {'P','r','i','n','t','e','r','D','r','i',
72 'v','e','r','D','a','t','a',0};
73 static WCHAR Separator_FileW[] = {'S','e','p','a','r','a','t','o','r',' ','F',
75 static WCHAR Share_NameW[] = {'S','h','a','r','e',' ','N','a','m','e',0};
76 static WCHAR WinPrintW[] = {'W','i','n','P','r','i','n','t',0};
78 static HKEY WINSPOOL_OpenDriverReg( LPVOID pEnvironment, BOOL unicode);
79 static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
80 DWORD Level, LPBYTE pDriverInfo,
81 DWORD cbBuf, LPDWORD pcbNeeded,
84 WINSPOOL_SetDefaultPrinter(const char *devname, const char *name,BOOL force) {
87 /* If forcing, or no profile string entry for device yet, set the entry
89 * The always change entry if not WINEPS yet is discussable.
92 !GetProfileStringA("windows","device","*",qbuf,sizeof(qbuf)) ||
94 !strstr(qbuf,"WINEPS")
96 char *buf = HeapAlloc(GetProcessHeap(),0,strlen(name)+strlen(devname)+strlen(",WINEPS,LPR:")+1);
98 sprintf(buf,"%s,WINEPS,LPR:%s",devname,name);
99 WriteProfileStringA("windows","device",buf);
100 HeapFree(GetProcessHeap(),0,buf);
106 CUPS_LoadPrinters(void) {
108 int i,nrofdests,hadprinter = FALSE;
109 PRINTER_INFO_2A pinfo2a;
110 const char* def = cupsGetDefault();
112 nrofdests = cupsGetPrinters(&printers);
114 for (i=0;i<nrofdests;i++) {
115 const char *ppd = cupsGetPPD(printers[i]);
119 WARN("No ppd file for %s.\n",printers[i]);
126 if (!strcmp(def,printers[i]))
127 WINSPOOL_SetDefaultPrinter(printers[i],printers[i],FALSE);
128 memset(&pinfo2a,0,sizeof(pinfo2a));
129 pinfo2a.pPrinterName = printers[i];
130 pinfo2a.pDatatype = "RAW";
131 pinfo2a.pPrintProcessor = "WinPrint";
132 pinfo2a.pDriverName = "PS Driver";
133 pinfo2a.pComment = "WINEPS Printer using CUPS";
134 pinfo2a.pLocation = "<physical location of printer>";
135 port = HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(printers[i])+1);
136 sprintf(port,"LPR:%s",printers[i]);
137 pinfo2a.pPortName = port;
138 pinfo2a.pParameters = "<parameters?>";
139 pinfo2a.pShareName = "<share name?>";
140 pinfo2a.pSepFile = "<sep file?>";
142 devline=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port)+1);
143 sprintf(devline,"WINEPS,%s",port);
144 WriteProfileStringA("devices",printers[i],devline);
145 HeapFree(GetProcessHeap(),0,devline);
147 if (!AddPrinterA(NULL,2,(LPBYTE)&pinfo2a)) {
148 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS)
149 ERR("%s not added by AddPrinterA (%ld)\n",printers[i],GetLastError());
151 HeapFree(GetProcessHeap(),0,port);
158 PRINTCAP_ParseEntry(char *pent,BOOL isfirst) {
159 PRINTER_INFO_2A pinfo2a;
160 char *s,*name,*prettyname,*devname;
164 s = strchr(pent,':');
165 if (!s) return FALSE;
171 /* Determine whether this is a postscript printer. */
173 /* 1. Check if name or aliases contain trigger phrases like 'ps' */
174 if (strstr(name,"ps") ||
175 strstr(name,"pd") || /* postscript double page */
176 strstr(name,"postscript") ||
177 strstr(name,"PostScript")
179 TRACE("%s has 'ps' style name, assuming postscript.\n",name);
182 /* 2. Check if this is a remote printer. These usually are postscript
185 if (strstr(pent,":rm")) {
187 TRACE("%s is remote, assuming postscript.\n",name);
189 /* 3. Check if we have an input filter program. If we have one, it
190 * most likely is one capable of converting postscript.
191 * (Could probably check for occurrence of 'gs' or 'ghostscript'
192 * in the if file itself.)
194 if (strstr(pent,":if=/")) {
196 TRACE("%s has inputfilter program, assuming postscript.\n",name);
199 /* If it is not a postscript printer, we cannot use it. */
204 /* Get longest name, usually the one at the right for later display. */
205 while ((s=strchr(prettyname,'|'))) prettyname = s+1;
206 s=strchr(name,'|');if (s) *s='\0';
208 /* prettyname must fit into the dmDeviceName member of DEVMODE struct,
209 * if it is too long, we use it as comment below. */
210 devname = prettyname;
211 if (strlen(devname)>=CCHDEVICENAME-1)
213 if (strlen(devname)>=CCHDEVICENAME-1)
216 if (isfirst) /* set first entry as default */
217 WINSPOOL_SetDefaultPrinter(devname,name,FALSE);
219 memset(&pinfo2a,0,sizeof(pinfo2a));
220 pinfo2a.pPrinterName = devname;
221 pinfo2a.pDatatype = "RAW";
222 pinfo2a.pPrintProcessor = "WinPrint";
223 pinfo2a.pDriverName = "PS Driver";
224 pinfo2a.pComment = "WINEPS Printer using LPR";
225 pinfo2a.pLocation = prettyname;
226 port = HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(name)+1);
227 sprintf(port,"LPR:%s",name);
228 pinfo2a.pPortName = port;
229 pinfo2a.pParameters = "<parameters?>";
230 pinfo2a.pShareName = "<share name?>";
231 pinfo2a.pSepFile = "<sep file?>";
233 devline=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port)+1);
234 sprintf(devline,"WINEPS,%s",port);
235 WriteProfileStringA("devices",devname,devline);
236 HeapFree(GetProcessHeap(),0,devline);
238 if (!AddPrinterA(NULL,2,(LPBYTE)&pinfo2a)) {
239 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS)
240 ERR("%s not added by AddPrinterA (%ld)\n",name,GetLastError());
242 HeapFree(GetProcessHeap(),0,port);
247 PRINTCAP_LoadPrinters(void) {
248 BOOL hadprinter = FALSE, isfirst = TRUE;
252 f = fopen("/etc/printcap","r");
256 while (fgets(buf,sizeof(buf),f)) {
260 s=strchr(buf,'\n'); if (s) *s='\0';
261 if ((buf[0]=='#') || (buf[0]=='\0'))
265 pent=HeapReAlloc(GetProcessHeap(),0,pent,strlen(pent)+strlen(buf)+2);
268 pent=HeapAlloc(GetProcessHeap(),0,strlen(buf)+1);
272 if (strlen(pent) && (pent[strlen(pent)-1] == '\\'))
273 pent[strlen(pent)-1] = '\0';
276 } while (fgets(buf,sizeof(buf),f));
278 hadprinter |= PRINTCAP_ParseEntry(pent,isfirst);
280 if (pent) HeapFree(GetProcessHeap(),0,pent);
288 static inline DWORD set_reg_szW(HKEY hkey, WCHAR *keyname, WCHAR *value)
290 return RegSetValueExW(hkey, keyname, 0, REG_SZ, (LPBYTE)value,
291 lstrlenW(value) * sizeof(WCHAR));
295 WINSPOOL_LoadSystemPrinters() {
298 di3a.cVersion = 0x400;
299 di3a.pName = "PS Driver";
300 di3a.pEnvironment = NULL; /* NULL means auto */
301 di3a.pDriverPath = "wineps.drv";
302 di3a.pDataFile = "<datafile?>";
303 di3a.pConfigFile = "wineps.drv";
304 di3a.pHelpFile = "<helpfile?>";
305 di3a.pDependentFiles = "<dependend files?>";
306 di3a.pMonitorName = "<monitor name?>";
307 di3a.pDefaultDataType = "RAW";
309 if (!AddPrinterDriverA(NULL,3,(LPBYTE)&di3a)) {
310 ERR("Failed adding PS Driver (%ld)\n",GetLastError());
314 /* If we have any CUPS based printers, skip looking for printcap printers */
315 if (CUPS_LoadPrinters())
319 /* Check for [ppd] section in config file before parsing /etc/printcap */
321 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\ppd",
322 &hkPPD) == ERROR_SUCCESS)
325 PRINTCAP_LoadPrinters();
330 /******************************************************************
331 * WINSPOOL_GetOpenedPrinterEntry
332 * Get the first place empty in the opened printer table
334 static HANDLE WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name )
338 for (i = 0; i < nb_printers; i++) if (!printer_array[i]) break;
340 if (i >= nb_printers)
342 LPWSTR *new_array = HeapReAlloc( GetProcessHeap(), 0, printer_array,
343 (nb_printers + 16) * sizeof(*new_array) );
344 if (!new_array) return 0;
345 printer_array = new_array;
349 if ((printer_array[i] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name)+1)*sizeof(WCHAR) )))
351 strcpyW( printer_array[i], name );
352 return (HANDLE)(i + 1);
357 /******************************************************************
358 * WINSPOOL_GetOpenedPrinter
359 * Get the pointer to the opened printer referred by the handle
361 static LPCWSTR WINSPOOL_GetOpenedPrinter(HANDLE printerHandle)
363 int idx = (int)printerHandle;
364 if ((idx <= 0) || (idx > nb_printers))
366 SetLastError(ERROR_INVALID_HANDLE);
369 return printer_array[idx - 1];
372 /******************************************************************
373 * WINSPOOL_GetOpenedPrinterRegKey
376 static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey)
378 LPCWSTR name = WINSPOOL_GetOpenedPrinter(hPrinter);
382 if(!name) return ERROR_INVALID_HANDLE;
384 if((ret = RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters)) !=
388 if(RegOpenKeyW(hkeyPrinters, name, phkey) != ERROR_SUCCESS)
390 ERR("Can't find opened printer %s in registry\n",
392 RegCloseKey(hkeyPrinters);
393 return ERROR_INVALID_PRINTER_NAME; /* ? */
395 RegCloseKey(hkeyPrinters);
396 return ERROR_SUCCESS;
399 /***********************************************************
402 static LPDEVMODEW DEVMODEcpyAtoW(DEVMODEW *dmW, const DEVMODEA *dmA)
405 ptrdiff_t off_formname = (char *)dmA->dmFormName - (char *)dmA;
408 Formname = (dmA->dmSize > off_formname);
409 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
410 MultiByteToWideChar(CP_ACP, 0, dmA->dmDeviceName, -1, dmW->dmDeviceName,
413 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
414 dmA->dmSize - CCHDEVICENAME);
416 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
417 off_formname - CCHDEVICENAME);
418 MultiByteToWideChar(CP_ACP, 0, dmA->dmFormName, -1, dmW->dmFormName,
420 memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA->dmSize -
421 (off_formname + CCHFORMNAME));
424 memcpy((char *)dmW + dmW->dmSize, (char *)dmA + dmA->dmSize,
429 /***********************************************************
431 * Creates a unicode copy of supplied devmode on heap
433 static LPDEVMODEW DEVMODEdupAtoW(HANDLE heap, const DEVMODEA *dmA)
438 ptrdiff_t off_formname;
441 if(!dmA) return NULL;
443 off_formname = (char *)dmA->dmFormName - (char *)dmA;
444 Formname = (dmA->dmSize > off_formname);
445 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
446 dmW = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmA->dmDriverExtra);
447 return DEVMODEcpyAtoW(dmW, dmA);
450 /***********************************************************
452 * Creates an ascii copy of supplied devmode on heap
454 static LPDEVMODEA DEVMODEdupWtoA(HANDLE heap, const DEVMODEW *dmW)
459 ptrdiff_t off_formname = (char *)dmW->dmFormName - (char *)dmW;
461 if(!dmW) return NULL;
462 Formname = (dmW->dmSize > off_formname);
463 size = dmW->dmSize - CCHDEVICENAME - (Formname ? CCHFORMNAME : 0);
464 dmA = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmW->dmDriverExtra);
465 WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, dmA->dmDeviceName,
466 CCHDEVICENAME, NULL, NULL);
468 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
469 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR));
471 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
472 off_formname - CCHDEVICENAME * sizeof(WCHAR));
473 WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, dmA->dmFormName,
474 CCHFORMNAME, NULL, NULL);
475 memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize -
476 (off_formname + CCHFORMNAME * sizeof(WCHAR)));
479 memcpy((char *)dmA + dmA->dmSize, (char *)dmW + dmW->dmSize,
484 /***********************************************************
486 * Creates a unicode copy of PRINTER_INFO_2A on heap
488 static LPPRINTER_INFO_2W PRINTER_INFO_2AtoW(HANDLE heap, LPPRINTER_INFO_2A piA)
490 LPPRINTER_INFO_2W piW;
491 if(!piA) return NULL;
492 piW = HeapAlloc(heap, 0, sizeof(*piW));
493 memcpy(piW, piA, sizeof(*piW)); /* copy everything first */
494 piW->pServerName = HEAP_strdupAtoW(heap, 0, piA->pServerName);
495 piW->pPrinterName = HEAP_strdupAtoW(heap, 0, piA->pPrinterName);
496 piW->pShareName = HEAP_strdupAtoW(heap, 0, piA->pShareName);
497 piW->pPortName = HEAP_strdupAtoW(heap, 0, piA->pPortName);
498 piW->pDriverName = HEAP_strdupAtoW(heap, 0, piA->pDriverName);
499 piW->pComment = HEAP_strdupAtoW(heap, 0, piA->pComment);
500 piW->pLocation = HEAP_strdupAtoW(heap, 0, piA->pLocation);
501 piW->pDevMode = DEVMODEdupAtoW(heap, piA->pDevMode);
502 piW->pSepFile = HEAP_strdupAtoW(heap, 0, piA->pSepFile);
503 piW->pPrintProcessor = HEAP_strdupAtoW(heap, 0, piA->pPrintProcessor);
504 piW->pDatatype = HEAP_strdupAtoW(heap, 0, piA->pDatatype);
505 piW->pParameters = HEAP_strdupAtoW(heap, 0, piA->pParameters);
509 /***********************************************************
510 * FREE_PRINTER_INFO_2W
511 * Free PRINTER_INFO_2W and all strings
513 static void FREE_PRINTER_INFO_2W(HANDLE heap, LPPRINTER_INFO_2W piW)
517 HeapFree(heap,0,piW->pServerName);
518 HeapFree(heap,0,piW->pPrinterName);
519 HeapFree(heap,0,piW->pShareName);
520 HeapFree(heap,0,piW->pPortName);
521 HeapFree(heap,0,piW->pDriverName);
522 HeapFree(heap,0,piW->pComment);
523 HeapFree(heap,0,piW->pLocation);
524 HeapFree(heap,0,piW->pDevMode);
525 HeapFree(heap,0,piW->pSepFile);
526 HeapFree(heap,0,piW->pPrintProcessor);
527 HeapFree(heap,0,piW->pDatatype);
528 HeapFree(heap,0,piW->pParameters);
529 HeapFree(heap,0,piW);
533 /******************************************************************
534 * DeviceCapabilities [WINSPOOL.@]
535 * DeviceCapabilitiesA [WINSPOOL.@]
538 INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap,
539 LPSTR pOutput, LPDEVMODEA lpdm)
543 if (!GDI_CallDeviceCapabilities16)
545 GDI_CallDeviceCapabilities16 = (void*)GetProcAddress( GetModuleHandleA("gdi32"),
547 if (!GDI_CallDeviceCapabilities16) return -1;
549 ret = GDI_CallDeviceCapabilities16(pDevice, pPort, cap, pOutput, lpdm);
551 /* If DC_PAPERSIZE map POINT16s to POINTs */
552 if(ret != -1 && cap == DC_PAPERSIZE && pOutput) {
553 POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) );
554 POINT *pt = (POINT *)pOutput;
556 memcpy(tmp, pOutput, ret * sizeof(POINT16));
557 for(i = 0; i < ret; i++, pt++)
562 HeapFree( GetProcessHeap(), 0, tmp );
568 /*****************************************************************************
569 * DeviceCapabilitiesW [WINSPOOL.@]
571 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
574 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
575 WORD fwCapability, LPWSTR pOutput,
576 const DEVMODEW *pDevMode)
578 LPDEVMODEA dmA = DEVMODEdupWtoA(GetProcessHeap(), pDevMode);
579 LPSTR pDeviceA = HEAP_strdupWtoA(GetProcessHeap(),0,pDevice);
580 LPSTR pPortA = HEAP_strdupWtoA(GetProcessHeap(),0,pPort);
583 if(pOutput && (fwCapability == DC_BINNAMES ||
584 fwCapability == DC_FILEDEPENDENCIES ||
585 fwCapability == DC_PAPERNAMES)) {
586 /* These need A -> W translation */
589 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, NULL,
593 switch(fwCapability) {
598 case DC_FILEDEPENDENCIES:
602 pOutputA = HeapAlloc(GetProcessHeap(), 0, size * ret);
603 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, pOutputA,
605 for(i = 0; i < ret; i++)
606 MultiByteToWideChar(CP_ACP, 0, pOutputA + (i * size), -1,
607 pOutput + (i * size), size);
608 HeapFree(GetProcessHeap(), 0, pOutputA);
610 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability,
611 (LPSTR)pOutput, dmA);
613 HeapFree(GetProcessHeap(),0,pPortA);
614 HeapFree(GetProcessHeap(),0,pDeviceA);
615 HeapFree(GetProcessHeap(),0,dmA);
619 /******************************************************************
620 * DocumentPropertiesA [WINSPOOL.@]
623 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
624 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
625 LPDEVMODEA pDevModeInput,DWORD fMode )
627 LPSTR lpName = pDeviceName;
630 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
631 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
635 LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
637 ERR("no name from hPrinter?\n");
640 lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
643 if (!GDI_CallExtDeviceMode16)
645 GDI_CallExtDeviceMode16 = (void*)GetProcAddress( GetModuleHandleA("gdi32"),
647 if (!GDI_CallExtDeviceMode16) {
648 ERR("No CallExtDeviceMode16?\n");
652 ret = GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
653 pDevModeInput, NULL, fMode);
656 HeapFree(GetProcessHeap(),0,lpName);
661 /*****************************************************************************
662 * DocumentPropertiesW (WINSPOOL.@)
664 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
666 LPDEVMODEW pDevModeOutput,
667 LPDEVMODEW pDevModeInput, DWORD fMode)
670 LPSTR pDeviceNameA = HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName);
671 LPDEVMODEA pDevModeInputA = DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput);
672 LPDEVMODEA pDevModeOutputA = NULL;
675 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
676 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
679 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, NULL, NULL, 0);
680 if(ret < 0) return ret;
681 pDevModeOutputA = HeapAlloc(GetProcessHeap(), 0, ret);
683 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, pDevModeOutputA,
684 pDevModeInputA, fMode);
686 DEVMODEcpyAtoW(pDevModeOutput, pDevModeOutputA);
687 HeapFree(GetProcessHeap(),0,pDevModeOutputA);
689 if(fMode == 0 && ret > 0)
690 ret += (CCHDEVICENAME + CCHFORMNAME);
691 HeapFree(GetProcessHeap(),0,pDevModeInputA);
692 HeapFree(GetProcessHeap(),0,pDeviceNameA);
696 /******************************************************************
697 * OpenPrinterA [WINSPOOL.@]
700 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
701 LPPRINTER_DEFAULTSA pDefault)
703 LPWSTR lpPrinterNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName);
704 PRINTER_DEFAULTSW DefaultW, *pDefaultW = NULL;
708 DefaultW.pDatatype = HEAP_strdupAtoW(GetProcessHeap(), 0,
709 pDefault->pDatatype);
710 DefaultW.pDevMode = DEVMODEdupAtoW(GetProcessHeap(),
712 DefaultW.DesiredAccess = pDefault->DesiredAccess;
713 pDefaultW = &DefaultW;
715 ret = OpenPrinterW(lpPrinterNameW, phPrinter, pDefaultW);
717 HeapFree(GetProcessHeap(), 0, DefaultW.pDatatype);
718 HeapFree(GetProcessHeap(), 0, DefaultW.pDevMode);
720 HeapFree(GetProcessHeap(), 0, lpPrinterNameW);
724 /******************************************************************
725 * OpenPrinterW [WINSPOOL.@]
728 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
729 LPPRINTER_DEFAULTSW pDefault)
731 HKEY hkeyPrinters, hkeyPrinter;
733 if (!lpPrinterName) {
734 FIXME("(printerName: NULL, pDefault %p Ret: False\n", pDefault);
735 SetLastError(ERROR_INVALID_PARAMETER);
739 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName),
742 /* Check Printer exists */
743 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
745 ERR("Can't create Printers key\n");
746 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
750 if(lpPrinterName[0] == '\0' || /* explicitly exclude "" */
751 RegOpenKeyW(hkeyPrinters, lpPrinterName, &hkeyPrinter)
753 TRACE("Can't find printer %s in registry\n",
754 debugstr_w(lpPrinterName));
755 RegCloseKey(hkeyPrinters);
756 SetLastError(ERROR_INVALID_PRINTER_NAME);
759 RegCloseKey(hkeyPrinter);
760 RegCloseKey(hkeyPrinters);
762 if(!phPrinter) /* This seems to be what win95 does anyway */
765 /* Get the unique handle of the printer*/
766 *phPrinter = WINSPOOL_GetOpenedPrinterEntry( lpPrinterName );
768 if (pDefault != NULL)
769 FIXME("Not handling pDefault\n");
774 /******************************************************************
775 * AddMonitorA [WINSPOOL.@]
778 BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors)
780 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
781 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
785 /******************************************************************
786 * DeletePrinterDriverA [WINSPOOL.@]
790 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
792 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
793 debugstr_a(pDriverName));
794 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
799 /******************************************************************
800 * DeleteMonitorA [WINSPOOL.@]
804 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
806 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
807 debugstr_a(pMonitorName));
808 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
813 /******************************************************************
814 * DeletePortA [WINSPOOL.@]
818 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
820 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
821 debugstr_a(pPortName));
822 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
826 /******************************************************************************
827 * SetPrinterW [WINSPOOL.@]
837 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
841 /******************************************************************************
842 * WritePrinter [WINSPOOL.@]
852 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
856 /*****************************************************************************
857 * AddFormA [WINSPOOL.@]
859 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
861 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
865 /*****************************************************************************
866 * AddFormW [WINSPOOL.@]
868 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
870 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
874 /*****************************************************************************
875 * AddJobA [WINSPOOL.@]
877 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
878 DWORD cbBuf, LPDWORD pcbNeeded)
880 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
885 /*****************************************************************************
886 * AddJobW [WINSPOOL.@]
888 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
891 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
896 /*****************************************************************************
897 * WINSPOOL_OpenDriverReg [internal]
899 * opens the registry for the printer drivers depending on the given input
900 * variable pEnvironment
903 * the opened hkey on success
906 static HKEY WINSPOOL_OpenDriverReg( LPVOID pEnvironment, BOOL unicode)
908 LPSTR lpKey, p = NULL;
911 (unicode) ? debugstr_w(pEnvironment) : debugstr_a(pEnvironment));
914 p = (unicode) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment) :
918 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
920 if(!GetVersionExA( &ver))
923 switch (ver.dwPlatformId) {
924 case VER_PLATFORM_WIN32s:
925 ERR("win32 style printing used with 16 bits app, try -winver win95\n");
928 case VER_PLATFORM_WIN32_NT:
929 p = "Windows NT x86";
935 TRACE("set environment to %s\n", p);
938 lpKey = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
939 strlen(p) + strlen(Drivers));
940 sprintf( lpKey, Drivers, p);
942 TRACE("%s\n", lpKey);
944 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, lpKey, &retval) !=
948 if(pEnvironment && unicode)
949 HeapFree( GetProcessHeap(), 0, p);
950 HeapFree( GetProcessHeap(), 0, lpKey);
955 /*****************************************************************************
956 * AddPrinterW [WINSPOOL.@]
958 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
960 PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
964 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
967 TRACE("(%s,%ld,%p)\n", debugstr_w(pName), Level, pPrinter);
970 ERR("pName = %s - unsupported\n", debugstr_w(pName));
971 SetLastError(ERROR_INVALID_PARAMETER);
975 ERR("Level = %ld, unsupported!\n", Level);
976 SetLastError(ERROR_INVALID_LEVEL);
979 if (strlenW(pi->pPrinterName) >= CCHDEVICENAME) {
980 ERR("Printername %s must not exceed length of DEVMODE.dmDeviceName !\n",
981 debugstr_w(pi->pPrinterName)
983 SetLastError(ERROR_INVALID_LEVEL);
987 SetLastError(ERROR_INVALID_PARAMETER);
990 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
992 ERR("Can't create Printers key\n");
995 if(!RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter)) {
996 if (!RegQueryValueA(hkeyPrinter,"Attributes",NULL,NULL)) {
997 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
998 RegCloseKey(hkeyPrinter);
999 RegCloseKey(hkeyPrinters);
1002 RegCloseKey(hkeyPrinter);
1004 hkeyDrivers = WINSPOOL_OpenDriverReg( NULL, TRUE);
1006 ERR("Can't create Drivers key\n");
1007 RegCloseKey(hkeyPrinters);
1010 if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
1012 WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
1013 RegCloseKey(hkeyPrinters);
1014 RegCloseKey(hkeyDrivers);
1015 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
1018 RegCloseKey(hkeyDriver);
1019 RegCloseKey(hkeyDrivers);
1021 if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) { /* FIXME */
1022 FIXME("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
1023 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
1024 RegCloseKey(hkeyPrinters);
1028 if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
1030 FIXME("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
1031 SetLastError(ERROR_INVALID_PRINTER_NAME);
1032 RegCloseKey(hkeyPrinters);
1035 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
1036 (LPBYTE)&pi->Attributes, sizeof(DWORD));
1037 set_reg_szW(hkeyPrinter, DatatypeW, pi->pDatatype);
1039 /* See if we can load the driver. We may need the devmode structure anyway
1042 * Note that DocumentPropertiesW will briefly try to open the printer we
1043 * just create to find a DEVMODEA struct (it will use the WINEPS default
1044 * one in case it is not there, so we are ok).
1046 size = DocumentPropertiesW(0, -1, pi->pPrinterName, NULL, NULL, 0);
1048 FIXME("DocumentProperties fails\n");
1049 size = sizeof(DEVMODEW);
1054 dmW = HeapAlloc(GetProcessHeap(), 0, size);
1056 if (0>DocumentPropertiesW(0,-1,pi->pPrinterName,dmW,NULL,DM_OUT_BUFFER)) {
1057 ERR("DocumentPropertiesW failed!\n");
1058 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
1061 /* set devmode to printer name */
1062 strcpyW(dmW->dmDeviceName,pi->pPrinterName);
1065 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
1066 and we support these drivers. NT writes DEVMODEW so somehow
1067 we'll need to distinguish between these when we support NT
1069 dmA = DEVMODEdupWtoA(GetProcessHeap(), dmW);
1070 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, (LPBYTE)dmA,
1071 dmA->dmSize + dmA->dmDriverExtra);
1072 HeapFree(GetProcessHeap(), 0, dmA);
1074 HeapFree(GetProcessHeap(), 0, dmW);
1075 set_reg_szW(hkeyPrinter, DescriptionW, pi->pComment);
1076 set_reg_szW(hkeyPrinter, LocationW, pi->pLocation);
1077 set_reg_szW(hkeyPrinter, NameW, pi->pPrinterName);
1078 set_reg_szW(hkeyPrinter, ParametersW, pi->pParameters);
1080 set_reg_szW(hkeyPrinter, PortW, pi->pPortName);
1081 set_reg_szW(hkeyPrinter, Print_ProcessorW, pi->pPrintProcessor);
1082 set_reg_szW(hkeyPrinter, Printer_DriverW, pi->pDriverName);
1083 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
1084 (LPBYTE)&pi->Priority, sizeof(DWORD));
1085 set_reg_szW(hkeyPrinter, Separator_FileW, pi->pSepFile);
1086 set_reg_szW(hkeyPrinter, Share_NameW, pi->pShareName);
1087 RegSetValueExA(hkeyPrinter, "StartTime", 0, REG_DWORD,
1088 (LPBYTE)&pi->StartTime, sizeof(DWORD));
1089 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
1090 (LPBYTE)&pi->Status, sizeof(DWORD));
1091 RegSetValueExA(hkeyPrinter, "UntilTime", 0, REG_DWORD,
1092 (LPBYTE)&pi->UntilTime, sizeof(DWORD));
1094 RegCloseKey(hkeyPrinter);
1095 RegCloseKey(hkeyPrinters);
1096 if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
1097 ERR("OpenPrinter failing\n");
1103 /*****************************************************************************
1104 * AddPrinterA [WINSPOOL.@]
1106 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
1109 PRINTER_INFO_2W *piW;
1110 PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter;
1113 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName), Level, pPrinter);
1115 ERR("Level = %ld, unsupported!\n", Level);
1116 SetLastError(ERROR_INVALID_LEVEL);
1119 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
1120 piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA);
1122 ret = AddPrinterW(pNameW, Level, (LPBYTE)piW);
1124 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW);
1125 HeapFree(GetProcessHeap(),0,pNameW);
1130 /*****************************************************************************
1131 * ClosePrinter [WINSPOOL.@]
1133 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
1135 int i = (int)hPrinter;
1137 TRACE("Handle %d\n", hPrinter);
1139 if ((i <= 0) || (i > nb_printers)) return FALSE;
1140 HeapFree( GetProcessHeap(), 0, printer_array[i - 1] );
1141 printer_array[i - 1] = NULL;
1145 /*****************************************************************************
1146 * DeleteFormA [WINSPOOL.@]
1148 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
1150 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
1154 /*****************************************************************************
1155 * DeleteFormW [WINSPOOL.@]
1157 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
1159 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
1163 /*****************************************************************************
1164 * DeletePrinter [WINSPOOL.@]
1166 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
1168 LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
1171 if(!lpNameW) return FALSE;
1172 if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1174 ERR("Can't open Printers key\n");
1178 /* This should use a recursive delete see Q142491 or SHDeleteKey */
1179 if(RegDeleteKeyW(hkeyPrinters, lpNameW) == ERROR_SUCCESS) {
1180 SetLastError(ERROR_PRINTER_NOT_FOUND); /* ?? */
1181 RegCloseKey(hkeyPrinters);
1185 ClosePrinter(hPrinter);
1189 /*****************************************************************************
1190 * SetPrinterA [WINSPOOL.@]
1192 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1195 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
1199 /*****************************************************************************
1200 * SetJobA [WINSPOOL.@]
1202 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
1203 LPBYTE pJob, DWORD Command)
1205 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1210 /*****************************************************************************
1211 * SetJobW [WINSPOOL.@]
1213 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
1214 LPBYTE pJob, DWORD Command)
1216 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1221 /*****************************************************************************
1222 * GetFormA [WINSPOOL.@]
1224 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1225 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1227 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
1228 Level,pForm,cbBuf,pcbNeeded);
1232 /*****************************************************************************
1233 * GetFormW [WINSPOOL.@]
1235 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1236 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1238 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
1239 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
1243 /*****************************************************************************
1244 * SetFormA [WINSPOOL.@]
1246 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1249 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1253 /*****************************************************************************
1254 * SetFormW [WINSPOOL.@]
1256 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1259 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1263 /*****************************************************************************
1264 * ReadPrinter [WINSPOOL.@]
1266 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1267 LPDWORD pNoBytesRead)
1269 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1273 /*****************************************************************************
1274 * ResetPrinterA [WINSPOOL.@]
1276 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1278 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1282 /*****************************************************************************
1283 * ResetPrinterW [WINSPOOL.@]
1285 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1287 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1291 /*****************************************************************************
1292 * WINSPOOL_GetDWORDFromReg
1294 * Return DWORD associated with ValueName from hkey.
1296 static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName)
1298 DWORD sz = sizeof(DWORD), type, value = 0;
1301 ret = RegQueryValueExA(hkey, ValueName, 0, &type, (LPBYTE)&value, &sz);
1303 if(ret != ERROR_SUCCESS) {
1304 WARN("Got ret = %ld on name %s\n", ret, ValueName);
1307 if(type != REG_DWORD) {
1308 ERR("Got type %ld\n", type);
1314 /*****************************************************************************
1315 * WINSPOOL_GetStringFromReg
1317 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1318 * String is stored either as unicode or ascii.
1319 * Bit of a hack here to get the ValueName if we want ascii.
1321 static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr,
1322 DWORD buflen, DWORD *needed,
1325 DWORD sz = buflen, type;
1329 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1331 LPSTR ValueNameA = HEAP_strdupWtoA(GetProcessHeap(),0,ValueName);
1332 ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz);
1333 HeapFree(GetProcessHeap(),0,ValueNameA);
1335 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1336 WARN("Got ret = %ld\n", ret);
1344 /*****************************************************************************
1345 * WINSPOOL_GetDefaultDevMode
1347 * Get a default DevMode values for wineps.
1351 static void WINSPOOL_GetDefaultDevMode(
1353 DWORD buflen, DWORD *needed,
1358 /* fill default DEVMODE - should be read from ppd... */
1359 ZeroMemory( &dm, sizeof(dm) );
1360 strcpy(dm.dmDeviceName,"wineps");
1361 dm.dmSpecVersion = DM_SPECVERSION;
1362 dm.dmDriverVersion = 1;
1363 dm.dmSize = sizeof(DEVMODEA);
1364 dm.dmDriverExtra = 0;
1366 DM_ORIENTATION | DM_PAPERSIZE |
1367 DM_PAPERLENGTH | DM_PAPERWIDTH |
1370 DM_DEFAULTSOURCE | DM_PRINTQUALITY |
1371 DM_YRESOLUTION | DM_TTOPTION;
1373 dm.u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1374 dm.u1.s1.dmPaperSize = DMPAPER_A4;
1375 dm.u1.s1.dmPaperLength = 2970;
1376 dm.u1.s1.dmPaperWidth = 2100;
1380 dm.dmDefaultSource = DMBIN_AUTO;
1381 dm.dmPrintQuality = DMRES_MEDIUM;
1384 dm.dmYResolution = 300; /* 300dpi */
1385 dm.dmTTOption = DMTT_BITMAP;
1388 /* dm.dmLogPixels */
1389 /* dm.dmBitsPerPel */
1390 /* dm.dmPelsWidth */
1391 /* dm.dmPelsHeight */
1392 /* dm.dmDisplayFlags */
1393 /* dm.dmDisplayFrequency */
1394 /* dm.dmICMMethod */
1395 /* dm.dmICMIntent */
1396 /* dm.dmMediaType */
1397 /* dm.dmDitherType */
1398 /* dm.dmReserved1 */
1399 /* dm.dmReserved2 */
1400 /* dm.dmPanningWidth */
1401 /* dm.dmPanningHeight */
1404 if(buflen >= sizeof(DEVMODEW)) {
1405 DEVMODEW *pdmW = DEVMODEdupAtoW(GetProcessHeap(), &dm );
1406 memcpy(ptr, pdmW, sizeof(DEVMODEW));
1407 HeapFree(GetProcessHeap(),0,pdmW);
1409 *needed = sizeof(DEVMODEW);
1413 if(buflen >= sizeof(DEVMODEA)) {
1414 memcpy(ptr, &dm, sizeof(DEVMODEA));
1416 *needed = sizeof(DEVMODEA);
1420 /*****************************************************************************
1421 * WINSPOOL_GetDevModeFromReg
1423 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1424 * DevMode is stored either as unicode or ascii.
1426 static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
1428 DWORD buflen, DWORD *needed,
1431 DWORD sz = buflen, type;
1434 if (ptr && buflen>=sizeof(DEVMODEA)) memset(ptr, 0, sizeof(DEVMODEA));
1435 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1436 if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
1437 if (sz < sizeof(DEVMODEA))
1439 ERR("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName),sz);
1442 /* ensures that dmSize is not erratically bogus if registry is invalid */
1443 if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA))
1444 ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA);
1446 sz += (CCHDEVICENAME + CCHFORMNAME);
1448 DEVMODEW *dmW = DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA*)ptr);
1449 memcpy(ptr, dmW, sz);
1450 HeapFree(GetProcessHeap(),0,dmW);
1457 /*********************************************************************
1458 * WINSPOOL_GetPrinter_2
1460 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1461 * The strings are either stored as unicode or ascii.
1463 static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2,
1464 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1467 DWORD size, left = cbBuf;
1468 BOOL space = (cbBuf > 0);
1473 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1475 if(space && size <= left) {
1476 pi2->pPrinterName = (LPWSTR)ptr;
1483 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size,
1485 if(space && size <= left) {
1486 pi2->pShareName = (LPWSTR)ptr;
1493 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1495 if(space && size <= left) {
1496 pi2->pPortName = (LPWSTR)ptr;
1503 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left,
1505 if(space && size <= left) {
1506 pi2->pDriverName = (LPWSTR)ptr;
1513 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size,
1515 if(space && size <= left) {
1516 pi2->pComment = (LPWSTR)ptr;
1523 if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size,
1525 if(space && size <= left) {
1526 pi2->pLocation = (LPWSTR)ptr;
1533 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left,
1535 if(space && size <= left) {
1536 pi2->pDevMode = (LPDEVMODEW)ptr;
1545 MESSAGE( "no DevMode in registry. please setup your printer again.\n"
1546 "use the default hard-coded DevMode(wineps/A4/300dpi).\n" );
1547 WINSPOOL_GetDefaultDevMode(ptr, left, &size, unicode);
1548 if(space && size <= left) {
1549 pi2->pDevMode = (LPDEVMODEW)ptr;
1556 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left,
1558 if(space && size <= left) {
1559 pi2->pSepFile = (LPWSTR)ptr;
1566 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left,
1568 if(space && size <= left) {
1569 pi2->pPrintProcessor = (LPWSTR)ptr;
1576 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left,
1578 if(space && size <= left) {
1579 pi2->pDatatype = (LPWSTR)ptr;
1586 if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left,
1588 if(space && size <= left) {
1589 pi2->pParameters = (LPWSTR)ptr;
1597 pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1598 pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority");
1599 pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1600 "Default Priority");
1601 pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime");
1602 pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime");
1605 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
1606 memset(pi2, 0, sizeof(*pi2));
1611 /*********************************************************************
1612 * WINSPOOL_GetPrinter_4
1614 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1616 static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4,
1617 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1620 DWORD size, left = cbBuf;
1621 BOOL space = (cbBuf > 0);
1626 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1628 if(space && size <= left) {
1629 pi4->pPrinterName = (LPWSTR)ptr;
1637 pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1640 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
1641 memset(pi4, 0, sizeof(*pi4));
1646 /*********************************************************************
1647 * WINSPOOL_GetPrinter_5
1649 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1651 static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5,
1652 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1655 DWORD size, left = cbBuf;
1656 BOOL space = (cbBuf > 0);
1661 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1663 if(space && size <= left) {
1664 pi5->pPrinterName = (LPWSTR)ptr;
1671 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1673 if(space && size <= left) {
1674 pi5->pPortName = (LPWSTR)ptr;
1682 pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1683 pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1685 pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1689 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
1690 memset(pi5, 0, sizeof(*pi5));
1695 /*****************************************************************************
1696 * WINSPOOL_GetPrinter
1698 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1699 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1700 * just a collection of pointers to strings.
1702 static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1703 DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
1706 DWORD size, needed = 0;
1708 HKEY hkeyPrinter, hkeyPrinters;
1711 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1713 if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE;
1715 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1717 ERR("Can't create Printers key\n");
1720 if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter) != ERROR_SUCCESS)
1722 ERR("Can't find opened printer %s in registry\n", debugstr_w(name));
1723 RegCloseKey(hkeyPrinters);
1724 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1731 PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter;
1733 size = sizeof(PRINTER_INFO_2W);
1735 ptr = pPrinter + size;
1737 memset(pPrinter, 0, size);
1742 ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed,
1750 PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter;
1752 size = sizeof(PRINTER_INFO_4W);
1754 ptr = pPrinter + size;
1756 memset(pPrinter, 0, size);
1761 ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed,
1770 PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter;
1772 size = sizeof(PRINTER_INFO_5W);
1774 ptr = pPrinter + size;
1776 memset(pPrinter, 0, size);
1782 ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed,
1789 FIXME("Unimplemented level %ld\n", Level);
1790 SetLastError(ERROR_INVALID_LEVEL);
1791 RegCloseKey(hkeyPrinters);
1792 RegCloseKey(hkeyPrinter);
1796 RegCloseKey(hkeyPrinter);
1797 RegCloseKey(hkeyPrinters);
1799 TRACE("returing %d needed = %ld\n", ret, needed);
1800 if(pcbNeeded) *pcbNeeded = needed;
1802 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1806 /*****************************************************************************
1807 * GetPrinterW [WINSPOOL.@]
1809 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1810 DWORD cbBuf, LPDWORD pcbNeeded)
1812 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1816 /*****************************************************************************
1817 * GetPrinterA [WINSPOOL.@]
1819 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1820 DWORD cbBuf, LPDWORD pcbNeeded)
1822 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1826 /*****************************************************************************
1827 * WINSPOOL_EnumPrinters
1829 * Implementation of EnumPrintersA|W
1831 static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName,
1832 DWORD dwLevel, LPBYTE lpbPrinters,
1833 DWORD cbBuf, LPDWORD lpdwNeeded,
1834 LPDWORD lpdwReturned, BOOL unicode)
1837 HKEY hkeyPrinters, hkeyPrinter;
1838 WCHAR PrinterName[255];
1839 DWORD needed = 0, number = 0;
1840 DWORD used, i, left;
1844 memset(lpbPrinters, 0, cbBuf);
1850 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1851 if(dwType == PRINTER_ENUM_DEFAULT)
1854 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1855 FIXME("dwType = %08lx\n", dwType);
1856 SetLastError(ERROR_INVALID_FLAGS);
1860 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1862 ERR("Can't create Printers key\n");
1866 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1867 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1868 RegCloseKey(hkeyPrinters);
1869 ERR("Can't query Printers key\n");
1872 TRACE("Found %ld printers\n", number);
1876 RegCloseKey(hkeyPrinters);
1878 *lpdwReturned = number;
1882 used = number * sizeof(PRINTER_INFO_2W);
1885 used = number * sizeof(PRINTER_INFO_4W);
1888 used = number * sizeof(PRINTER_INFO_5W);
1892 SetLastError(ERROR_INVALID_LEVEL);
1893 RegCloseKey(hkeyPrinters);
1896 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1898 for(i = 0; i < number; i++) {
1899 if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1901 ERR("Can't enum key number %ld\n", i);
1902 RegCloseKey(hkeyPrinters);
1905 TRACE("Printer %ld is %s\n", i, debugstr_w(PrinterName));
1906 if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1908 ERR("Can't open key %s\n", debugstr_w(PrinterName));
1909 RegCloseKey(hkeyPrinters);
1914 buf = lpbPrinters + used;
1915 left = cbBuf - used;
1923 WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf,
1924 left, &needed, unicode);
1926 if(pi) pi += sizeof(PRINTER_INFO_2W);
1929 WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf,
1930 left, &needed, unicode);
1932 if(pi) pi += sizeof(PRINTER_INFO_4W);
1935 WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf,
1936 left, &needed, unicode);
1938 if(pi) pi += sizeof(PRINTER_INFO_5W);
1941 ERR("Shouldn't be here!\n");
1942 RegCloseKey(hkeyPrinter);
1943 RegCloseKey(hkeyPrinters);
1946 RegCloseKey(hkeyPrinter);
1948 RegCloseKey(hkeyPrinters);
1955 memset(lpbPrinters, 0, cbBuf);
1956 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1960 *lpdwReturned = number;
1961 SetLastError(ERROR_SUCCESS);
1966 /******************************************************************
1967 * EnumPrintersW [WINSPOOL.@]
1969 * Enumerates the available printers, print servers and print
1970 * providers, depending on the specified flags, name and level.
1974 * If level is set to 1:
1975 * Not implemented yet!
1976 * Returns TRUE with an empty list.
1978 * If level is set to 2:
1979 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1980 * Returns an array of PRINTER_INFO_2 data structures in the
1981 * lpbPrinters buffer. Note that according to MSDN also an
1982 * OpenPrinter should be performed on every remote printer.
1984 * If level is set to 4 (officially WinNT only):
1985 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1986 * Fast: Only the registry is queried to retrieve printer names,
1987 * no connection to the driver is made.
1988 * Returns an array of PRINTER_INFO_4 data structures in the
1989 * lpbPrinters buffer.
1991 * If level is set to 5 (officially WinNT4/Win9x only):
1992 * Fast: Only the registry is queried to retrieve printer names,
1993 * no connection to the driver is made.
1994 * Returns an array of PRINTER_INFO_5 data structures in the
1995 * lpbPrinters buffer.
1997 * If level set to 3 or 6+:
1998 * returns zero (failure!)
2000 * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
2004 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
2005 * - Only levels 2, 4 and 5 are implemented at the moment.
2006 * - 16-bit printer drivers are not enumerated.
2007 * - Returned amount of bytes used/needed does not match the real Windoze
2008 * implementation (as in this implementation, all strings are part
2009 * of the buffer, whereas Win32 keeps them somewhere else)
2010 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
2013 * - In a regular Wine installation, no registry settings for printers
2014 * exist, which makes this function return an empty list.
2016 BOOL WINAPI EnumPrintersW(
2017 DWORD dwType, /* [in] Types of print objects to enumerate */
2018 LPWSTR lpszName, /* [in] name of objects to enumerate */
2019 DWORD dwLevel, /* [in] type of printer info structure */
2020 LPBYTE lpbPrinters, /* [out] buffer which receives info */
2021 DWORD cbBuf, /* [in] max size of buffer in bytes */
2022 LPDWORD lpdwNeeded, /* [out] pointer to var: # bytes used/needed */
2023 LPDWORD lpdwReturned /* [out] number of entries returned */
2026 return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf,
2027 lpdwNeeded, lpdwReturned, TRUE);
2030 /******************************************************************
2031 * EnumPrintersA [WINSPOOL.@]
2034 BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
2035 DWORD dwLevel, LPBYTE lpbPrinters,
2036 DWORD cbBuf, LPDWORD lpdwNeeded,
2037 LPDWORD lpdwReturned)
2040 LPWSTR lpszNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpszName);
2042 ret = WINSPOOL_EnumPrinters(dwType, lpszNameW, dwLevel, lpbPrinters, cbBuf,
2043 lpdwNeeded, lpdwReturned, FALSE);
2044 HeapFree(GetProcessHeap(),0,lpszNameW);
2048 /*****************************************************************************
2049 * WINSPOOL_GetDriverInfoFromReg [internal]
2051 * Enters the information from the registry into the DRIVER_INFO struct
2054 * zero if the printer driver does not exist in the registry
2055 * (only if Level > 1) otherwise nonzero
2057 static BOOL WINSPOOL_GetDriverInfoFromReg(
2060 LPWSTR pEnvironment,
2062 LPBYTE ptr, /* DRIVER_INFO */
2063 LPBYTE pDriverStrings, /* strings buffer */
2064 DWORD cbBuf, /* size of string buffer */
2065 LPDWORD pcbNeeded, /* space needed for str. */
2066 BOOL unicode) /* type of strings */
2067 { DWORD dw, size, tmp, type;
2069 LPBYTE strPtr = pDriverStrings;
2071 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
2072 debugstr_w(DriverName), debugstr_w(pEnvironment),
2073 Level, ptr, pDriverStrings, cbBuf, unicode);
2076 *pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
2077 if (*pcbNeeded <= cbBuf)
2078 strcpyW((LPWSTR)strPtr, DriverName);
2080 *pcbNeeded = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0,
2082 if(*pcbNeeded <= cbBuf)
2083 WideCharToMultiByte(CP_ACP, 0, DriverName, -1, strPtr, *pcbNeeded,
2088 ((PDRIVER_INFO_1W) ptr)->pName = (LPWSTR) strPtr;
2092 ((PDRIVER_INFO_3W) ptr)->pName = (LPWSTR) strPtr;
2093 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
2096 if(!DriverName[0] || RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) {
2097 ERR("Can't find driver '%s' in registry\n", debugstr_w(DriverName));
2098 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
2103 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw, &size) !=
2105 WARN("Can't get Version\n");
2107 ((PDRIVER_INFO_3A) ptr)->cVersion = dw;
2110 pEnvironment = DefaultEnvironmentW;
2112 size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
2114 size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
2117 if(*pcbNeeded <= cbBuf) {
2119 strcpyW((LPWSTR)strPtr, pEnvironment);
2121 WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, strPtr, size,
2124 ((PDRIVER_INFO_3W) ptr)->pEnvironment = (LPWSTR)strPtr;
2125 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
2128 if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, 0, &size,
2131 if(*pcbNeeded <= cbBuf)
2132 WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, size, &tmp,
2135 ((PDRIVER_INFO_3W) ptr)->pDriverPath = (LPWSTR)strPtr;
2136 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
2139 if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, 0, &size,
2142 if(*pcbNeeded <= cbBuf)
2143 WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, size,
2146 ((PDRIVER_INFO_3W) ptr)->pDataFile = (LPWSTR)strPtr;
2147 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2150 if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
2151 0, &size, unicode)) {
2153 if(*pcbNeeded <= cbBuf)
2154 WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
2155 size, &tmp, unicode);
2157 ((PDRIVER_INFO_3W) ptr)->pConfigFile = (LPWSTR)strPtr;
2158 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2162 RegCloseKey(hkeyDriver);
2163 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
2167 if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, 0, &size,
2170 if(*pcbNeeded <= cbBuf)
2171 WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr,
2172 size, &tmp, unicode);
2174 ((PDRIVER_INFO_3W) ptr)->pHelpFile = (LPWSTR)strPtr;
2175 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2178 if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, 0,
2181 if(*pcbNeeded <= cbBuf)
2182 WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr,
2183 size, &tmp, unicode);
2185 ((PDRIVER_INFO_3W) ptr)->pDependentFiles = (LPWSTR)strPtr;
2186 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2189 if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size,
2192 if(*pcbNeeded <= cbBuf)
2193 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
2194 size, &tmp, unicode);
2196 ((PDRIVER_INFO_3W) ptr)->pMonitorName = (LPWSTR)strPtr;
2197 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2200 if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size,
2203 if(*pcbNeeded <= cbBuf)
2204 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
2205 size, &tmp, unicode);
2207 ((PDRIVER_INFO_3W) ptr)->pDefaultDataType = (LPWSTR)strPtr;
2208 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
2211 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
2212 RegCloseKey(hkeyDriver);
2216 /*****************************************************************************
2217 * WINSPOOL_GetPrinterDriver
2219 static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
2220 DWORD Level, LPBYTE pDriverInfo,
2221 DWORD cbBuf, LPDWORD pcbNeeded,
2225 WCHAR DriverName[100];
2226 DWORD ret, type, size, needed = 0;
2228 HKEY hkeyPrinter, hkeyPrinters, hkeyDrivers;
2230 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
2231 Level,pDriverInfo,cbBuf, pcbNeeded);
2233 ZeroMemory(pDriverInfo, cbBuf);
2235 if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE;
2237 if(Level < 1 || Level > 3) {
2238 SetLastError(ERROR_INVALID_LEVEL);
2241 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
2243 ERR("Can't create Printers key\n");
2246 if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter)
2248 ERR("Can't find opened printer %s in registry\n", debugstr_w(name));
2249 RegCloseKey(hkeyPrinters);
2250 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
2253 size = sizeof(DriverName);
2255 ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type,
2256 (LPBYTE)DriverName, &size);
2257 RegCloseKey(hkeyPrinter);
2258 RegCloseKey(hkeyPrinters);
2259 if(ret != ERROR_SUCCESS) {
2260 ERR("Can't get DriverName for printer %s\n", debugstr_w(name));
2264 hkeyDrivers = WINSPOOL_OpenDriverReg( pEnvironment, TRUE);
2266 ERR("Can't create Drivers key\n");
2272 size = sizeof(DRIVER_INFO_1W);
2275 size = sizeof(DRIVER_INFO_2W);
2278 size = sizeof(DRIVER_INFO_3W);
2281 ERR("Invalid level\n");
2286 ptr = pDriverInfo + size;
2288 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName,
2289 pEnvironment, Level, pDriverInfo,
2290 (cbBuf < size) ? NULL : ptr,
2291 (cbBuf < size) ? 0 : cbBuf - size,
2292 &needed, unicode)) {
2293 RegCloseKey(hkeyDrivers);
2297 RegCloseKey(hkeyDrivers);
2299 if(pcbNeeded) *pcbNeeded = size + needed;
2300 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
2301 if(cbBuf >= needed) return TRUE;
2302 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2306 /*****************************************************************************
2307 * GetPrinterDriverA [WINSPOOL.@]
2309 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
2310 DWORD Level, LPBYTE pDriverInfo,
2311 DWORD cbBuf, LPDWORD pcbNeeded)
2314 LPWSTR pEnvW = HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment);
2315 ret = WINSPOOL_GetPrinterDriver(hPrinter, pEnvW, Level, pDriverInfo,
2316 cbBuf, pcbNeeded, FALSE);
2317 HeapFree(GetProcessHeap(),0,pEnvW);
2320 /*****************************************************************************
2321 * GetPrinterDriverW [WINSPOOL.@]
2323 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
2324 DWORD Level, LPBYTE pDriverInfo,
2325 DWORD cbBuf, LPDWORD pcbNeeded)
2327 return WINSPOOL_GetPrinterDriver(hPrinter, pEnvironment, Level,
2328 pDriverInfo, cbBuf, pcbNeeded, TRUE);
2331 /*****************************************************************************
2332 * GetPrinterDriverDirectoryA [WINSPOOL.@]
2334 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
2335 DWORD Level, LPBYTE pDriverDirectory,
2336 DWORD cbBuf, LPDWORD pcbNeeded)
2340 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
2341 pDriverDirectory, cbBuf, pcbNeeded);
2343 FIXME("pName = `%s' - unsupported\n", pName);
2344 SetLastError(ERROR_INVALID_PARAMETER);
2347 if(pEnvironment != NULL) {
2348 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
2349 SetLastError(ERROR_INVALID_ENVIRONMENT);
2352 if(Level != 1) /* win95 ignores this so we just carry on */
2353 WARN("Level = %ld - assuming 1\n", Level);
2355 /* FIXME should read from registry */
2356 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
2359 *pcbNeeded = needed;
2360 if(needed > cbBuf) {
2361 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2368 /*****************************************************************************
2369 * GetPrinterDriverDirectoryW [WINSPOOL.@]
2371 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
2372 DWORD Level, LPBYTE pDriverDirectory,
2373 DWORD cbBuf, LPDWORD pcbNeeded)
2375 LPSTR pNameA = NULL, pEnvironmentA = NULL;
2379 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
2381 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
2382 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
2383 pDriverDirectory, cbBuf, pcbNeeded );
2385 HeapFree( GetProcessHeap(), 0, pNameA );
2387 HeapFree( GetProcessHeap(), 0, pEnvironmentA );
2392 /*****************************************************************************
2393 * AddPrinterDriverA [WINSPOOL.@]
2395 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
2398 HKEY hkeyDrivers, hkeyName;
2400 TRACE("(%s,%ld,%p)\n",debugstr_a(pName),level,pDriverInfo);
2402 if(level != 2 && level != 3) {
2403 SetLastError(ERROR_INVALID_LEVEL);
2407 FIXME("pName= %s - unsupported\n", debugstr_a(pName));
2408 SetLastError(ERROR_INVALID_PARAMETER);
2412 WARN("pDriverInfo == NULL\n");
2413 SetLastError(ERROR_INVALID_PARAMETER);
2418 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
2420 memset(&di3, 0, sizeof(di3));
2421 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
2424 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
2426 SetLastError(ERROR_INVALID_PARAMETER);
2429 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
2430 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
2431 if(!di3.pHelpFile) di3.pHelpFile = "";
2432 if(!di3.pMonitorName) di3.pMonitorName = "";
2434 hkeyDrivers = WINSPOOL_OpenDriverReg(di3.pEnvironment, FALSE);
2437 ERR("Can't create Drivers key\n");
2441 if(level == 2) { /* apparently can't overwrite with level2 */
2442 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
2443 RegCloseKey(hkeyName);
2444 RegCloseKey(hkeyDrivers);
2445 WARN("Trying to create existing printer driver %s\n", debugstr_a(di3.pName));
2446 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
2450 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
2451 RegCloseKey(hkeyDrivers);
2452 ERR("Can't create Name key\n");
2455 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
2457 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
2458 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
2459 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
2461 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
2462 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
2463 di3.pDependentFiles, 0);
2464 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
2465 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
2466 RegCloseKey(hkeyName);
2467 RegCloseKey(hkeyDrivers);
2471 /*****************************************************************************
2472 * AddPrinterDriverW [WINSPOOL.@]
2474 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
2477 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
2483 /*****************************************************************************
2484 * PrinterProperties [WINSPOOL.@]
2486 * Displays a dialog to set the properties of the printer.
2489 * nonzero on success or zero on failure
2492 * implemented as stub only
2494 BOOL WINAPI PrinterProperties(HWND hWnd, /* [in] handle to parent window */
2495 HANDLE hPrinter /* [in] handle to printer object */
2497 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
2498 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2502 /*****************************************************************************
2503 * EnumJobsA [WINSPOOL.@]
2506 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2507 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2511 if(pcbNeeded) *pcbNeeded = 0;
2512 if(pcReturned) *pcReturned = 0;
2517 /*****************************************************************************
2518 * EnumJobsW [WINSPOOL.@]
2521 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2522 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2526 if(pcbNeeded) *pcbNeeded = 0;
2527 if(pcReturned) *pcReturned = 0;
2531 /*****************************************************************************
2532 * WINSPOOL_EnumPrinterDrivers [internal]
2534 * Delivers information about all printer drivers installed on the
2535 * localhost or a given server
2538 * nonzero on success or zero on failure. If the buffer for the returned
2539 * information is too small the function will return an error
2542 * - only implemented for localhost, foreign hosts will return an error
2544 static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPWSTR pEnvironment,
2545 DWORD Level, LPBYTE pDriverInfo,
2546 DWORD cbBuf, LPDWORD pcbNeeded,
2547 LPDWORD pcReturned, BOOL unicode)
2550 DWORD i, needed, number = 0, size = 0;
2551 WCHAR DriverNameW[255];
2554 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2555 debugstr_w(pName), debugstr_w(pEnvironment),
2556 Level, pDriverInfo, cbBuf, unicode);
2558 /* check for local drivers */
2560 ERR("remote drivers unsupported! Current remote host is %s\n",
2565 /* check input parameter */
2566 if((Level < 1) || (Level > 3)) {
2567 ERR("unsupported level %ld \n", Level);
2571 /* initialize return values */
2573 memset( pDriverInfo, 0, cbBuf);
2577 hkeyDrivers = WINSPOOL_OpenDriverReg(pEnvironment, TRUE);
2579 ERR("Can't open Drivers key\n");
2583 if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, &number, NULL, NULL,
2584 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
2585 RegCloseKey(hkeyDrivers);
2586 ERR("Can't query Drivers key\n");
2589 TRACE("Found %ld Drivers\n", number);
2591 /* get size of single struct
2592 * unicode and ascii structure have the same size
2596 size = sizeof(DRIVER_INFO_1A);
2599 size = sizeof(DRIVER_INFO_2A);
2602 size = sizeof(DRIVER_INFO_3A);
2606 /* calculate required buffer size */
2607 *pcbNeeded = size * number;
2609 for( i = 0, ptr = (pDriverInfo && (cbBuf >= size)) ? pDriverInfo : NULL ;
2611 i++, ptr = (ptr && (cbBuf >= size * i)) ? ptr + size : NULL) {
2612 if(RegEnumKeyW(hkeyDrivers, i, DriverNameW, sizeof(DriverNameW))
2614 ERR("Can't enum key number %ld\n", i);
2615 RegCloseKey(hkeyDrivers);
2618 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW,
2619 pEnvironment, Level, ptr,
2620 (cbBuf < *pcbNeeded) ? NULL : pDriverInfo + *pcbNeeded,
2621 (cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded,
2622 &needed, unicode)) {
2623 RegCloseKey(hkeyDrivers);
2626 (*pcbNeeded) += needed;
2629 RegCloseKey(hkeyDrivers);
2631 if(cbBuf < *pcbNeeded){
2632 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2639 /*****************************************************************************
2640 * EnumPrinterDriversW [WINSPOOL.@]
2642 * see function EnumPrinterDrivers for RETURNS, BUGS
2644 BOOL WINAPI EnumPrinterDriversW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
2645 LPBYTE pDriverInfo, DWORD cbBuf,
2646 LPDWORD pcbNeeded, LPDWORD pcReturned)
2648 return WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo,
2649 cbBuf, pcbNeeded, pcReturned, TRUE);
2652 /*****************************************************************************
2653 * EnumPrinterDriversA [WINSPOOL.@]
2655 * see function EnumPrinterDrivers for RETURNS, BUGS
2657 BOOL WINAPI EnumPrinterDriversA(LPSTR pName, LPSTR pEnvironment, DWORD Level,
2658 LPBYTE pDriverInfo, DWORD cbBuf,
2659 LPDWORD pcbNeeded, LPDWORD pcReturned)
2661 WCHAR *pNameW = NULL, *pEnvironmentW = NULL;
2664 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
2666 pEnvironmentW = HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment);
2668 ret = WINSPOOL_EnumPrinterDrivers(pNameW, pEnvironmentW, Level, pDriverInfo,
2669 cbBuf, pcbNeeded, pcReturned, FALSE);
2671 HeapFree(GetProcessHeap(), 0, pNameW);
2673 HeapFree(GetProcessHeap(), 0, pEnvironmentW);
2679 /******************************************************************************
2680 * EnumPortsA (WINSPOOL.@)
2682 BOOL WINAPI EnumPortsA(LPSTR name,DWORD level,LPBYTE ports,DWORD bufsize,
2683 LPDWORD bufneeded,LPDWORD bufreturned)
2685 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name,level,ports,bufsize,bufneeded,bufreturned);
2689 /******************************************************************************
2690 * GetDefaultPrinterA (WINSPOOL.@)
2692 * Based on PRINTDLG_GetDefaultPrinterName in dlls/commdlg/printdlg.c
2694 BOOL WINAPI GetDefaultPrinterA(LPSTR name, LPDWORD namesize)
2700 SetLastError (ERROR_INSUFFICIENT_BUFFER);
2704 if (!GetProfileStringA ("windows", "device", "", name, *namesize))
2706 SetLastError (ERROR_FILE_NOT_FOUND);
2710 if ((ptr = strchr (name, ',')) == NULL)
2712 SetLastError (ERROR_FILE_NOT_FOUND);
2717 *namesize = strlen (name) + 1;
2722 /******************************************************************************
2723 * GetDefaultPrinterW (WINSPOOL.@)
2725 BOOL WINAPI GetDefaultPrinterW(LPWSTR name, LPDWORD namesize)
2732 SetLastError (ERROR_INSUFFICIENT_BUFFER);
2736 buf = HeapAlloc (GetProcessHeap (), 0, *namesize);
2737 ret = GetDefaultPrinterA (buf, namesize);
2740 DWORD len = MultiByteToWideChar (CP_ACP, 0, buf, -1, name, *namesize);
2743 SetLastError (ERROR_INSUFFICIENT_BUFFER);
2746 else *namesize = len;
2749 HeapFree (GetProcessHeap (), 0, buf);
2754 /******************************************************************************
2755 * SetPrinterDataExA (WINSPOOL.@)
2757 DWORD WINAPI SetPrinterDataExA(HANDLE hPrinter, LPSTR pKeyName,
2758 LPSTR pValueName, DWORD Type,
2759 LPBYTE pData, DWORD cbData)
2761 HKEY hkeyPrinter, hkeySubkey;
2764 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter, debugstr_a(pKeyName),
2765 debugstr_a(pValueName), Type, pData, cbData);
2767 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2771 if((ret = RegCreateKeyA(hkeyPrinter, pKeyName, &hkeySubkey))
2773 ERR("Can't create subkey %s\n", debugstr_a(pKeyName));
2774 RegCloseKey(hkeyPrinter);
2777 ret = RegSetValueExA(hkeySubkey, pValueName, 0, Type, pData, cbData);
2778 RegCloseKey(hkeySubkey);
2779 RegCloseKey(hkeyPrinter);
2783 /******************************************************************************
2784 * SetPrinterDataExW (WINSPOOL.@)
2786 DWORD WINAPI SetPrinterDataExW(HANDLE hPrinter, LPWSTR pKeyName,
2787 LPWSTR pValueName, DWORD Type,
2788 LPBYTE pData, DWORD cbData)
2790 HKEY hkeyPrinter, hkeySubkey;
2793 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter, debugstr_w(pKeyName),
2794 debugstr_w(pValueName), Type, pData, cbData);
2796 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2800 if((ret = RegCreateKeyW(hkeyPrinter, pKeyName, &hkeySubkey))
2802 ERR("Can't create subkey %s\n", debugstr_w(pKeyName));
2803 RegCloseKey(hkeyPrinter);
2806 ret = RegSetValueExW(hkeySubkey, pValueName, 0, Type, pData, cbData);
2807 RegCloseKey(hkeySubkey);
2808 RegCloseKey(hkeyPrinter);
2812 /******************************************************************************
2813 * SetPrinterDataA (WINSPOOL.@)
2815 DWORD WINAPI SetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, DWORD Type,
2816 LPBYTE pData, DWORD cbData)
2818 return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type,
2822 /******************************************************************************
2823 * SetPrinterDataW (WINSPOOL.@)
2825 DWORD WINAPI SetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, DWORD Type,
2826 LPBYTE pData, DWORD cbData)
2828 return SetPrinterDataExW(hPrinter, PrinterDriverDataW, pValueName, Type,
2832 /******************************************************************************
2833 * GetPrinterDataExA (WINSPOOL.@)
2835 DWORD WINAPI GetPrinterDataExA(HANDLE hPrinter, LPSTR pKeyName,
2836 LPSTR pValueName, LPDWORD pType,
2837 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2839 HKEY hkeyPrinter, hkeySubkey;
2842 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter,
2843 debugstr_a(pKeyName), debugstr_a(pValueName), pType, pData, nSize,
2846 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2850 if((ret = RegOpenKeyA(hkeyPrinter, pKeyName, &hkeySubkey))
2852 WARN("Can't open subkey %s\n", debugstr_a(pKeyName));
2853 RegCloseKey(hkeyPrinter);
2857 ret = RegQueryValueExA(hkeySubkey, pValueName, 0, pType, pData, pcbNeeded);
2858 RegCloseKey(hkeySubkey);
2859 RegCloseKey(hkeyPrinter);
2863 /******************************************************************************
2864 * GetPrinterDataExW (WINSPOOL.@)
2866 DWORD WINAPI GetPrinterDataExW(HANDLE hPrinter, LPWSTR pKeyName,
2867 LPWSTR pValueName, LPDWORD pType,
2868 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2870 HKEY hkeyPrinter, hkeySubkey;
2873 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter,
2874 debugstr_w(pKeyName), debugstr_w(pValueName), pType, pData, nSize,
2877 if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter))
2881 if((ret = RegOpenKeyW(hkeyPrinter, pKeyName, &hkeySubkey))
2883 WARN("Can't open subkey %s\n", debugstr_w(pKeyName));
2884 RegCloseKey(hkeyPrinter);
2888 ret = RegQueryValueExW(hkeySubkey, pValueName, 0, pType, pData, pcbNeeded);
2889 RegCloseKey(hkeySubkey);
2890 RegCloseKey(hkeyPrinter);
2894 /******************************************************************************
2895 * GetPrinterDataA (WINSPOOL.@)
2897 DWORD WINAPI GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType,
2898 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2900 return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType,
2901 pData, nSize, pcbNeeded);
2904 /******************************************************************************
2905 * GetPrinterDataW (WINSPOOL.@)
2907 DWORD WINAPI GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType,
2908 LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
2910 return GetPrinterDataExW(hPrinter, PrinterDriverDataW, pValueName, pType,
2911 pData, nSize, pcbNeeded);
2914 /*******************************************************************************
2915 * EnumPrinterDataExW [WINSPOOL.@]
2917 DWORD WINAPI EnumPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName,
2918 LPBYTE pEnumValues, DWORD cbEnumValues,
2919 LPDWORD pcbEnumValues, LPDWORD pnEnumValues)
2921 HKEY hkPrinter, hkSubKey;
2922 DWORD r, ret, dwIndex, cValues, cbMaxValueNameLen,
2923 cbValueNameLen, cbMaxValueLen, cbValueLen,
2928 PPRINTER_ENUM_VALUESW ppev;
2930 TRACE ("%08x %s\n", hPrinter, debugstr_w (pKeyName));
2932 if (pKeyName == NULL || *pKeyName == 0)
2933 return ERROR_INVALID_PARAMETER;
2935 ret = WINSPOOL_GetOpenedPrinterRegKey (hPrinter, &hkPrinter);
2936 if (ret != ERROR_SUCCESS)
2938 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%08x) returned %li\n",
2943 ret = RegOpenKeyExW (hkPrinter, pKeyName, 0, KEY_READ, &hkSubKey);
2944 if (ret != ERROR_SUCCESS)
2946 r = RegCloseKey (hkPrinter);
2947 if (r != ERROR_SUCCESS)
2948 WARN ("RegCloseKey returned %li\n", r);
2949 TRACE ("RegOpenKeyExW (%08x, %s) returned %li\n", hPrinter,
2950 debugstr_w (pKeyName), ret);
2954 ret = RegCloseKey (hkPrinter);
2955 if (ret != ERROR_SUCCESS)
2957 ERR ("RegCloseKey returned %li\n", ret);
2958 r = RegCloseKey (hkSubKey);
2959 if (r != ERROR_SUCCESS)
2960 WARN ("RegCloseKey returned %li\n", r);
2964 ret = RegQueryInfoKeyW (hkSubKey, NULL, NULL, NULL, NULL, NULL, NULL,
2965 &cValues, &cbMaxValueNameLen, &cbMaxValueLen, NULL, NULL);
2966 if (ret != ERROR_SUCCESS)
2968 r = RegCloseKey (hkSubKey);
2969 if (r != ERROR_SUCCESS)
2970 WARN ("RegCloseKey returned %li\n", r);
2971 TRACE ("RegQueryInfoKeyW (%08x) returned %li\n", hkSubKey, ret);
2975 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
2976 "cbMaxValueLen = %li\n", cValues, cbMaxValueNameLen, cbMaxValueLen);
2978 if (cValues == 0) /* empty key */
2980 r = RegCloseKey (hkSubKey);
2981 if (r != ERROR_SUCCESS)
2982 WARN ("RegCloseKey returned %li\n", r);
2983 *pcbEnumValues = *pnEnumValues = 0;
2984 return ERROR_SUCCESS;
2987 ++cbMaxValueNameLen; /* allow for trailing '\0' */
2989 hHeap = GetProcessHeap ();
2990 if (hHeap == (HANDLE) NULL)
2992 ERR ("GetProcessHeap failed\n");
2993 r = RegCloseKey (hkSubKey);
2994 if (r != ERROR_SUCCESS)
2995 WARN ("RegCloseKey returned %li\n", r);
2996 return ERROR_OUTOFMEMORY;
2999 lpValueName = HeapAlloc (hHeap, 0, cbMaxValueNameLen * sizeof (WCHAR));
3000 if (lpValueName == NULL)
3002 ERR ("Failed to allocate %li bytes from process heap\n",
3003 cbMaxValueNameLen * sizeof (WCHAR));
3004 r = RegCloseKey (hkSubKey);
3005 if (r != ERROR_SUCCESS)
3006 WARN ("RegCloseKey returned %li\n", r);
3007 return ERROR_OUTOFMEMORY;
3010 lpValue = HeapAlloc (hHeap, 0, cbMaxValueLen);
3011 if (lpValue == NULL)
3013 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen);
3014 if (HeapFree (hHeap, 0, lpValueName) == 0)
3015 WARN ("HeapFree failed with code %li\n", GetLastError ());
3016 r = RegCloseKey (hkSubKey);
3017 if (r != ERROR_SUCCESS)
3018 WARN ("RegCloseKey returned %li\n", r);
3019 return ERROR_OUTOFMEMORY;
3022 TRACE ("pass 1: calculating buffer required for all names and values\n");
3024 cbBufSize = cValues * sizeof (PRINTER_ENUM_VALUESW);
3026 TRACE ("%li bytes required for %li headers\n", cbBufSize, cValues);
3028 for (dwIndex = 0; dwIndex < cValues; ++dwIndex)
3030 cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen;
3031 ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen,
3032 NULL, NULL, lpValue, &cbValueLen);
3033 if (ret != ERROR_SUCCESS)
3035 if (HeapFree (hHeap, 0, lpValue) == 0)
3036 WARN ("HeapFree failed with code %li\n", GetLastError ());
3037 if (HeapFree (hHeap, 0, lpValueName) == 0)
3038 WARN ("HeapFree failed with code %li\n", GetLastError ());
3039 r = RegCloseKey (hkSubKey);
3040 if (r != ERROR_SUCCESS)
3041 WARN ("RegCloseKey returned %li\n", r);
3042 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex, ret);
3046 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
3047 debugstr_w (lpValueName), dwIndex,
3048 (cbValueNameLen + 1) * sizeof (WCHAR), cbValueLen);
3050 cbBufSize += (cbValueNameLen + 1) * sizeof (WCHAR);
3051 cbBufSize += cbValueLen;
3054 TRACE ("%li bytes required for all %li values\n", cbBufSize, cValues);
3056 *pcbEnumValues = cbBufSize;
3057 *pnEnumValues = cValues;
3059 if (cbEnumValues < cbBufSize) /* buffer too small */
3061 if (HeapFree (hHeap, 0, lpValue) == 0)
3062 WARN ("HeapFree failed with code %li\n", GetLastError ());
3063 if (HeapFree (hHeap, 0, lpValueName) == 0)
3064 WARN ("HeapFree failed with code %li\n", GetLastError ());
3065 r = RegCloseKey (hkSubKey);
3066 if (r != ERROR_SUCCESS)
3067 WARN ("RegCloseKey returned %li\n", r);
3068 TRACE ("%li byte buffer is not large enough\n", cbEnumValues);
3069 return ERROR_MORE_DATA;
3072 TRACE ("pass 2: copying all names and values to buffer\n");
3074 ppev = (PPRINTER_ENUM_VALUESW) pEnumValues; /* array of structs */
3075 pEnumValues += cValues * sizeof (PRINTER_ENUM_VALUESW);
3077 for (dwIndex = 0; dwIndex < cValues; ++dwIndex)
3079 cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen;
3080 ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen,
3081 NULL, &dwType, lpValue, &cbValueLen);
3082 if (ret != ERROR_SUCCESS)
3084 if (HeapFree (hHeap, 0, lpValue) == 0)
3085 WARN ("HeapFree failed with code %li\n", GetLastError ());
3086 if (HeapFree (hHeap, 0, lpValueName) == 0)
3087 WARN ("HeapFree failed with code %li\n", GetLastError ());
3088 r = RegCloseKey (hkSubKey);
3089 if (r != ERROR_SUCCESS)
3090 WARN ("RegCloseKey returned %li\n", r);
3091 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex, ret);
3095 cbValueNameLen = (cbValueNameLen + 1) * sizeof (WCHAR);
3096 memcpy (pEnumValues, lpValueName, cbValueNameLen);
3097 ppev[dwIndex].pValueName = (LPWSTR) pEnumValues;
3098 pEnumValues += cbValueNameLen;
3100 /* return # of *bytes* (including trailing \0), not # of chars */
3101 ppev[dwIndex].cbValueName = cbValueNameLen;
3103 ppev[dwIndex].dwType = dwType;
3105 memcpy (pEnumValues, lpValue, cbValueLen);
3106 ppev[dwIndex].pData = pEnumValues;
3107 pEnumValues += cbValueLen;
3109 ppev[dwIndex].cbData = cbValueLen;
3111 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
3112 debugstr_w (lpValueName), dwIndex, cbValueNameLen, cbValueLen);
3115 if (HeapFree (hHeap, 0, lpValue) == 0)
3117 ret = GetLastError ();
3118 ERR ("HeapFree failed with code %li\n", ret);
3119 if (HeapFree (hHeap, 0, lpValueName) == 0)
3120 WARN ("HeapFree failed with code %li\n", GetLastError ());
3121 r = RegCloseKey (hkSubKey);
3122 if (r != ERROR_SUCCESS)
3123 WARN ("RegCloseKey returned %li\n", r);
3127 if (HeapFree (hHeap, 0, lpValueName) == 0)
3129 ret = GetLastError ();
3130 ERR ("HeapFree failed with code %li\n", ret);
3131 r = RegCloseKey (hkSubKey);
3132 if (r != ERROR_SUCCESS)
3133 WARN ("RegCloseKey returned %li\n", r);
3137 ret = RegCloseKey (hkSubKey);
3138 if (ret != ERROR_SUCCESS)
3140 ERR ("RegCloseKey returned %li\n", ret);
3144 return ERROR_SUCCESS;
3147 /*******************************************************************************
3148 * EnumPrinterDataExA [WINSPOOL.@]
3150 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
3151 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
3152 * what Windows 2000 SP1 does.
3155 DWORD WINAPI EnumPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName,
3156 LPBYTE pEnumValues, DWORD cbEnumValues,
3157 LPDWORD pcbEnumValues, LPDWORD pnEnumValues)
3161 DWORD ret, dwIndex, dwBufSize;
3165 TRACE ("%08x %s\n", hPrinter, pKeyName);
3167 if (pKeyName == NULL || *pKeyName == 0)
3168 return ERROR_INVALID_PARAMETER;
3170 len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0);
3173 ret = GetLastError ();
3174 ERR ("MultiByteToWideChar failed with code %li\n", ret);
3178 hHeap = GetProcessHeap ();
3179 if (hHeap == (HANDLE) NULL)
3181 ERR ("GetProcessHeap failed\n");
3182 return ERROR_OUTOFMEMORY;
3185 pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR));
3186 if (pKeyNameW == NULL)
3188 ERR ("Failed to allocate %li bytes from process heap\n",
3189 (LONG) len * sizeof (WCHAR));
3190 return ERROR_OUTOFMEMORY;
3193 if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0)
3195 ret = GetLastError ();
3196 ERR ("MultiByteToWideChar failed with code %li\n", ret);
3197 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
3198 WARN ("HeapFree failed with code %li\n", GetLastError ());
3202 ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues,
3203 pcbEnumValues, pnEnumValues);
3204 if (ret != ERROR_SUCCESS)
3206 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
3207 WARN ("HeapFree failed with code %li\n", GetLastError ());
3208 TRACE ("EnumPrinterDataExW returned %li\n", ret);
3212 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
3214 ret = GetLastError ();
3215 ERR ("HeapFree failed with code %li\n", ret);
3219 if (*pnEnumValues == 0) /* empty key */
3220 return ERROR_SUCCESS;
3223 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
3225 PPRINTER_ENUM_VALUESW ppev =
3226 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
3228 if (dwBufSize < ppev->cbValueName)
3229 dwBufSize = ppev->cbValueName;
3231 if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ ||
3232 ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
3233 dwBufSize = ppev->cbData;
3236 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize);
3238 pBuffer = HeapAlloc (hHeap, 0, dwBufSize);
3239 if (pBuffer == NULL)
3241 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize);
3242 return ERROR_OUTOFMEMORY;
3245 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
3247 PPRINTER_ENUM_VALUESW ppev =
3248 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
3250 len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName,
3251 ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL,
3255 ret = GetLastError ();
3256 ERR ("WideCharToMultiByte failed with code %li\n", ret);
3257 if (HeapFree (hHeap, 0, pBuffer) == 0)
3258 WARN ("HeapFree failed with code %li\n", GetLastError ());
3262 memcpy (ppev->pValueName, pBuffer, len);
3264 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
3266 if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ &&
3267 ppev->dwType != REG_MULTI_SZ)
3270 len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData,
3271 ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL);
3274 ret = GetLastError ();
3275 ERR ("WideCharToMultiByte failed with code %li\n", ret);
3276 if (HeapFree (hHeap, 0, pBuffer) == 0)
3277 WARN ("HeapFree failed with code %li\n", GetLastError ());
3281 memcpy (ppev->pData, pBuffer, len);
3283 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
3284 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
3287 if (HeapFree (hHeap, 0, pBuffer) == 0)
3289 ret = GetLastError ();
3290 ERR ("HeapFree failed with code %li\n", ret);
3294 return ERROR_SUCCESS;