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
);
82 CUPS_LoadPrinters(void) {
85 PRINTER_INFO_2A pinfo2a
;
87 const char* def
= cupsGetDefault();
89 nrofdests
= cupsGetDests(&dests
);
91 di3a
.cVersion
= 0x400;
92 di3a
.pName
= "PS Driver";
93 di3a
.pEnvironment
= NULL
; /* NULL means auto */
94 di3a
.pDriverPath
= "wineps.drv";
95 di3a
.pDataFile
= "<datafile?>";
96 di3a
.pConfigFile
= "wineps.drv";
97 di3a
.pHelpFile
= "<helpfile?>";
98 di3a
.pDependentFiles
= "<dependend files?>";
99 di3a
.pMonitorName
= "<monitor name?>";
100 di3a
.pDefaultDataType
= "RAW";
103 if (!AddPrinterDriverA(NULL
,3,(LPBYTE
)&di3a
)) {
104 ERR("Failed adding PS Driver (%ld)\n",GetLastError());
107 for (i
=0;i
<nrofdests
;i
++) {
108 const char *ppd
= cupsGetPPD(dests
[i
].name
);
115 if (!strcmp(def
,dests
[i
].name
)) {
116 char *buf
= HeapAlloc(GetProcessHeap(),0,2*strlen(dests
[i
].name
)+strlen(",WINEPS,CUPS:")+1);
118 sprintf(buf
,"%s,WINEPS,CUPS:%s",dests
[i
].name
,dests
[i
].name
);
119 WriteProfileStringA("windows","device",buf
);
120 HeapFree(GetProcessHeap(),0,buf
);
122 memset(&pinfo2a
,0,sizeof(pinfo2a
));
123 pinfo2a
.pPrinterName
= dests
[i
].name
;
124 pinfo2a
.pDatatype
= "RAW";
125 pinfo2a
.pPrintProcessor
= "WinPrint";
126 pinfo2a
.pDriverName
= "PS Driver";
127 pinfo2a
.pComment
= "WINEPS Printer using CUPS";
128 pinfo2a
.pLocation
= "<physical location of printer>";
129 port
= HeapAlloc(GetProcessHeap(),0,strlen("CUPS:")+strlen(dests
[i
].name
)+1);
130 sprintf(port
,"CUPS:%s",dests
[i
].name
);
131 pinfo2a
.pPortName
= port
;
132 pinfo2a
.pParameters
= "<parameters?>";
133 pinfo2a
.pShareName
= "<share name?>";
134 pinfo2a
.pSepFile
= "<sep file?>";
136 devline
=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port
)+1);
137 sprintf(devline
,"WINEPS,%s",port
);
138 WriteProfileStringA("devices",dests
[i
].name
,devline
);
139 HeapFree(GetProcessHeap(),0,devline
);
141 if (!AddPrinterA(NULL
,2,(LPBYTE
)&pinfo2a
)) {
142 if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS
)
143 ERR("%s not added by AddPrinterA (%ld)\n",dests
[i
].name
,GetLastError());
145 HeapFree(GetProcessHeap(),0,port
);
151 /******************************************************************
152 * WINSPOOL_GetOpenedPrinterEntry
153 * Get the first place empty in the opened printer table
155 static HANDLE
WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name
)
159 for (i
= 0; i
< nb_printers
; i
++) if (!printer_array
[i
]) break;
161 if (i
>= nb_printers
)
163 LPWSTR
*new_array
= HeapReAlloc( GetProcessHeap(), 0, printer_array
,
164 (nb_printers
+ 16) * sizeof(*new_array
) );
165 if (!new_array
) return 0;
166 printer_array
= new_array
;
170 if ((printer_array
[i
] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name
)+1)*sizeof(WCHAR
) )))
172 strcpyW( printer_array
[i
], name
);
173 return (HANDLE
)(i
+ 1);
178 /******************************************************************
179 * WINSPOOL_GetOpenedPrinter
180 * Get the pointer to the opened printer referred by the handle
182 static LPCWSTR
WINSPOOL_GetOpenedPrinter(HANDLE printerHandle
)
184 int idx
= (int)printerHandle
;
185 if ((idx
<= 0) || (idx
> nb_printers
))
187 SetLastError(ERROR_INVALID_HANDLE
);
190 return printer_array
[idx
- 1];
193 /******************************************************************
194 * WINSPOOL_GetOpenedPrinterRegKey
197 static DWORD
WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter
, HKEY
*phkey
)
199 LPCWSTR name
= WINSPOOL_GetOpenedPrinter(hPrinter
);
203 if(!name
) return ERROR_INVALID_HANDLE
;
205 if((ret
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
)) !=
209 if(RegOpenKeyW(hkeyPrinters
, name
, phkey
) != ERROR_SUCCESS
)
211 ERR("Can't find opened printer %s in registry\n",
213 RegCloseKey(hkeyPrinters
);
214 return ERROR_INVALID_PRINTER_NAME
; /* ? */
216 RegCloseKey(hkeyPrinters
);
217 return ERROR_SUCCESS
;
220 /***********************************************************
223 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
226 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
229 Formname
= (dmA
->dmSize
> off_formname
);
230 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
231 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
234 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
235 dmA
->dmSize
- CCHDEVICENAME
);
237 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
238 off_formname
- CCHDEVICENAME
);
239 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
241 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
242 (off_formname
+ CCHFORMNAME
));
245 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
250 /***********************************************************
252 * Creates a unicode copy of supplied devmode on heap
254 static LPDEVMODEW
DEVMODEdupAtoW(HANDLE heap
, const DEVMODEA
*dmA
)
259 ptrdiff_t off_formname
;
262 if(!dmA
) return NULL
;
264 off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
265 Formname
= (dmA
->dmSize
> off_formname
);
266 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
267 dmW
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmA
->dmDriverExtra
);
268 return DEVMODEcpyAtoW(dmW
, dmA
);
271 /***********************************************************
273 * Creates an ascii copy of supplied devmode on heap
275 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
280 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
282 if(!dmW
) return NULL
;
283 Formname
= (dmW
->dmSize
> off_formname
);
284 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
285 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
286 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
287 CCHDEVICENAME
, NULL
, NULL
);
289 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
290 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
292 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
293 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
294 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
295 CCHFORMNAME
, NULL
, NULL
);
296 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
297 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
300 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
305 /***********************************************************
307 * Creates a unicode copy of PRINTER_INFO_2A on heap
309 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
311 LPPRINTER_INFO_2W piW
;
312 if(!piA
) return NULL
;
313 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
314 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
315 piW
->pServerName
= HEAP_strdupAtoW(heap
, 0, piA
->pServerName
);
316 piW
->pPrinterName
= HEAP_strdupAtoW(heap
, 0, piA
->pPrinterName
);
317 piW
->pShareName
= HEAP_strdupAtoW(heap
, 0, piA
->pShareName
);
318 piW
->pPortName
= HEAP_strdupAtoW(heap
, 0, piA
->pPortName
);
319 piW
->pDriverName
= HEAP_strdupAtoW(heap
, 0, piA
->pDriverName
);
320 piW
->pComment
= HEAP_strdupAtoW(heap
, 0, piA
->pComment
);
321 piW
->pLocation
= HEAP_strdupAtoW(heap
, 0, piA
->pLocation
);
322 piW
->pDevMode
= DEVMODEdupAtoW(heap
, piA
->pDevMode
);
323 piW
->pSepFile
= HEAP_strdupAtoW(heap
, 0, piA
->pSepFile
);
324 piW
->pPrintProcessor
= HEAP_strdupAtoW(heap
, 0, piA
->pPrintProcessor
);
325 piW
->pDatatype
= HEAP_strdupAtoW(heap
, 0, piA
->pDatatype
);
326 piW
->pParameters
= HEAP_strdupAtoW(heap
, 0, piA
->pParameters
);
330 /***********************************************************
331 * FREE_PRINTER_INFO_2W
332 * Free PRINTER_INFO_2W and all strings
334 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
338 HeapFree(heap
,0,piW
->pServerName
);
339 HeapFree(heap
,0,piW
->pPrinterName
);
340 HeapFree(heap
,0,piW
->pShareName
);
341 HeapFree(heap
,0,piW
->pPortName
);
342 HeapFree(heap
,0,piW
->pDriverName
);
343 HeapFree(heap
,0,piW
->pComment
);
344 HeapFree(heap
,0,piW
->pLocation
);
345 HeapFree(heap
,0,piW
->pDevMode
);
346 HeapFree(heap
,0,piW
->pSepFile
);
347 HeapFree(heap
,0,piW
->pPrintProcessor
);
348 HeapFree(heap
,0,piW
->pDatatype
);
349 HeapFree(heap
,0,piW
->pParameters
);
350 HeapFree(heap
,0,piW
);
354 /******************************************************************
355 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
358 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
359 LPSTR pOutput
, LPDEVMODEA lpdm
)
363 if (!GDI_CallDeviceCapabilities16
)
365 GDI_CallDeviceCapabilities16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
367 if (!GDI_CallDeviceCapabilities16
) return -1;
369 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
371 /* If DC_PAPERSIZE map POINT16s to POINTs */
372 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
373 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
374 POINT
*pt
= (POINT
*)pOutput
;
376 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
377 for(i
= 0; i
< ret
; i
++, pt
++)
382 HeapFree( GetProcessHeap(), 0, tmp
);
388 /*****************************************************************************
389 * DeviceCapabilitiesW [WINSPOOL.152]
391 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
394 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
395 WORD fwCapability
, LPWSTR pOutput
,
396 const DEVMODEW
*pDevMode
)
398 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
399 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
400 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
403 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
404 fwCapability
== DC_FILEDEPENDENCIES
||
405 fwCapability
== DC_PAPERNAMES
)) {
406 /* These need A -> W translation */
409 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
413 switch(fwCapability
) {
418 case DC_FILEDEPENDENCIES
:
422 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
423 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
425 for(i
= 0; i
< ret
; i
++)
426 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
427 pOutput
+ (i
* size
), size
);
428 HeapFree(GetProcessHeap(), 0, pOutputA
);
430 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
431 (LPSTR
)pOutput
, dmA
);
433 HeapFree(GetProcessHeap(),0,pPortA
);
434 HeapFree(GetProcessHeap(),0,pDeviceA
);
435 HeapFree(GetProcessHeap(),0,dmA
);
439 /******************************************************************
440 * DocumentPropertiesA [WINSPOOL.155]
443 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
444 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
445 LPDEVMODEA pDevModeInput
,DWORD fMode
)
447 LPSTR lpName
= pDeviceName
;
450 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
451 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
455 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
457 ERR("no name from hPrinter?\n");
460 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
463 if (!GDI_CallExtDeviceMode16
)
465 GDI_CallExtDeviceMode16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
467 if (!GDI_CallExtDeviceMode16
) {
468 ERR("No CallExtDeviceMode16?\n");
472 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
473 pDevModeInput
, NULL
, fMode
);
476 HeapFree(GetProcessHeap(),0,lpName
);
481 /*****************************************************************************
482 * DocumentPropertiesW
484 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
486 LPDEVMODEW pDevModeOutput
,
487 LPDEVMODEW pDevModeInput
, DWORD fMode
)
490 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
491 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
492 LPDEVMODEA pDevModeOutputA
= NULL
;
495 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
496 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
499 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
500 if(ret
< 0) return ret
;
501 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
503 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
504 pDevModeInputA
, fMode
);
506 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
507 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
509 if(fMode
== 0 && ret
> 0)
510 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
511 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
512 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
516 /******************************************************************
517 * OpenPrinterA [WINSPOOL.196]
520 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
521 LPPRINTER_DEFAULTSA pDefault
)
523 LPWSTR lpPrinterNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName
);
524 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
528 DefaultW
.pDatatype
= HEAP_strdupAtoW(GetProcessHeap(), 0,
529 pDefault
->pDatatype
);
530 DefaultW
.pDevMode
= DEVMODEdupAtoW(GetProcessHeap(),
532 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
533 pDefaultW
= &DefaultW
;
535 ret
= OpenPrinterW(lpPrinterNameW
, phPrinter
, pDefaultW
);
537 HeapFree(GetProcessHeap(), 0, DefaultW
.pDatatype
);
538 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
540 HeapFree(GetProcessHeap(), 0, lpPrinterNameW
);
544 /******************************************************************
545 * OpenPrinterW [WINSPOOL.197]
548 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
549 LPPRINTER_DEFAULTSW pDefault
)
551 HKEY hkeyPrinters
, hkeyPrinter
;
553 if (!lpPrinterName
) {
554 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
555 SetLastError(ERROR_INVALID_PARAMETER
);
559 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
562 /* Check Printer exists */
563 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
565 ERR("Can't create Printers key\n");
566 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
570 if(RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
572 ERR("Can't find printer %s in registry\n", debugstr_w(lpPrinterName
));
573 RegCloseKey(hkeyPrinters
);
574 SetLastError(ERROR_INVALID_PARAMETER
);
577 RegCloseKey(hkeyPrinter
);
578 RegCloseKey(hkeyPrinters
);
580 if(!phPrinter
) /* This seems to be what win95 does anyway */
583 /* Get the unique handle of the printer*/
584 *phPrinter
= WINSPOOL_GetOpenedPrinterEntry( lpPrinterName
);
586 if (pDefault
!= NULL
)
587 FIXME("Not handling pDefault\n");
592 /******************************************************************
593 * AddMonitorA [WINSPOOL.107]
596 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
598 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
599 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
603 /******************************************************************
604 * DeletePrinterDriverA [WINSPOOL.146]
608 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
610 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
611 debugstr_a(pDriverName
));
612 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
617 /******************************************************************
618 * DeleteMonitorA [WINSPOOL.135]
622 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
624 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
625 debugstr_a(pMonitorName
));
626 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
631 /******************************************************************
632 * DeletePortA [WINSPOOL.137]
636 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
638 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
639 debugstr_a(pPortName
));
640 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
644 /******************************************************************************
645 * SetPrinterW [WINSPOOL.214]
655 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
659 /******************************************************************************
660 * WritePrinter [WINSPOOL.223]
670 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
674 /*****************************************************************************
675 * AddFormA [WINSPOOL.103]
677 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
679 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
683 /*****************************************************************************
684 * AddFormW [WINSPOOL.104]
686 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
688 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
692 /*****************************************************************************
693 * AddJobA [WINSPOOL.105]
695 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
696 DWORD cbBuf
, LPDWORD pcbNeeded
)
698 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
703 /*****************************************************************************
704 * AddJobW [WINSPOOL.106]
706 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
709 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
714 /*****************************************************************************
715 * WINSPOOL_OpenDriverReg [internal]
717 * opens the registry for the printer drivers depending on the given input
718 * variable pEnvironment
721 * the opened hkey on success
724 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
)
726 LPSTR lpKey
, p
= NULL
;
729 (unicode
) ? debugstr_w(pEnvironment
) : debugstr_a(pEnvironment
));
732 p
= (unicode
) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
) :
736 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
738 if(!GetVersionExA( &ver
))
741 switch (ver
.dwPlatformId
) {
742 case VER_PLATFORM_WIN32s
:
744 case VER_PLATFORM_WIN32_NT
:
745 p
= "Windows NT x86";
751 TRACE("set environment to %s\n", p
);
754 lpKey
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
755 strlen(p
) + strlen(Drivers
));
756 sprintf( lpKey
, Drivers
, p
);
758 TRACE("%s\n", lpKey
);
760 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, lpKey
, &retval
) !=
764 if(pEnvironment
&& unicode
)
765 HeapFree( GetProcessHeap(), 0, p
);
766 HeapFree( GetProcessHeap(), 0, lpKey
);
771 /*****************************************************************************
772 * AddPrinterW [WINSPOOL.122]
774 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
776 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
780 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
783 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
786 ERR("pName = %s - unsupported\n", debugstr_w(pName
));
787 SetLastError(ERROR_INVALID_PARAMETER
);
791 ERR("Level = %ld, unsupported!\n", Level
);
792 SetLastError(ERROR_INVALID_LEVEL
);
796 SetLastError(ERROR_INVALID_PARAMETER
);
799 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
801 ERR("Can't create Printers key\n");
804 if(RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) ==
806 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
807 RegCloseKey(hkeyPrinter
);
808 RegCloseKey(hkeyPrinters
);
811 hkeyDrivers
= WINSPOOL_OpenDriverReg( NULL
, TRUE
);
813 ERR("Can't create Drivers key\n");
814 RegCloseKey(hkeyPrinters
);
817 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
819 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
820 RegCloseKey(hkeyPrinters
);
821 RegCloseKey(hkeyDrivers
);
822 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
825 RegCloseKey(hkeyDriver
);
826 RegCloseKey(hkeyDrivers
);
828 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
829 FIXME("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
830 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
831 RegCloseKey(hkeyPrinters
);
835 /* See if we can load the driver. We may need the devmode structure anyway
837 size
= DocumentPropertiesW(0, -1, pi
->pPrinterName
, NULL
, NULL
, 0);
839 FIXME("DocumentProperties fails\n");
840 size
= sizeof(DEVMODEW
);
845 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
847 DocumentPropertiesW(0, -1, pi
->pPrinterName
, dmW
, NULL
, DM_OUT_BUFFER
);
850 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
852 FIXME("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
853 SetLastError(ERROR_INVALID_PRINTER_NAME
);
854 RegCloseKey(hkeyPrinters
);
856 HeapFree(GetProcessHeap(), 0, dmW
);
859 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
860 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
861 RegSetValueExW(hkeyPrinter
, DatatypeW
, 0, REG_SZ
, (LPBYTE
)pi
->pDatatype
,
863 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
864 and we support these drivers. NT writes DEVMODEW so somehow
865 we'll need to distinguish between these when we support NT
867 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
868 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
, (LPBYTE
)dmA
,
869 dmA
->dmSize
+ dmA
->dmDriverExtra
);
870 HeapFree(GetProcessHeap(), 0, dmA
);
872 HeapFree(GetProcessHeap(), 0, dmW
);
873 RegSetValueExW(hkeyPrinter
, DescriptionW
, 0, REG_SZ
, (LPBYTE
)pi
->pComment
,
875 RegSetValueExW(hkeyPrinter
, LocationW
, 0, REG_SZ
, (LPBYTE
)pi
->pLocation
,
877 RegSetValueExW(hkeyPrinter
, NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pPrinterName
, 0);
878 RegSetValueExW(hkeyPrinter
, ParametersW
, 0, REG_SZ
,
879 (LPBYTE
)pi
->pParameters
, 0);
880 RegSetValueExW(hkeyPrinter
, PortW
, 0, REG_SZ
, (LPBYTE
)pi
->pPortName
, 0);
881 RegSetValueExW(hkeyPrinter
, Print_ProcessorW
, 0, REG_SZ
,
882 (LPBYTE
)pi
->pPrintProcessor
, 0);
883 RegSetValueExW(hkeyPrinter
, Printer_DriverW
, 0, REG_SZ
,
884 (LPBYTE
)pi
->pDriverName
, 0);
885 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
886 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
887 RegSetValueExW(hkeyPrinter
, Separator_FileW
, 0, REG_SZ
,
888 (LPBYTE
)pi
->pSepFile
, 0);
889 RegSetValueExW(hkeyPrinter
, Share_NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pShareName
,
891 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
892 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
893 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
894 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
895 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
896 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
898 RegCloseKey(hkeyPrinter
);
899 RegCloseKey(hkeyPrinters
);
900 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
901 ERR("OpenPrinter failing\n");
907 /*****************************************************************************
908 * AddPrinterA [WINSPOOL.117]
910 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
913 PRINTER_INFO_2W
*piW
;
914 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
917 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
919 ERR("Level = %ld, unsupported!\n", Level
);
920 SetLastError(ERROR_INVALID_LEVEL
);
923 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
924 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
926 ret
= AddPrinterW(pNameW
, Level
, (LPBYTE
)piW
);
928 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
929 HeapFree(GetProcessHeap(),0,pNameW
);
934 /*****************************************************************************
935 * ClosePrinter [WINSPOOL.126]
937 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
939 int i
= (int)hPrinter
;
941 TRACE("Handle %d\n", hPrinter
);
943 if ((i
<= 0) || (i
> nb_printers
)) return FALSE
;
944 HeapFree( GetProcessHeap(), 0, printer_array
[i
- 1] );
945 printer_array
[i
- 1] = NULL
;
949 /*****************************************************************************
950 * DeleteFormA [WINSPOOL.133]
952 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
954 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
958 /*****************************************************************************
959 * DeleteFormW [WINSPOOL.134]
961 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
963 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
967 /*****************************************************************************
968 * DeletePrinter [WINSPOOL.143]
970 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
972 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
975 if(!lpNameW
) return FALSE
;
976 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
978 ERR("Can't open Printers key\n");
982 /* This should use a recursive delete see Q142491 or SHDeleteKey */
983 if(RegDeleteKeyW(hkeyPrinters
, lpNameW
) == ERROR_SUCCESS
) {
984 SetLastError(ERROR_PRINTER_NOT_FOUND
); /* ?? */
985 RegCloseKey(hkeyPrinters
);
989 ClosePrinter(hPrinter
);
993 /*****************************************************************************
994 * SetPrinterA [WINSPOOL.211]
996 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
999 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
1003 /*****************************************************************************
1004 * SetJobA [WINSPOOL.209]
1006 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1007 LPBYTE pJob
, DWORD Command
)
1009 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1014 /*****************************************************************************
1015 * SetJobW [WINSPOOL.210]
1017 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1018 LPBYTE pJob
, DWORD Command
)
1020 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1025 /*****************************************************************************
1026 * GetFormA [WINSPOOL.181]
1028 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1029 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1031 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1032 Level
,pForm
,cbBuf
,pcbNeeded
);
1036 /*****************************************************************************
1037 * GetFormW [WINSPOOL.182]
1039 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1040 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1042 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1043 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1047 /*****************************************************************************
1048 * SetFormA [WINSPOOL.207]
1050 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1053 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1057 /*****************************************************************************
1058 * SetFormW [WINSPOOL.208]
1060 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1063 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1067 /*****************************************************************************
1068 * ReadPrinter [WINSPOOL.202]
1070 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1071 LPDWORD pNoBytesRead
)
1073 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1077 /*****************************************************************************
1078 * ResetPrinterA [WINSPOOL.203]
1080 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1082 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1086 /*****************************************************************************
1087 * ResetPrinterW [WINSPOOL.204]
1089 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1091 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1095 /*****************************************************************************
1096 * WINSPOOL_GetDWORDFromReg
1098 * Return DWORD associated with ValueName from hkey.
1100 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
1102 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
1105 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
1107 if(ret
!= ERROR_SUCCESS
) {
1108 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
1111 if(type
!= REG_DWORD
) {
1112 ERR("Got type %ld\n", type
);
1118 /*****************************************************************************
1119 * WINSPOOL_GetStringFromReg
1121 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1122 * String is stored either as unicode or ascii.
1123 * Bit of a hack here to get the ValueName if we want ascii.
1125 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1126 DWORD buflen
, DWORD
*needed
,
1129 DWORD sz
= buflen
, type
;
1133 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1135 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1136 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1137 HeapFree(GetProcessHeap(),0,ValueNameA
);
1139 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1140 WARN("Got ret = %ld\n", ret
);
1148 /*****************************************************************************
1149 * WINSPOOL_GetDevModeFromReg
1151 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1152 * DevMode is stored either as unicode or ascii.
1154 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1156 DWORD buflen
, DWORD
*needed
,
1159 DWORD sz
= buflen
, type
;
1162 if (ptr
) memset(ptr
, 0, sizeof(DEVMODEA
));
1163 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1164 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1165 if (sz
< sizeof(DEVMODEA
))
1167 ERR("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName
),sz
);
1168 sz
= sizeof(DEVMODEA
);
1170 /* ensures that dmSize is not erratically bogus if registry is invalid */
1171 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1172 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1174 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1176 DEVMODEW
*dmW
= DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA
*)ptr
);
1177 memcpy(ptr
, dmW
, sz
);
1178 HeapFree(GetProcessHeap(),0,dmW
);
1185 /*********************************************************************
1186 * WINSPOOL_GetPrinter_2
1188 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1189 * The strings are either stored as unicode or ascii.
1191 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1192 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1195 DWORD size
, left
= cbBuf
;
1196 BOOL space
= (cbBuf
> 0);
1201 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1203 if(space
&& size
<= left
) {
1204 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1211 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1213 if(space
&& size
<= left
) {
1214 pi2
->pShareName
= (LPWSTR
)ptr
;
1221 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1223 if(space
&& size
<= left
) {
1224 pi2
->pPortName
= (LPWSTR
)ptr
;
1231 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1233 if(space
&& size
<= left
) {
1234 pi2
->pDriverName
= (LPWSTR
)ptr
;
1241 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1243 if(space
&& size
<= left
) {
1244 pi2
->pComment
= (LPWSTR
)ptr
;
1251 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1253 if(space
&& size
<= left
) {
1254 pi2
->pLocation
= (LPWSTR
)ptr
;
1261 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1263 if(space
&& size
<= left
) {
1264 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1271 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1273 if(space
&& size
<= left
) {
1274 pi2
->pSepFile
= (LPWSTR
)ptr
;
1281 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1283 if(space
&& size
<= left
) {
1284 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1291 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1293 if(space
&& size
<= left
) {
1294 pi2
->pDatatype
= (LPWSTR
)ptr
;
1301 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1303 if(space
&& size
<= left
) {
1304 pi2
->pParameters
= (LPWSTR
)ptr
;
1312 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1313 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1314 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1315 "Default Priority");
1316 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1317 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1320 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1321 memset(pi2
, 0, sizeof(*pi2
));
1326 /*********************************************************************
1327 * WINSPOOL_GetPrinter_4
1329 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1331 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1332 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1335 DWORD size
, left
= cbBuf
;
1336 BOOL space
= (cbBuf
> 0);
1341 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1343 if(space
&& size
<= left
) {
1344 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1352 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1355 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1356 memset(pi4
, 0, sizeof(*pi4
));
1361 /*********************************************************************
1362 * WINSPOOL_GetPrinter_5
1364 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1366 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1367 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1370 DWORD size
, left
= cbBuf
;
1371 BOOL space
= (cbBuf
> 0);
1376 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1378 if(space
&& size
<= left
) {
1379 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1386 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1388 if(space
&& size
<= left
) {
1389 pi5
->pPortName
= (LPWSTR
)ptr
;
1397 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1398 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1400 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1404 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1405 memset(pi5
, 0, sizeof(*pi5
));
1410 /*****************************************************************************
1411 * WINSPOOL_GetPrinter
1413 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1414 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1415 * just a collection of pointers to strings.
1417 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1418 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1421 DWORD size
, needed
= 0;
1423 HKEY hkeyPrinter
, hkeyPrinters
;
1426 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1428 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
1430 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1432 ERR("Can't create Printers key\n");
1435 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
) != ERROR_SUCCESS
)
1437 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
1438 RegCloseKey(hkeyPrinters
);
1439 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1446 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
1448 size
= sizeof(PRINTER_INFO_2W
);
1450 ptr
= pPrinter
+ size
;
1452 memset(pPrinter
, 0, size
);
1457 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
1465 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
1467 size
= sizeof(PRINTER_INFO_4W
);
1469 ptr
= pPrinter
+ size
;
1471 memset(pPrinter
, 0, size
);
1476 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
1485 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
1487 size
= sizeof(PRINTER_INFO_5W
);
1489 ptr
= pPrinter
+ size
;
1491 memset(pPrinter
, 0, size
);
1497 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
1504 FIXME("Unimplemented level %ld\n", Level
);
1505 SetLastError(ERROR_INVALID_LEVEL
);
1506 RegCloseKey(hkeyPrinters
);
1507 RegCloseKey(hkeyPrinter
);
1511 RegCloseKey(hkeyPrinter
);
1512 RegCloseKey(hkeyPrinters
);
1514 TRACE("returing %d needed = %ld\n", ret
, needed
);
1515 if(pcbNeeded
) *pcbNeeded
= needed
;
1517 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1521 /*****************************************************************************
1522 * GetPrinterW [WINSPOOL.194]
1524 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1525 DWORD cbBuf
, LPDWORD pcbNeeded
)
1527 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1531 /*****************************************************************************
1532 * GetPrinterA [WINSPOOL.187]
1534 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1535 DWORD cbBuf
, LPDWORD pcbNeeded
)
1537 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1541 /*****************************************************************************
1542 * WINSPOOL_EnumPrinters
1544 * Implementation of EnumPrintersA|W
1546 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
1547 DWORD dwLevel
, LPBYTE lpbPrinters
,
1548 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1549 LPDWORD lpdwReturned
, BOOL unicode
)
1552 HKEY hkeyPrinters
, hkeyPrinter
;
1553 WCHAR PrinterName
[255];
1554 DWORD needed
= 0, number
= 0;
1555 DWORD used
, i
, left
;
1559 memset(lpbPrinters
, 0, cbBuf
);
1565 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1566 if(dwType
== PRINTER_ENUM_DEFAULT
)
1569 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
1570 FIXME("dwType = %08lx\n", dwType
);
1571 SetLastError(ERROR_INVALID_FLAGS
);
1575 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1577 ERR("Can't create Printers key\n");
1581 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
1582 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
1583 RegCloseKey(hkeyPrinters
);
1584 ERR("Can't query Printers key\n");
1587 TRACE("Found %ld printers\n", number
);
1591 RegCloseKey(hkeyPrinters
);
1593 *lpdwReturned
= number
;
1597 used
= number
* sizeof(PRINTER_INFO_2W
);
1600 used
= number
* sizeof(PRINTER_INFO_4W
);
1603 used
= number
* sizeof(PRINTER_INFO_5W
);
1607 SetLastError(ERROR_INVALID_LEVEL
);
1608 RegCloseKey(hkeyPrinters
);
1611 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
1613 for(i
= 0; i
< number
; i
++) {
1614 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
1616 ERR("Can't enum key number %ld\n", i
);
1617 RegCloseKey(hkeyPrinters
);
1620 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
1621 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
1623 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
1624 RegCloseKey(hkeyPrinters
);
1629 buf
= lpbPrinters
+ used
;
1630 left
= cbBuf
- used
;
1638 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
1639 left
, &needed
, unicode
);
1641 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
1644 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
1645 left
, &needed
, unicode
);
1647 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
1650 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
1651 left
, &needed
, unicode
);
1653 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
1656 ERR("Shouldn't be here!\n");
1657 RegCloseKey(hkeyPrinter
);
1658 RegCloseKey(hkeyPrinters
);
1661 RegCloseKey(hkeyPrinter
);
1663 RegCloseKey(hkeyPrinters
);
1670 memset(lpbPrinters
, 0, cbBuf
);
1671 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1675 *lpdwReturned
= number
;
1676 SetLastError(ERROR_SUCCESS
);
1681 /******************************************************************
1682 * EnumPrintersW [WINSPOOL.175]
1684 * Enumerates the available printers, print servers and print
1685 * providers, depending on the specified flags, name and level.
1689 * If level is set to 1:
1690 * Not implemented yet!
1691 * Returns TRUE with an empty list.
1693 * If level is set to 2:
1694 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1695 * Returns an array of PRINTER_INFO_2 data structures in the
1696 * lpbPrinters buffer. Note that according to MSDN also an
1697 * OpenPrinter should be performed on every remote printer.
1699 * If level is set to 4 (officially WinNT only):
1700 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1701 * Fast: Only the registry is queried to retrieve printer names,
1702 * no connection to the driver is made.
1703 * Returns an array of PRINTER_INFO_4 data structures in the
1704 * lpbPrinters buffer.
1706 * If level is set to 5 (officially WinNT4/Win9x only):
1707 * Fast: Only the registry is queried to retrieve printer names,
1708 * no connection to the driver is made.
1709 * Returns an array of PRINTER_INFO_5 data structures in the
1710 * lpbPrinters buffer.
1712 * If level set to 3 or 6+:
1713 * returns zero (failure!)
1715 * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
1719 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1720 * - Only levels 2, 4 and 5 are implemented at the moment.
1721 * - 16-bit printer drivers are not enumerated.
1722 * - Returned amount of bytes used/needed does not match the real Windoze
1723 * implementation (as in this implementation, all strings are part
1724 * of the buffer, whereas Win32 keeps them somewhere else)
1725 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1728 * - In a regular Wine installation, no registry settings for printers
1729 * exist, which makes this function return an empty list.
1731 BOOL WINAPI
EnumPrintersW(
1732 DWORD dwType
, /* [in] Types of print objects to enumerate */
1733 LPWSTR lpszName
, /* [in] name of objects to enumerate */
1734 DWORD dwLevel
, /* [in] type of printer info structure */
1735 LPBYTE lpbPrinters
, /* [out] buffer which receives info */
1736 DWORD cbBuf
, /* [in] max size of buffer in bytes */
1737 LPDWORD lpdwNeeded
, /* [out] pointer to var: # bytes used/needed */
1738 LPDWORD lpdwReturned
/* [out] number of entries returned */
1741 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
1742 lpdwNeeded
, lpdwReturned
, TRUE
);
1745 /******************************************************************
1746 * EnumPrintersA [WINSPOOL.174]
1749 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
1750 DWORD dwLevel
, LPBYTE lpbPrinters
,
1751 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1752 LPDWORD lpdwReturned
)
1755 LPWSTR lpszNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpszName
);
1757 ret
= WINSPOOL_EnumPrinters(dwType
, lpszNameW
, dwLevel
, lpbPrinters
, cbBuf
,
1758 lpdwNeeded
, lpdwReturned
, FALSE
);
1759 HeapFree(GetProcessHeap(),0,lpszNameW
);
1763 /*****************************************************************************
1764 * WINSPOOL_GetDriverInfoFromReg [internal]
1766 * Enters the information from the registry into the DRIVER_INFO struct
1769 * zero if the printer driver does not exist in the registry
1770 * (only if Level > 1) otherwise nonzero
1772 static BOOL
WINSPOOL_GetDriverInfoFromReg(
1775 LPWSTR pEnvironment
,
1777 LPBYTE ptr
, /* DRIVER_INFO */
1778 LPBYTE pDriverStrings
, /* strings buffer */
1779 DWORD cbBuf
, /* size of string buffer */
1780 LPDWORD pcbNeeded
, /* space needed for str. */
1781 BOOL unicode
) /* type of strings */
1782 { DWORD dw
, size
, tmp
, type
;
1784 LPBYTE strPtr
= pDriverStrings
;
1786 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
1787 debugstr_w(DriverName
), debugstr_w(pEnvironment
),
1788 Level
, ptr
, pDriverStrings
, cbBuf
, unicode
);
1791 *pcbNeeded
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
1792 if (*pcbNeeded
<= cbBuf
)
1793 strcpyW((LPWSTR
)strPtr
, DriverName
);
1795 *pcbNeeded
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0,
1797 if(*pcbNeeded
<= cbBuf
)
1798 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, strPtr
, *pcbNeeded
,
1803 ((PDRIVER_INFO_1W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1807 ((PDRIVER_INFO_3W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1808 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1811 if(RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
) != ERROR_SUCCESS
) {
1812 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName
));
1813 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
1818 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
, &size
) !=
1820 WARN("Can't get Version\n");
1822 ((PDRIVER_INFO_3A
) ptr
)->cVersion
= dw
;
1825 pEnvironment
= DefaultEnvironmentW
;
1827 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
1829 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
1832 if(*pcbNeeded
<= cbBuf
) {
1834 strcpyW((LPWSTR
)strPtr
, pEnvironment
);
1836 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, strPtr
, size
,
1839 ((PDRIVER_INFO_3W
) ptr
)->pEnvironment
= (LPWSTR
)strPtr
;
1840 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1843 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, 0, &size
,
1846 if(*pcbNeeded
<= cbBuf
)
1847 WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, size
, &tmp
,
1850 ((PDRIVER_INFO_3W
) ptr
)->pDriverPath
= (LPWSTR
)strPtr
;
1851 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1854 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, 0, &size
,
1857 if(*pcbNeeded
<= cbBuf
)
1858 WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, size
,
1861 ((PDRIVER_INFO_3W
) ptr
)->pDataFile
= (LPWSTR
)strPtr
;
1862 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1865 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1866 0, &size
, unicode
)) {
1868 if(*pcbNeeded
<= cbBuf
)
1869 WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1870 size
, &tmp
, unicode
);
1872 ((PDRIVER_INFO_3W
) ptr
)->pConfigFile
= (LPWSTR
)strPtr
;
1873 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1877 RegCloseKey(hkeyDriver
);
1878 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1882 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
, 0, &size
,
1885 if(*pcbNeeded
<= cbBuf
)
1886 WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
,
1887 size
, &tmp
, unicode
);
1889 ((PDRIVER_INFO_3W
) ptr
)->pHelpFile
= (LPWSTR
)strPtr
;
1890 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1893 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
, 0,
1896 if(*pcbNeeded
<= cbBuf
)
1897 WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
,
1898 size
, &tmp
, unicode
);
1900 ((PDRIVER_INFO_3W
) ptr
)->pDependentFiles
= (LPWSTR
)strPtr
;
1901 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1904 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
, 0, &size
,
1907 if(*pcbNeeded
<= cbBuf
)
1908 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1909 size
, &tmp
, unicode
);
1911 ((PDRIVER_INFO_3W
) ptr
)->pMonitorName
= (LPWSTR
)strPtr
;
1912 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1915 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, strPtr
, 0, &size
,
1918 if(*pcbNeeded
<= cbBuf
)
1919 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1920 size
, &tmp
, unicode
);
1922 ((PDRIVER_INFO_3W
) ptr
)->pDefaultDataType
= (LPWSTR
)strPtr
;
1923 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1926 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1927 RegCloseKey(hkeyDriver
);
1931 /*****************************************************************************
1932 * WINSPOOL_GetPrinterDriver
1934 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
1935 DWORD Level
, LPBYTE pDriverInfo
,
1936 DWORD cbBuf
, LPDWORD pcbNeeded
,
1940 WCHAR DriverName
[100];
1941 DWORD ret
, type
, size
, needed
= 0;
1943 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDrivers
;
1945 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
1946 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1948 ZeroMemory(pDriverInfo
, cbBuf
);
1950 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
1952 if(Level
< 1 || Level
> 3) {
1953 SetLastError(ERROR_INVALID_LEVEL
);
1956 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1958 ERR("Can't create Printers key\n");
1961 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
)
1963 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
1964 RegCloseKey(hkeyPrinters
);
1965 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1968 size
= sizeof(DriverName
);
1969 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
1970 (LPBYTE
)DriverName
, &size
);
1971 RegCloseKey(hkeyPrinter
);
1972 RegCloseKey(hkeyPrinters
);
1973 if(ret
!= ERROR_SUCCESS
) {
1974 ERR("Can't get DriverName for printer %s\n", debugstr_w(name
));
1978 hkeyDrivers
= WINSPOOL_OpenDriverReg( pEnvironment
, TRUE
);
1980 ERR("Can't create Drivers key\n");
1986 size
= sizeof(DRIVER_INFO_1W
);
1989 size
= sizeof(DRIVER_INFO_2W
);
1992 size
= sizeof(DRIVER_INFO_3W
);
1995 ERR("Invalid level\n");
2000 ptr
= pDriverInfo
+ size
;
2002 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverName
,
2003 pEnvironment
, Level
, pDriverInfo
,
2004 (cbBuf
< size
) ? NULL
: ptr
,
2005 (cbBuf
< size
) ? 0 : cbBuf
- size
,
2006 &needed
, unicode
)) {
2007 RegCloseKey(hkeyDrivers
);
2011 RegCloseKey(hkeyDrivers
);
2013 if(pcbNeeded
) *pcbNeeded
= size
+ needed
;
2014 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2015 if(cbBuf
>= needed
) return TRUE
;
2016 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2020 /*****************************************************************************
2021 * GetPrinterDriverA [WINSPOOL.190]
2023 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
2024 DWORD Level
, LPBYTE pDriverInfo
,
2025 DWORD cbBuf
, LPDWORD pcbNeeded
)
2028 LPWSTR pEnvW
= HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment
);
2029 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pEnvW
, Level
, pDriverInfo
,
2030 cbBuf
, pcbNeeded
, FALSE
);
2031 HeapFree(GetProcessHeap(),0,pEnvW
);
2034 /*****************************************************************************
2035 * GetPrinterDriverW [WINSPOOL.193]
2037 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
2038 DWORD Level
, LPBYTE pDriverInfo
,
2039 DWORD cbBuf
, LPDWORD pcbNeeded
)
2041 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
2042 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
2045 /*****************************************************************************
2046 * GetPrinterDriverDirectoryA [WINSPOOL.191]
2048 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
2049 DWORD Level
, LPBYTE pDriverDirectory
,
2050 DWORD cbBuf
, LPDWORD pcbNeeded
)
2054 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName
, pEnvironment
, Level
,
2055 pDriverDirectory
, cbBuf
, pcbNeeded
);
2057 FIXME("pName = `%s' - unsupported\n", pName
);
2058 SetLastError(ERROR_INVALID_PARAMETER
);
2061 if(pEnvironment
!= NULL
) {
2062 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment
);
2063 SetLastError(ERROR_INVALID_ENVIRONMENT
);
2066 if(Level
!= 1) /* win95 ignores this so we just carry on */
2067 WARN("Level = %ld - assuming 1\n", Level
);
2069 /* FIXME should read from registry */
2070 needed
= GetSystemDirectoryA(pDriverDirectory
, cbBuf
);
2073 *pcbNeeded
= needed
;
2074 if(needed
> cbBuf
) {
2075 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2082 /*****************************************************************************
2083 * GetPrinterDriverDirectoryW [WINSPOOL.192]
2085 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
2086 DWORD Level
, LPBYTE pDriverDirectory
,
2087 DWORD cbBuf
, LPDWORD pcbNeeded
)
2089 LPSTR pNameA
= NULL
, pEnvironmentA
= NULL
;
2093 pNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pName
);
2095 pEnvironmentA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
);
2096 ret
= GetPrinterDriverDirectoryA( pNameA
, pEnvironmentA
, Level
,
2097 pDriverDirectory
, cbBuf
, pcbNeeded
);
2099 HeapFree( GetProcessHeap(), 0, pNameA
);
2101 HeapFree( GetProcessHeap(), 0, pEnvironmentA
);
2106 /*****************************************************************************
2107 * AddPrinterDriverA [WINSPOOL.120]
2109 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
2112 HKEY hkeyDrivers
, hkeyName
;
2114 TRACE("(%s,%ld,%p)\n",pName
,level
,pDriverInfo
);
2116 if(level
!= 2 && level
!= 3) {
2117 SetLastError(ERROR_INVALID_LEVEL
);
2121 FIXME("pName= `%s' - unsupported\n", pName
);
2122 SetLastError(ERROR_INVALID_PARAMETER
);
2126 WARN("pDriverInfo == NULL");
2127 SetLastError(ERROR_INVALID_PARAMETER
);
2132 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
2134 memset(&di3
, 0, sizeof(di3
));
2135 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
2138 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
2140 SetLastError(ERROR_INVALID_PARAMETER
);
2143 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
2144 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
2145 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
2146 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
2148 hkeyDrivers
= WINSPOOL_OpenDriverReg(di3
.pEnvironment
, FALSE
);
2151 ERR("Can't create Drivers key\n");
2155 if(level
== 2) { /* apparently can't overwrite with level2 */
2156 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2157 RegCloseKey(hkeyName
);
2158 RegCloseKey(hkeyDrivers
);
2159 WARN("Trying to create existing printer driver `%s'\n", di3
.pName
);
2160 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2164 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2165 RegCloseKey(hkeyDrivers
);
2166 ERR("Can't create Name key\n");
2169 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2171 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2172 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2173 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2175 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2176 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2177 di3
.pDependentFiles
, 0);
2178 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2179 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2180 RegCloseKey(hkeyName
);
2181 RegCloseKey(hkeyDrivers
);
2185 /*****************************************************************************
2186 * AddPrinterDriverW [WINSPOOL.121]
2188 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2191 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2197 /*****************************************************************************
2198 * PrinterProperties [WINSPOOL.201]
2200 * Displays a dialog to set the properties of the printer.
2203 * nonzero on success or zero on failure
2206 * implemented as stub only
2208 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* [in] handle to parent window */
2209 HANDLE hPrinter
/* [in] handle to printer object */
2211 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
2212 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2216 /*****************************************************************************
2217 * EnumJobsA [WINSPOOL.162]
2220 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2221 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2225 if(pcbNeeded
) *pcbNeeded
= 0;
2226 if(pcReturned
) *pcReturned
= 0;
2231 /*****************************************************************************
2232 * EnumJobsW [WINSPOOL.163]
2235 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2236 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2240 if(pcbNeeded
) *pcbNeeded
= 0;
2241 if(pcReturned
) *pcReturned
= 0;
2245 /*****************************************************************************
2246 * WINSPOOL_EnumPrinterDrivers [internal]
2248 * Delivers information about all printer drivers installed on the
2249 * localhost or a given server
2252 * nonzero on success or zero on failure. If the buffer for the returned
2253 * information is too small the function will return an error
2256 * - only implemented for localhost, foreign hosts will return an error
2258 static BOOL
WINSPOOL_EnumPrinterDrivers(LPWSTR pName
, LPWSTR pEnvironment
,
2259 DWORD Level
, LPBYTE pDriverInfo
,
2260 DWORD cbBuf
, LPDWORD pcbNeeded
,
2261 LPDWORD pcReturned
, BOOL unicode
)
2264 DWORD i
, needed
, number
= 0, size
= 0;
2265 WCHAR DriverNameW
[255];
2268 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2269 debugstr_w(pName
), debugstr_w(pEnvironment
),
2270 Level
, pDriverInfo
, cbBuf
, unicode
);
2272 /* check for local drivers */
2274 ERR("remote drivers unsupported! Current remote host is %s\n",
2279 /* check input parameter */
2280 if((Level
< 1) || (Level
> 3)) {
2281 ERR("unsupported level %ld \n", Level
);
2285 /* initialize return values */
2287 memset( pDriverInfo
, 0, cbBuf
);
2291 hkeyDrivers
= WINSPOOL_OpenDriverReg(pEnvironment
, TRUE
);
2293 ERR("Can't open Drivers key\n");
2297 if(RegQueryInfoKeyA(hkeyDrivers
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2298 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2299 RegCloseKey(hkeyDrivers
);
2300 ERR("Can't query Drivers key\n");
2303 TRACE("Found %ld Drivers\n", number
);
2305 /* get size of single struct
2306 * unicode and ascii structure have the same size
2310 size
= sizeof(DRIVER_INFO_1A
);
2313 size
= sizeof(DRIVER_INFO_2A
);
2316 size
= sizeof(DRIVER_INFO_3A
);
2320 /* calculate required buffer size */
2321 *pcbNeeded
= size
* number
;
2323 for( i
= 0, ptr
= (pDriverInfo
&& (cbBuf
>= size
)) ? pDriverInfo
: NULL
;
2325 i
++, ptr
= (ptr
&& (cbBuf
>= size
* i
)) ? ptr
+ size
: NULL
) {
2326 if(RegEnumKeyW(hkeyDrivers
, i
, DriverNameW
, sizeof(DriverNameW
))
2328 ERR("Can't enum key number %ld\n", i
);
2329 RegCloseKey(hkeyDrivers
);
2332 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverNameW
,
2333 pEnvironment
, Level
, ptr
,
2334 (cbBuf
< *pcbNeeded
) ? NULL
: pDriverInfo
+ *pcbNeeded
,
2335 (cbBuf
< *pcbNeeded
) ? 0 : cbBuf
- *pcbNeeded
,
2336 &needed
, unicode
)) {
2337 RegCloseKey(hkeyDrivers
);
2340 (*pcbNeeded
) += needed
;
2343 RegCloseKey(hkeyDrivers
);
2345 if(cbBuf
< *pcbNeeded
){
2346 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2353 /*****************************************************************************
2354 * EnumPrinterDriversW [WINSPOOL.173]
2356 * see function EnumPrinterDrivers for RETURNS, BUGS
2358 BOOL WINAPI
EnumPrinterDriversW(LPWSTR pName
, LPWSTR pEnvironment
, DWORD Level
,
2359 LPBYTE pDriverInfo
, DWORD cbBuf
,
2360 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2362 return WINSPOOL_EnumPrinterDrivers(pName
, pEnvironment
, Level
, pDriverInfo
,
2363 cbBuf
, pcbNeeded
, pcReturned
, TRUE
);
2366 /*****************************************************************************
2367 * EnumPrinterDriversA [WINSPOOL.172]
2369 * see function EnumPrinterDrivers for RETURNS, BUGS
2371 BOOL WINAPI
EnumPrinterDriversA(LPSTR pName
, LPSTR pEnvironment
, DWORD Level
,
2372 LPBYTE pDriverInfo
, DWORD cbBuf
,
2373 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2375 WCHAR
*pNameW
= NULL
, *pEnvironmentW
= NULL
;
2378 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
2380 pEnvironmentW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment
);
2382 ret
= WINSPOOL_EnumPrinterDrivers(pNameW
, pEnvironmentW
, Level
, pDriverInfo
,
2383 cbBuf
, pcbNeeded
, pcReturned
, FALSE
);
2385 HeapFree(GetProcessHeap(), 0, pNameW
);
2387 HeapFree(GetProcessHeap(), 0, pEnvironmentW
);
2393 /******************************************************************************
2394 * EnumPortsA (WINSPOOL.166)
2396 BOOL WINAPI
EnumPortsA(LPSTR name
,DWORD level
,LPBYTE ports
,DWORD bufsize
,
2397 LPDWORD bufneeded
,LPDWORD bufreturned
)
2399 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name
,level
,ports
,bufsize
,bufneeded
,bufreturned
);
2403 /******************************************************************************
2404 * SetPrinterDataExA (WINSPOOL)
2406 DWORD WINAPI
SetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2407 LPSTR pValueName
, DWORD Type
,
2408 LPBYTE pData
, DWORD cbData
)
2410 HKEY hkeyPrinter
, hkeySubkey
;
2413 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_a(pKeyName
),
2414 debugstr_a(pValueName
), Type
, pData
, cbData
);
2416 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2420 if((ret
= RegCreateKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2422 ERR("Can't create subkey %s\n", debugstr_a(pKeyName
));
2423 RegCloseKey(hkeyPrinter
);
2426 ret
= RegSetValueExA(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2427 RegCloseKey(hkeySubkey
);
2428 RegCloseKey(hkeyPrinter
);
2432 /******************************************************************************
2433 * SetPrinterDataExW (WINSPOOL)
2435 DWORD WINAPI
SetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
2436 LPWSTR pValueName
, DWORD Type
,
2437 LPBYTE pData
, DWORD cbData
)
2439 HKEY hkeyPrinter
, hkeySubkey
;
2442 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_w(pKeyName
),
2443 debugstr_w(pValueName
), Type
, pData
, cbData
);
2445 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2449 if((ret
= RegCreateKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2451 ERR("Can't create subkey %s\n", debugstr_w(pKeyName
));
2452 RegCloseKey(hkeyPrinter
);
2455 ret
= RegSetValueExW(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2456 RegCloseKey(hkeySubkey
);
2457 RegCloseKey(hkeyPrinter
);
2461 /******************************************************************************
2462 * SetPrinterDataA (WINSPOOL)
2464 DWORD WINAPI
SetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, DWORD Type
,
2465 LPBYTE pData
, DWORD cbData
)
2467 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
,
2471 /******************************************************************************
2472 * SetPrinterDataW (WINSPOOL)
2474 DWORD WINAPI
SetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, DWORD Type
,
2475 LPBYTE pData
, DWORD cbData
)
2477 return SetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, Type
,
2481 /******************************************************************************
2482 * GetPrinterDataExA (WINSPOOL)
2484 DWORD WINAPI
GetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2485 LPSTR pValueName
, LPDWORD pType
,
2486 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2488 HKEY hkeyPrinter
, hkeySubkey
;
2491 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
2492 debugstr_a(pKeyName
), debugstr_a(pValueName
), pType
, pData
, nSize
,
2495 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2499 if((ret
= RegOpenKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2501 WARN("Can't open subkey %s\n", debugstr_a(pKeyName
));
2502 RegCloseKey(hkeyPrinter
);
2506 ret
= RegQueryValueExA(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
2507 RegCloseKey(hkeySubkey
);
2508 RegCloseKey(hkeyPrinter
);
2512 /******************************************************************************
2513 * GetPrinterDataExW (WINSPOOL)
2515 DWORD WINAPI
GetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
2516 LPWSTR pValueName
, LPDWORD pType
,
2517 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2519 HKEY hkeyPrinter
, hkeySubkey
;
2522 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
2523 debugstr_w(pKeyName
), debugstr_w(pValueName
), pType
, pData
, nSize
,
2526 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2530 if((ret
= RegOpenKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2532 WARN("Can't open subkey %s\n", debugstr_w(pKeyName
));
2533 RegCloseKey(hkeyPrinter
);
2537 ret
= RegQueryValueExW(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
2538 RegCloseKey(hkeySubkey
);
2539 RegCloseKey(hkeyPrinter
);
2543 /******************************************************************************
2544 * GetPrinterDataA (WINSPOOL)
2546 DWORD WINAPI
GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
,
2547 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2549 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
,
2550 pData
, nSize
, pcbNeeded
);
2553 /******************************************************************************
2554 * GetPrinterDataW (WINSPOOL)
2556 DWORD WINAPI
GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
,
2557 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2559 return GetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, pType
,
2560 pData
, nSize
, pcbNeeded
);
2563 /*******************************************************************************
2564 * EnumPrinterDataExW [WINSPOOL.197]
2566 DWORD WINAPI
EnumPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
,
2567 LPBYTE pEnumValues
, DWORD cbEnumValues
,
2568 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
2570 HKEY hkPrinter
, hkSubKey
;
2571 DWORD r
, ret
, dwIndex
, cValues
, cbMaxValueNameLen
,
2572 cbValueNameLen
, cbMaxValueLen
, cbValueLen
,
2577 PPRINTER_ENUM_VALUESW ppev
;
2579 TRACE ("%08x %s\n", hPrinter
, debugstr_w (pKeyName
));
2581 if (pKeyName
== NULL
|| *pKeyName
== 0)
2582 return ERROR_INVALID_PARAMETER
;
2584 ret
= WINSPOOL_GetOpenedPrinterRegKey (hPrinter
, &hkPrinter
);
2585 if (ret
!= ERROR_SUCCESS
)
2587 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%08x) returned %li\n",
2592 ret
= RegOpenKeyExW (hkPrinter
, pKeyName
, 0, KEY_READ
, &hkSubKey
);
2593 if (ret
!= ERROR_SUCCESS
)
2595 r
= RegCloseKey (hkPrinter
);
2596 if (r
!= ERROR_SUCCESS
)
2597 WARN ("RegCloseKey returned %li\n", r
);
2598 TRACE ("RegOpenKeyExW (%08x, %s) returned %li\n", hPrinter
,
2599 debugstr_w (pKeyName
), ret
);
2603 ret
= RegCloseKey (hkPrinter
);
2604 if (ret
!= ERROR_SUCCESS
)
2606 ERR ("RegCloseKey returned %li\n", ret
);
2607 r
= RegCloseKey (hkSubKey
);
2608 if (r
!= ERROR_SUCCESS
)
2609 WARN ("RegCloseKey returned %li\n", r
);
2613 ret
= RegQueryInfoKeyW (hkSubKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
2614 &cValues
, &cbMaxValueNameLen
, &cbMaxValueLen
, NULL
, NULL
);
2615 if (ret
!= ERROR_SUCCESS
)
2617 r
= RegCloseKey (hkSubKey
);
2618 if (r
!= ERROR_SUCCESS
)
2619 WARN ("RegCloseKey returned %li\n", r
);
2620 TRACE ("RegQueryInfoKeyW (%08x) returned %li\n", hkSubKey
, ret
);
2624 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
2625 "cbMaxValueLen = %li\n", cValues
, cbMaxValueNameLen
, cbMaxValueLen
);
2627 if (cValues
== 0) /* empty key */
2629 r
= RegCloseKey (hkSubKey
);
2630 if (r
!= ERROR_SUCCESS
)
2631 WARN ("RegCloseKey returned %li\n", r
);
2632 *pcbEnumValues
= *pnEnumValues
= 0;
2633 return ERROR_SUCCESS
;
2636 ++cbMaxValueNameLen
; /* allow for trailing '\0' */
2638 hHeap
= GetProcessHeap ();
2639 if (hHeap
== (HANDLE
) NULL
)
2641 ERR ("GetProcessHeap failed\n");
2642 r
= RegCloseKey (hkSubKey
);
2643 if (r
!= ERROR_SUCCESS
)
2644 WARN ("RegCloseKey returned %li\n", r
);
2645 return ERROR_OUTOFMEMORY
;
2648 lpValueName
= HeapAlloc (hHeap
, 0, cbMaxValueNameLen
* sizeof (WCHAR
));
2649 if (lpValueName
== NULL
)
2651 ERR ("Failed to allocate %li bytes from process heap\n",
2652 cbMaxValueNameLen
* sizeof (WCHAR
));
2653 r
= RegCloseKey (hkSubKey
);
2654 if (r
!= ERROR_SUCCESS
)
2655 WARN ("RegCloseKey returned %li\n", r
);
2656 return ERROR_OUTOFMEMORY
;
2659 lpValue
= HeapAlloc (hHeap
, 0, cbMaxValueLen
);
2660 if (lpValue
== NULL
)
2662 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen
);
2663 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2664 WARN ("HeapFree failed with code %li\n", GetLastError ());
2665 r
= RegCloseKey (hkSubKey
);
2666 if (r
!= ERROR_SUCCESS
)
2667 WARN ("RegCloseKey returned %li\n", r
);
2668 return ERROR_OUTOFMEMORY
;
2671 TRACE ("pass 1: calculating buffer required for all names and values\n");
2673 cbBufSize
= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
2675 TRACE ("%li bytes required for %li headers\n", cbBufSize
, cValues
);
2677 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
2679 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
2680 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
2681 NULL
, NULL
, lpValue
, &cbValueLen
);
2682 if (ret
!= ERROR_SUCCESS
)
2684 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2685 WARN ("HeapFree failed with code %li\n", GetLastError ());
2686 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2687 WARN ("HeapFree failed with code %li\n", GetLastError ());
2688 r
= RegCloseKey (hkSubKey
);
2689 if (r
!= ERROR_SUCCESS
)
2690 WARN ("RegCloseKey returned %li\n", r
);
2691 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
2695 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
2696 debugstr_w (lpValueName
), dwIndex
,
2697 (cbValueNameLen
+ 1) * sizeof (WCHAR
), cbValueLen
);
2699 cbBufSize
+= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
2700 cbBufSize
+= cbValueLen
;
2703 TRACE ("%li bytes required for all %li values\n", cbBufSize
, cValues
);
2705 *pcbEnumValues
= cbBufSize
;
2706 *pnEnumValues
= cValues
;
2708 if (cbEnumValues
< cbBufSize
) /* buffer too small */
2710 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2711 WARN ("HeapFree failed with code %li\n", GetLastError ());
2712 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2713 WARN ("HeapFree failed with code %li\n", GetLastError ());
2714 r
= RegCloseKey (hkSubKey
);
2715 if (r
!= ERROR_SUCCESS
)
2716 WARN ("RegCloseKey returned %li\n", r
);
2717 TRACE ("%li byte buffer is not large enough\n", cbEnumValues
);
2718 return ERROR_MORE_DATA
;
2721 TRACE ("pass 2: copying all names and values to buffer\n");
2723 ppev
= (PPRINTER_ENUM_VALUESW
) pEnumValues
; /* array of structs */
2724 pEnumValues
+= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
2726 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
2728 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
2729 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
2730 NULL
, &dwType
, lpValue
, &cbValueLen
);
2731 if (ret
!= ERROR_SUCCESS
)
2733 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2734 WARN ("HeapFree failed with code %li\n", GetLastError ());
2735 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2736 WARN ("HeapFree failed with code %li\n", GetLastError ());
2737 r
= RegCloseKey (hkSubKey
);
2738 if (r
!= ERROR_SUCCESS
)
2739 WARN ("RegCloseKey returned %li\n", r
);
2740 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
2744 cbValueNameLen
= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
2745 memcpy (pEnumValues
, lpValueName
, cbValueNameLen
);
2746 ppev
[dwIndex
].pValueName
= (LPWSTR
) pEnumValues
;
2747 pEnumValues
+= cbValueNameLen
;
2749 /* return # of *bytes* (including trailing \0), not # of chars */
2750 ppev
[dwIndex
].cbValueName
= cbValueNameLen
;
2752 ppev
[dwIndex
].dwType
= dwType
;
2754 memcpy (pEnumValues
, lpValue
, cbValueLen
);
2755 ppev
[dwIndex
].pData
= pEnumValues
;
2756 pEnumValues
+= cbValueLen
;
2758 ppev
[dwIndex
].cbData
= cbValueLen
;
2760 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
2761 debugstr_w (lpValueName
), dwIndex
, cbValueNameLen
, cbValueLen
);
2764 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2766 ret
= GetLastError ();
2767 ERR ("HeapFree failed with code %li\n", ret
);
2768 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2769 WARN ("HeapFree failed with code %li\n", GetLastError ());
2770 r
= RegCloseKey (hkSubKey
);
2771 if (r
!= ERROR_SUCCESS
)
2772 WARN ("RegCloseKey returned %li\n", r
);
2776 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2778 ret
= GetLastError ();
2779 ERR ("HeapFree failed with code %li\n", ret
);
2780 r
= RegCloseKey (hkSubKey
);
2781 if (r
!= ERROR_SUCCESS
)
2782 WARN ("RegCloseKey returned %li\n", r
);
2786 ret
= RegCloseKey (hkSubKey
);
2787 if (ret
!= ERROR_SUCCESS
)
2789 ERR ("RegCloseKey returned %li\n", ret
);
2793 return ERROR_SUCCESS
;
2796 /*******************************************************************************
2797 * EnumPrinterDataExA [WINSPOOL.196]
2799 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
2800 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
2801 * what Windows 2000 SP1 does.
2804 DWORD WINAPI
EnumPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
,
2805 LPBYTE pEnumValues
, DWORD cbEnumValues
,
2806 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
2810 DWORD ret
, dwIndex
, dwBufSize
;
2814 TRACE ("%08x %s\n", hPrinter
, pKeyName
);
2816 if (pKeyName
== NULL
|| *pKeyName
== 0)
2817 return ERROR_INVALID_PARAMETER
;
2819 len
= MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, NULL
, 0);
2822 ret
= GetLastError ();
2823 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
2827 hHeap
= GetProcessHeap ();
2828 if (hHeap
== (HANDLE
) NULL
)
2830 ERR ("GetProcessHeap failed\n");
2831 return ERROR_OUTOFMEMORY
;
2834 pKeyNameW
= HeapAlloc (hHeap
, 0, len
* sizeof (WCHAR
));
2835 if (pKeyNameW
== NULL
)
2837 ERR ("Failed to allocate %li bytes from process heap\n",
2838 (LONG
) len
* sizeof (WCHAR
));
2839 return ERROR_OUTOFMEMORY
;
2842 if (MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, pKeyNameW
, len
) == 0)
2844 ret
= GetLastError ();
2845 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
2846 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
2847 WARN ("HeapFree failed with code %li\n", GetLastError ());
2851 ret
= EnumPrinterDataExW (hPrinter
, pKeyNameW
, pEnumValues
, cbEnumValues
,
2852 pcbEnumValues
, pnEnumValues
);
2853 if (ret
!= ERROR_SUCCESS
)
2855 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
2856 WARN ("HeapFree failed with code %li\n", GetLastError ());
2857 TRACE ("EnumPrinterDataExW returned %li\n", ret
);
2861 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
2863 ret
= GetLastError ();
2864 ERR ("HeapFree failed with code %li\n", ret
);
2868 if (*pnEnumValues
== 0) /* empty key */
2869 return ERROR_SUCCESS
;
2872 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
2874 PPRINTER_ENUM_VALUESW ppev
=
2875 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
2877 if (dwBufSize
< ppev
->cbValueName
)
2878 dwBufSize
= ppev
->cbValueName
;
2880 if (dwBufSize
< ppev
->cbData
&& (ppev
->dwType
== REG_SZ
||
2881 ppev
->dwType
== REG_EXPAND_SZ
|| ppev
->dwType
== REG_MULTI_SZ
))
2882 dwBufSize
= ppev
->cbData
;
2885 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize
);
2887 pBuffer
= HeapAlloc (hHeap
, 0, dwBufSize
);
2888 if (pBuffer
== NULL
)
2890 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize
);
2891 return ERROR_OUTOFMEMORY
;
2894 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
2896 PPRINTER_ENUM_VALUESW ppev
=
2897 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
2899 len
= WideCharToMultiByte (CP_ACP
, 0, ppev
->pValueName
,
2900 ppev
->cbValueName
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
,
2904 ret
= GetLastError ();
2905 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
2906 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
2907 WARN ("HeapFree failed with code %li\n", GetLastError ());
2911 memcpy (ppev
->pValueName
, pBuffer
, len
);
2913 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
2915 if (ppev
->dwType
!= REG_SZ
&& ppev
->dwType
!= REG_EXPAND_SZ
&&
2916 ppev
->dwType
!= REG_MULTI_SZ
)
2919 len
= WideCharToMultiByte (CP_ACP
, 0, (LPWSTR
) ppev
->pData
,
2920 ppev
->cbData
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
, NULL
);
2923 ret
= GetLastError ();
2924 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
2925 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
2926 WARN ("HeapFree failed with code %li\n", GetLastError ());
2930 memcpy (ppev
->pData
, pBuffer
, len
);
2932 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
2933 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
2936 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
2938 ret
= GetLastError ();
2939 ERR ("HeapFree failed with code %li\n", ret
);
2943 return ERROR_SUCCESS
;