4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
7 * Copyright 1999, 2000 Huw D M Davies
19 #include "wine/windef16.h"
20 #include "wine/unicode.h"
21 #include "debugtools.h"
25 DEFAULT_DEBUG_CHANNEL(winspool
);
27 static LPWSTR
*printer_array
;
28 static int nb_printers
;
30 static DWORD
WINAPI (*GDI_CallDeviceCapabilities16
)( LPCSTR lpszDevice
, LPCSTR lpszPort
,
31 WORD fwCapability
, LPSTR lpszOutput
,
33 static INT
WINAPI (*GDI_CallExtDeviceMode16
)( HWND hwnd
, LPDEVMODEA lpdmOutput
,
34 LPSTR lpszDevice
, LPSTR lpszPort
,
35 LPDEVMODEA lpdmInput
, LPSTR lpszProfile
,
38 static char Printers
[] =
39 "System\\CurrentControlSet\\control\\Print\\Printers\\";
40 static char Drivers
[] =
41 "System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
43 static WCHAR DefaultEnvironmentW
[] = {'W','i','n','e',0};
45 static WCHAR Configuration_FileW
[] = {'C','o','n','f','i','g','u','r','a','t',
46 'i','o','n',' ','F','i','l','e',0};
47 static WCHAR DatatypeW
[] = {'D','a','t','a','t','y','p','e',0};
48 static WCHAR Data_FileW
[] = {'D','a','t','a',' ','F','i','l','e',0};
49 static WCHAR Default_DevModeW
[] = {'D','e','f','a','u','l','t',' ','D','e','v',
51 static WCHAR Dependent_FilesW
[] = {'D','e','p','e','n','d','e','n','t',' ','F',
53 static WCHAR DescriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
54 static WCHAR DriverW
[] = {'D','r','i','v','e','r',0};
55 static WCHAR Help_FileW
[] = {'H','e','l','p',' ','F','i','l','e',0};
56 static WCHAR LocationW
[] = {'L','o','c','a','t','i','o','n',0};
57 static WCHAR MonitorW
[] = {'M','o','n','i','t','o','r',0};
58 static WCHAR NameW
[] = {'N','a','m','e',0};
59 static WCHAR ParametersW
[] = {'P','a','r','a','m','e','t','e','r','s',0};
60 static WCHAR PortW
[] = {'P','o','r','t',0};
61 static WCHAR Print_ProcessorW
[] = {'P','r','i','n','t',' ','P','r','o','c','e',
63 static WCHAR Printer_DriverW
[] = {'P','r','i','n','t','e','r',' ','D','r','i',
65 static WCHAR PrinterDriverDataW
[] = {'P','r','i','n','t','e','r','D','r','i',
66 'v','e','r','D','a','t','a',0};
67 static WCHAR Separator_FileW
[] = {'S','e','p','a','r','a','t','o','r',' ','F',
69 static WCHAR Share_NameW
[] = {'S','h','a','r','e',' ','N','a','m','e',0};
70 static WCHAR WinPrintW
[] = {'W','i','n','P','r','i','n','t',0};
72 /******************************************************************
73 * WINSPOOL_GetOpenedPrinterEntry
74 * Get the first place empty in the opened printer table
76 static HANDLE
WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name
)
80 for (i
= 0; i
< nb_printers
; i
++) if (!printer_array
[i
]) break;
84 LPWSTR
*new_array
= HeapReAlloc( GetProcessHeap(), 0, printer_array
,
85 (nb_printers
+ 16) * sizeof(*new_array
) );
86 if (!new_array
) return 0;
87 printer_array
= new_array
;
91 if ((printer_array
[i
] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name
)+1)*sizeof(WCHAR
) )))
93 strcpyW( printer_array
[i
], name
);
94 return (HANDLE
)(i
+ 1);
99 /******************************************************************
100 * WINSPOOL_GetOpenedPrinter
101 * Get the pointer to the opened printer referred by the handle
103 static LPCWSTR
WINSPOOL_GetOpenedPrinter(HANDLE printerHandle
)
105 int idx
= (int)printerHandle
;
106 if ((idx
<= 0) || (idx
> nb_printers
))
108 SetLastError(ERROR_INVALID_HANDLE
);
111 return printer_array
[idx
- 1];
114 /******************************************************************
115 * WINSPOOL_GetOpenedPrinterRegKey
118 static DWORD
WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter
, HKEY
*phkey
)
120 LPCWSTR name
= WINSPOOL_GetOpenedPrinter(hPrinter
);
124 if(!name
) return ERROR_INVALID_HANDLE
;
126 if((ret
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
)) !=
130 if(RegOpenKeyW(hkeyPrinters
, name
, phkey
) != ERROR_SUCCESS
)
132 ERR("Can't find opened printer %s in registry\n",
134 RegCloseKey(hkeyPrinters
);
135 return ERROR_INVALID_PRINTER_NAME
; /* ? */
137 RegCloseKey(hkeyPrinters
);
138 return ERROR_SUCCESS
;
141 /***********************************************************
144 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
147 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
150 Formname
= (dmA
->dmSize
> off_formname
);
151 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
152 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
155 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
156 dmA
->dmSize
- CCHDEVICENAME
);
158 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
159 off_formname
- CCHDEVICENAME
);
160 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
162 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
163 (off_formname
+ CCHFORMNAME
));
166 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
171 /***********************************************************
173 * Creates a unicode copy of supplied devmode on heap
175 static LPDEVMODEW
DEVMODEdupAtoW(HANDLE heap
, const DEVMODEA
*dmA
)
180 ptrdiff_t off_formname
;
183 if(!dmA
) return NULL
;
185 off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
186 Formname
= (dmA
->dmSize
> off_formname
);
187 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
188 dmW
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmA
->dmDriverExtra
);
189 return DEVMODEcpyAtoW(dmW
, dmA
);
192 /***********************************************************
194 * Creates an ascii copy of supplied devmode on heap
196 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
201 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
203 if(!dmW
) return NULL
;
204 Formname
= (dmW
->dmSize
> off_formname
);
205 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
206 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
207 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
208 CCHDEVICENAME
, NULL
, NULL
);
210 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
211 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
213 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
214 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
215 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
216 CCHFORMNAME
, NULL
, NULL
);
217 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
218 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
221 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
226 /***********************************************************
228 * Creates a unicode copy of PRINTER_INFO_2A on heap
230 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
232 LPPRINTER_INFO_2W piW
;
233 if(!piA
) return NULL
;
234 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
235 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
236 piW
->pServerName
= HEAP_strdupAtoW(heap
, 0, piA
->pServerName
);
237 piW
->pPrinterName
= HEAP_strdupAtoW(heap
, 0, piA
->pPrinterName
);
238 piW
->pShareName
= HEAP_strdupAtoW(heap
, 0, piA
->pShareName
);
239 piW
->pPortName
= HEAP_strdupAtoW(heap
, 0, piA
->pPortName
);
240 piW
->pDriverName
= HEAP_strdupAtoW(heap
, 0, piA
->pDriverName
);
241 piW
->pComment
= HEAP_strdupAtoW(heap
, 0, piA
->pComment
);
242 piW
->pLocation
= HEAP_strdupAtoW(heap
, 0, piA
->pLocation
);
243 piW
->pDevMode
= DEVMODEdupAtoW(heap
, piA
->pDevMode
);
244 piW
->pSepFile
= HEAP_strdupAtoW(heap
, 0, piA
->pSepFile
);
245 piW
->pPrintProcessor
= HEAP_strdupAtoW(heap
, 0, piA
->pPrintProcessor
);
246 piW
->pDatatype
= HEAP_strdupAtoW(heap
, 0, piA
->pDatatype
);
247 piW
->pParameters
= HEAP_strdupAtoW(heap
, 0, piA
->pParameters
);
251 /***********************************************************
252 * FREE_PRINTER_INFO_2W
253 * Free PRINTER_INFO_2W and all strings
255 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
259 HeapFree(heap
,0,piW
->pServerName
);
260 HeapFree(heap
,0,piW
->pPrinterName
);
261 HeapFree(heap
,0,piW
->pShareName
);
262 HeapFree(heap
,0,piW
->pPortName
);
263 HeapFree(heap
,0,piW
->pDriverName
);
264 HeapFree(heap
,0,piW
->pComment
);
265 HeapFree(heap
,0,piW
->pLocation
);
266 HeapFree(heap
,0,piW
->pDevMode
);
267 HeapFree(heap
,0,piW
->pSepFile
);
268 HeapFree(heap
,0,piW
->pPrintProcessor
);
269 HeapFree(heap
,0,piW
->pDatatype
);
270 HeapFree(heap
,0,piW
->pParameters
);
271 HeapFree(heap
,0,piW
);
275 /******************************************************************
276 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
279 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
280 LPSTR pOutput
, LPDEVMODEA lpdm
)
284 if (!GDI_CallDeviceCapabilities16
)
286 GDI_CallDeviceCapabilities16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
288 if (!GDI_CallDeviceCapabilities16
) return -1;
290 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
292 /* If DC_PAPERSIZE map POINT16s to POINTs */
293 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
294 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
295 POINT
*pt
= (POINT
*)pOutput
;
297 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
298 for(i
= 0; i
< ret
; i
++, pt
++)
303 HeapFree( GetProcessHeap(), 0, tmp
);
309 /*****************************************************************************
310 * DeviceCapabilitiesW [WINSPOOL.152]
312 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
315 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
316 WORD fwCapability
, LPWSTR pOutput
,
317 const DEVMODEW
*pDevMode
)
319 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
320 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
321 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
324 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
325 fwCapability
== DC_FILEDEPENDENCIES
||
326 fwCapability
== DC_PAPERNAMES
)) {
327 /* These need A -> W translation */
330 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
334 switch(fwCapability
) {
339 case DC_FILEDEPENDENCIES
:
343 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
344 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
346 for(i
= 0; i
< ret
; i
++)
347 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
348 pOutput
+ (i
* size
), size
);
349 HeapFree(GetProcessHeap(), 0, pOutputA
);
351 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
352 (LPSTR
)pOutput
, dmA
);
354 HeapFree(GetProcessHeap(),0,pPortA
);
355 HeapFree(GetProcessHeap(),0,pDeviceA
);
356 HeapFree(GetProcessHeap(),0,dmA
);
360 /******************************************************************
361 * DocumentPropertiesA [WINSPOOL.155]
364 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
365 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
366 LPDEVMODEA pDevModeInput
,DWORD fMode
)
368 LPSTR lpName
= pDeviceName
;
371 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
372 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
376 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
377 if(!lpNameW
) return -1;
378 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
381 if (!GDI_CallExtDeviceMode16
)
383 GDI_CallExtDeviceMode16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
385 if (!GDI_CallExtDeviceMode16
) return -1;
387 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
388 pDevModeInput
, NULL
, fMode
);
391 HeapFree(GetProcessHeap(),0,lpName
);
396 /*****************************************************************************
397 * DocumentPropertiesW
399 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
401 LPDEVMODEW pDevModeOutput
,
402 LPDEVMODEW pDevModeInput
, DWORD fMode
)
405 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
406 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
407 LPDEVMODEA pDevModeOutputA
= NULL
;
410 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
411 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
414 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
415 if(ret
< 0) return ret
;
416 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
418 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
419 pDevModeInputA
, fMode
);
421 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
422 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
424 if(fMode
== 0 && ret
> 0)
425 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
426 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
427 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
431 /******************************************************************
432 * OpenPrinterA [WINSPOOL.196]
435 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
436 LPPRINTER_DEFAULTSA pDefault
)
438 LPWSTR lpPrinterNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName
);
439 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
443 DefaultW
.pDatatype
= HEAP_strdupAtoW(GetProcessHeap(), 0,
444 pDefault
->pDatatype
);
445 DefaultW
.pDevMode
= DEVMODEdupAtoW(GetProcessHeap(),
447 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
448 pDefaultW
= &DefaultW
;
450 ret
= OpenPrinterW(lpPrinterNameW
, phPrinter
, pDefaultW
);
452 HeapFree(GetProcessHeap(), 0, DefaultW
.pDatatype
);
453 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
455 HeapFree(GetProcessHeap(), 0, lpPrinterNameW
);
459 /******************************************************************
460 * OpenPrinterW [WINSPOOL.197]
463 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
464 LPPRINTER_DEFAULTSW pDefault
)
466 HKEY hkeyPrinters
, hkeyPrinter
;
468 if (!lpPrinterName
) {
469 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
470 SetLastError(ERROR_INVALID_PARAMETER
);
474 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
477 /* Check Printer exists */
478 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
480 ERR("Can't create Printers key\n");
481 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
485 if(RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
487 WARN("Can't find printer %s in registry\n", debugstr_w(lpPrinterName
));
488 RegCloseKey(hkeyPrinters
);
489 SetLastError(ERROR_INVALID_PARAMETER
);
492 RegCloseKey(hkeyPrinter
);
493 RegCloseKey(hkeyPrinters
);
495 if(!phPrinter
) /* This seems to be what win95 does anyway */
498 /* Get the unique handle of the printer*/
499 *phPrinter
= WINSPOOL_GetOpenedPrinterEntry( lpPrinterName
);
501 if (pDefault
!= NULL
)
502 FIXME("Not handling pDefault\n");
507 /******************************************************************
508 * AddMonitorA [WINSPOOL.107]
511 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
513 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
514 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
518 /******************************************************************
519 * DeletePrinterDriverA [WINSPOOL.146]
523 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
525 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
526 debugstr_a(pDriverName
));
527 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
532 /******************************************************************
533 * DeleteMonitorA [WINSPOOL.135]
537 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
539 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
540 debugstr_a(pMonitorName
));
541 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
546 /******************************************************************
547 * DeletePortA [WINSPOOL.137]
551 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
553 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
554 debugstr_a(pPortName
));
555 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
559 /******************************************************************************
560 * SetPrinterW [WINSPOOL.214]
570 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
574 /******************************************************************************
575 * WritePrinter [WINSPOOL.223]
585 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
589 /*****************************************************************************
590 * AddFormA [WINSPOOL.103]
592 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
594 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
598 /*****************************************************************************
599 * AddFormW [WINSPOOL.104]
601 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
603 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
607 /*****************************************************************************
608 * AddJobA [WINSPOOL.105]
610 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
611 DWORD cbBuf
, LPDWORD pcbNeeded
)
613 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
618 /*****************************************************************************
619 * AddJobW [WINSPOOL.106]
621 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
624 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
629 /*****************************************************************************
630 * WINSPOOL_OpenDriverReg [internal]
632 * opens the registry for the printer drivers depending on the given input
633 * variable pEnvironment
636 * the opened hkey on success
639 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
)
641 LPSTR lpKey
, p
= NULL
;
644 (unicode
) ? debugstr_w(pEnvironment
) : debugstr_a(pEnvironment
));
647 p
= (unicode
) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
) :
651 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
653 if(!GetVersionExA( &ver
))
656 switch (ver
.dwPlatformId
) {
657 case VER_PLATFORM_WIN32s
:
659 case VER_PLATFORM_WIN32_NT
:
660 p
= "Windows NT x86";
666 TRACE("set environment to %s\n", p
);
669 lpKey
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
670 strlen(p
) + strlen(Drivers
));
671 sprintf( lpKey
, Drivers
, p
);
673 TRACE("%s\n", lpKey
);
675 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, lpKey
, &retval
) !=
679 if(pEnvironment
&& unicode
)
680 HeapFree( GetProcessHeap(), 0, p
);
681 HeapFree( GetProcessHeap(), 0, lpKey
);
686 /*****************************************************************************
687 * AddPrinterW [WINSPOOL.122]
689 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
691 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
695 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
698 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
701 FIXME("pName = %s - unsupported\n", debugstr_w(pName
));
702 SetLastError(ERROR_INVALID_PARAMETER
);
706 WARN("Level = %ld\n", Level
);
707 SetLastError(ERROR_INVALID_LEVEL
);
711 SetLastError(ERROR_INVALID_PARAMETER
);
714 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
716 ERR("Can't create Printers key\n");
719 if(RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) ==
721 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
722 RegCloseKey(hkeyPrinter
);
723 RegCloseKey(hkeyPrinters
);
726 hkeyDrivers
= WINSPOOL_OpenDriverReg( NULL
, TRUE
);
728 ERR("Can't create Drivers key\n");
729 RegCloseKey(hkeyPrinters
);
732 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
734 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
735 RegCloseKey(hkeyPrinters
);
736 RegCloseKey(hkeyDrivers
);
737 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
740 RegCloseKey(hkeyDriver
);
741 RegCloseKey(hkeyDrivers
);
743 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
744 WARN("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
745 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
746 RegCloseKey(hkeyPrinters
);
750 /* See if we can load the driver. We may need the devmode structure anyway
752 size
= DocumentPropertiesW(0, -1, pi
->pPrinterName
, NULL
, NULL
, 0);
754 WARN("DocumentProperties fails\n");
755 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
761 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
762 DocumentPropertiesW(0, -1, pi
->pPrinterName
, dmW
, NULL
, DM_OUT_BUFFER
);
765 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
767 WARN("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
768 SetLastError(ERROR_INVALID_PRINTER_NAME
);
769 RegCloseKey(hkeyPrinters
);
771 HeapFree(GetProcessHeap(), 0, dmW
);
774 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
775 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
776 RegSetValueExW(hkeyPrinter
, DatatypeW
, 0, REG_SZ
, (LPBYTE
)pi
->pDatatype
,
779 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
780 and we support these drivers. NT writes DEVMODEW so somehow
781 we'll need to distinguish between these when we support NT
783 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
784 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
, (LPBYTE
)dmA
,
785 dmA
->dmSize
+ dmA
->dmDriverExtra
);
786 HeapFree(GetProcessHeap(), 0, dmA
);
788 HeapFree(GetProcessHeap(), 0, dmW
);
789 RegSetValueExW(hkeyPrinter
, DescriptionW
, 0, REG_SZ
, (LPBYTE
)pi
->pComment
,
791 RegSetValueExW(hkeyPrinter
, LocationW
, 0, REG_SZ
, (LPBYTE
)pi
->pLocation
,
793 RegSetValueExW(hkeyPrinter
, NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pPrinterName
, 0);
794 RegSetValueExW(hkeyPrinter
, ParametersW
, 0, REG_SZ
,
795 (LPBYTE
)pi
->pParameters
, 0);
796 RegSetValueExW(hkeyPrinter
, PortW
, 0, REG_SZ
, (LPBYTE
)pi
->pPortName
, 0);
797 RegSetValueExW(hkeyPrinter
, Print_ProcessorW
, 0, REG_SZ
,
798 (LPBYTE
)pi
->pPrintProcessor
, 0);
799 RegSetValueExW(hkeyPrinter
, Printer_DriverW
, 0, REG_SZ
,
800 (LPBYTE
)pi
->pDriverName
, 0);
801 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
802 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
803 RegSetValueExW(hkeyPrinter
, Separator_FileW
, 0, REG_SZ
,
804 (LPBYTE
)pi
->pSepFile
, 0);
805 RegSetValueExW(hkeyPrinter
, Share_NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pShareName
,
807 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
808 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
809 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
810 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
811 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
812 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
814 RegCloseKey(hkeyPrinter
);
815 RegCloseKey(hkeyPrinters
);
816 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
817 ERR("OpenPrinter failing\n");
823 /*****************************************************************************
824 * AddPrinterA [WINSPOOL.117]
826 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
829 PRINTER_INFO_2W
*piW
;
830 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
833 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
835 WARN("Level = %ld\n", Level
);
836 SetLastError(ERROR_INVALID_LEVEL
);
839 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
840 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
842 ret
= AddPrinterW(pNameW
, Level
, (LPBYTE
)piW
);
844 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
845 HeapFree(GetProcessHeap(),0,pNameW
);
850 /*****************************************************************************
851 * ClosePrinter [WINSPOOL.126]
853 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
855 int i
= (int)hPrinter
;
857 TRACE("Handle %d\n", hPrinter
);
859 if ((i
<= 0) || (i
> nb_printers
)) return FALSE
;
860 HeapFree( GetProcessHeap(), 0, printer_array
[i
- 1] );
861 printer_array
[i
- 1] = NULL
;
865 /*****************************************************************************
866 * DeleteFormA [WINSPOOL.133]
868 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
870 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
874 /*****************************************************************************
875 * DeleteFormW [WINSPOOL.134]
877 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
879 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
883 /*****************************************************************************
884 * DeletePrinter [WINSPOOL.143]
886 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
888 LPCWSTR lpNameW
= WINSPOOL_GetOpenedPrinter(hPrinter
);
891 if(!lpNameW
) return FALSE
;
892 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
894 ERR("Can't open Printers key\n");
898 /* This should use a recursive delete see Q142491 or SHDeleteKey */
899 if(RegDeleteKeyW(hkeyPrinters
, lpNameW
) == ERROR_SUCCESS
) {
900 SetLastError(ERROR_PRINTER_NOT_FOUND
); /* ?? */
901 RegCloseKey(hkeyPrinters
);
905 ClosePrinter(hPrinter
);
909 /*****************************************************************************
910 * SetPrinterA [WINSPOOL.211]
912 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
915 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
919 /*****************************************************************************
920 * SetJobA [WINSPOOL.209]
922 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
923 LPBYTE pJob
, DWORD Command
)
925 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
930 /*****************************************************************************
931 * SetJobW [WINSPOOL.210]
933 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
934 LPBYTE pJob
, DWORD Command
)
936 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
941 /*****************************************************************************
942 * GetFormA [WINSPOOL.181]
944 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
945 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
947 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
948 Level
,pForm
,cbBuf
,pcbNeeded
);
952 /*****************************************************************************
953 * GetFormW [WINSPOOL.182]
955 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
956 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
958 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
959 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
963 /*****************************************************************************
964 * SetFormA [WINSPOOL.207]
966 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
969 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
973 /*****************************************************************************
974 * SetFormW [WINSPOOL.208]
976 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
979 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
983 /*****************************************************************************
984 * ReadPrinter [WINSPOOL.202]
986 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
987 LPDWORD pNoBytesRead
)
989 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
993 /*****************************************************************************
994 * ResetPrinterA [WINSPOOL.203]
996 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
998 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1002 /*****************************************************************************
1003 * ResetPrinterW [WINSPOOL.204]
1005 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1007 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1011 /*****************************************************************************
1012 * WINSPOOL_GetDWORDFromReg
1014 * Return DWORD associated with ValueName from hkey.
1016 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
1018 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
1021 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
1023 if(ret
!= ERROR_SUCCESS
) {
1024 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
1027 if(type
!= REG_DWORD
) {
1028 ERR("Got type %ld\n", type
);
1034 /*****************************************************************************
1035 * WINSPOOL_GetStringFromReg
1037 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1038 * String is stored either as unicode or ascii.
1039 * Bit of a hack here to get the ValueName if we want ascii.
1041 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1042 DWORD buflen
, DWORD
*needed
,
1045 DWORD sz
= buflen
, type
;
1049 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1051 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1052 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1053 HeapFree(GetProcessHeap(),0,ValueNameA
);
1055 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1056 WARN("Got ret = %ld\n", ret
);
1064 /*****************************************************************************
1065 * WINSPOOL_GetDevModeFromReg
1067 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1068 * DevMode is stored either as unicode or ascii.
1070 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1072 DWORD buflen
, DWORD
*needed
,
1075 DWORD sz
= buflen
, type
;
1078 if (ptr
) memset(ptr
, 0, sizeof(DEVMODEA
));
1079 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1080 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1081 if (sz
< sizeof(DEVMODEA
))
1083 ERR("corrupted registry for %s\n", debugstr_w(ValueName
));
1084 sz
= sizeof(DEVMODEA
);
1086 /* ensures that dmSize is not erratically bogus if registry is invalid */
1087 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1088 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1090 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1092 DEVMODEW
*dmW
= DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA
*)ptr
);
1093 memcpy(ptr
, dmW
, sz
);
1094 HeapFree(GetProcessHeap(),0,dmW
);
1101 /*********************************************************************
1102 * WINSPOOL_GetPrinter_2
1104 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1105 * The strings are either stored as unicode or ascii.
1107 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1108 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1111 DWORD size
, left
= cbBuf
;
1112 BOOL space
= (cbBuf
> 0);
1117 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1119 if(space
&& size
<= left
) {
1120 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1127 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1129 if(space
&& size
<= left
) {
1130 pi2
->pShareName
= (LPWSTR
)ptr
;
1137 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1139 if(space
&& size
<= left
) {
1140 pi2
->pPortName
= (LPWSTR
)ptr
;
1147 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1149 if(space
&& size
<= left
) {
1150 pi2
->pDriverName
= (LPWSTR
)ptr
;
1157 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1159 if(space
&& size
<= left
) {
1160 pi2
->pComment
= (LPWSTR
)ptr
;
1167 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1169 if(space
&& size
<= left
) {
1170 pi2
->pLocation
= (LPWSTR
)ptr
;
1177 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1179 if(space
&& size
<= left
) {
1180 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1187 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1189 if(space
&& size
<= left
) {
1190 pi2
->pSepFile
= (LPWSTR
)ptr
;
1197 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1199 if(space
&& size
<= left
) {
1200 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1207 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1209 if(space
&& size
<= left
) {
1210 pi2
->pDatatype
= (LPWSTR
)ptr
;
1217 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1219 if(space
&& size
<= left
) {
1220 pi2
->pParameters
= (LPWSTR
)ptr
;
1228 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1229 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1230 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1231 "Default Priority");
1232 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1233 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1236 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1237 memset(pi2
, 0, sizeof(*pi2
));
1242 /*********************************************************************
1243 * WINSPOOL_GetPrinter_4
1245 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1247 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1248 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1251 DWORD size
, left
= cbBuf
;
1252 BOOL space
= (cbBuf
> 0);
1257 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1259 if(space
&& size
<= left
) {
1260 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1268 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1271 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1272 memset(pi4
, 0, sizeof(*pi4
));
1277 /*********************************************************************
1278 * WINSPOOL_GetPrinter_5
1280 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1282 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1283 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1286 DWORD size
, left
= cbBuf
;
1287 BOOL space
= (cbBuf
> 0);
1292 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1294 if(space
&& size
<= left
) {
1295 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1302 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1304 if(space
&& size
<= left
) {
1305 pi5
->pPortName
= (LPWSTR
)ptr
;
1313 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1314 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1316 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1320 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1321 memset(pi5
, 0, sizeof(*pi5
));
1326 /*****************************************************************************
1327 * WINSPOOL_GetPrinter
1329 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1330 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1331 * just a collection of pointers to strings.
1333 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1334 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1337 DWORD size
, needed
= 0;
1339 HKEY hkeyPrinter
, hkeyPrinters
;
1342 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1344 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
1346 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1348 ERR("Can't create Printers key\n");
1351 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
) != ERROR_SUCCESS
)
1353 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
1354 RegCloseKey(hkeyPrinters
);
1355 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1362 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
1364 size
= sizeof(PRINTER_INFO_2W
);
1366 ptr
= pPrinter
+ size
;
1368 memset(pPrinter
, 0, size
);
1373 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
1381 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
1383 size
= sizeof(PRINTER_INFO_4W
);
1385 ptr
= pPrinter
+ size
;
1387 memset(pPrinter
, 0, size
);
1392 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
1401 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
1403 size
= sizeof(PRINTER_INFO_5W
);
1405 ptr
= pPrinter
+ size
;
1407 memset(pPrinter
, 0, size
);
1413 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
1420 FIXME("Unimplemented level %ld\n", Level
);
1421 SetLastError(ERROR_INVALID_LEVEL
);
1422 RegCloseKey(hkeyPrinters
);
1423 RegCloseKey(hkeyPrinter
);
1427 RegCloseKey(hkeyPrinter
);
1428 RegCloseKey(hkeyPrinters
);
1430 TRACE("returing %d needed = %ld\n", ret
, needed
);
1431 if(pcbNeeded
) *pcbNeeded
= needed
;
1433 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1437 /*****************************************************************************
1438 * GetPrinterW [WINSPOOL.194]
1440 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1441 DWORD cbBuf
, LPDWORD pcbNeeded
)
1443 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1447 /*****************************************************************************
1448 * GetPrinterA [WINSPOOL.187]
1450 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1451 DWORD cbBuf
, LPDWORD pcbNeeded
)
1453 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1457 /*****************************************************************************
1458 * WINSPOOL_EnumPrinters
1460 * Implementation of EnumPrintersA|W
1462 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
1463 DWORD dwLevel
, LPBYTE lpbPrinters
,
1464 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1465 LPDWORD lpdwReturned
, BOOL unicode
)
1468 HKEY hkeyPrinters
, hkeyPrinter
;
1469 WCHAR PrinterName
[255];
1470 DWORD needed
= 0, number
= 0;
1471 DWORD used
, i
, left
;
1475 memset(lpbPrinters
, 0, cbBuf
);
1481 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1482 if(dwType
== PRINTER_ENUM_DEFAULT
)
1485 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
1486 FIXME("dwType = %08lx\n", dwType
);
1487 SetLastError(ERROR_INVALID_FLAGS
);
1491 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1493 ERR("Can't create Printers key\n");
1497 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
1498 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
1499 RegCloseKey(hkeyPrinters
);
1500 ERR("Can't query Printers key\n");
1503 TRACE("Found %ld printers\n", number
);
1507 RegCloseKey(hkeyPrinters
);
1509 *lpdwReturned
= number
;
1513 used
= number
* sizeof(PRINTER_INFO_2W
);
1516 used
= number
* sizeof(PRINTER_INFO_4W
);
1519 used
= number
* sizeof(PRINTER_INFO_5W
);
1523 SetLastError(ERROR_INVALID_LEVEL
);
1524 RegCloseKey(hkeyPrinters
);
1527 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
1529 for(i
= 0; i
< number
; i
++) {
1530 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
1532 ERR("Can't enum key number %ld\n", i
);
1533 RegCloseKey(hkeyPrinters
);
1536 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
1537 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
1539 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
1540 RegCloseKey(hkeyPrinters
);
1545 buf
= lpbPrinters
+ used
;
1546 left
= cbBuf
- used
;
1554 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
1555 left
, &needed
, unicode
);
1557 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
1560 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
1561 left
, &needed
, unicode
);
1563 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
1566 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
1567 left
, &needed
, unicode
);
1569 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
1572 ERR("Shouldn't be here!\n");
1573 RegCloseKey(hkeyPrinter
);
1574 RegCloseKey(hkeyPrinters
);
1577 RegCloseKey(hkeyPrinter
);
1579 RegCloseKey(hkeyPrinters
);
1586 memset(lpbPrinters
, 0, cbBuf
);
1587 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1591 *lpdwReturned
= number
;
1592 SetLastError(ERROR_SUCCESS
);
1597 /******************************************************************
1598 * EnumPrintersW [WINSPOOL.175]
1600 * Enumerates the available printers, print servers and print
1601 * providers, depending on the specified flags, name and level.
1605 * If level is set to 1:
1606 * Not implemented yet!
1607 * Returns TRUE with an empty list.
1609 * If level is set to 2:
1610 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1611 * Returns an array of PRINTER_INFO_2 data structures in the
1612 * lpbPrinters buffer. Note that according to MSDN also an
1613 * OpenPrinter should be performed on every remote printer.
1615 * If level is set to 4 (officially WinNT only):
1616 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1617 * Fast: Only the registry is queried to retrieve printer names,
1618 * no connection to the driver is made.
1619 * Returns an array of PRINTER_INFO_4 data structures in the
1620 * lpbPrinters buffer.
1622 * If level is set to 5 (officially WinNT4/Win9x only):
1623 * Fast: Only the registry is queried to retrieve printer names,
1624 * no connection to the driver is made.
1625 * Returns an array of PRINTER_INFO_5 data structures in the
1626 * lpbPrinters buffer.
1628 * If level set to 3 or 6+:
1629 * returns zero (failure!)
1631 * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
1635 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1636 * - Only levels 2, 4 and 5 are implemented at the moment.
1637 * - 16-bit printer drivers are not enumerated.
1638 * - Returned amount of bytes used/needed does not match the real Windoze
1639 * implementation (as in this implementation, all strings are part
1640 * of the buffer, whereas Win32 keeps them somewhere else)
1641 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1644 * - In a regular Wine installation, no registry settings for printers
1645 * exist, which makes this function return an empty list.
1647 BOOL WINAPI
EnumPrintersW(
1648 DWORD dwType
, /* [in] Types of print objects to enumerate */
1649 LPWSTR lpszName
, /* [in] name of objects to enumerate */
1650 DWORD dwLevel
, /* [in] type of printer info structure */
1651 LPBYTE lpbPrinters
, /* [out] buffer which receives info */
1652 DWORD cbBuf
, /* [in] max size of buffer in bytes */
1653 LPDWORD lpdwNeeded
, /* [out] pointer to var: # bytes used/needed */
1654 LPDWORD lpdwReturned
/* [out] number of entries returned */
1657 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
1658 lpdwNeeded
, lpdwReturned
, TRUE
);
1661 /******************************************************************
1662 * EnumPrintersA [WINSPOOL.174]
1665 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
1666 DWORD dwLevel
, LPBYTE lpbPrinters
,
1667 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1668 LPDWORD lpdwReturned
)
1671 LPWSTR lpszNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpszName
);
1673 ret
= WINSPOOL_EnumPrinters(dwType
, lpszNameW
, dwLevel
, lpbPrinters
, cbBuf
,
1674 lpdwNeeded
, lpdwReturned
, FALSE
);
1675 HeapFree(GetProcessHeap(),0,lpszNameW
);
1679 /*****************************************************************************
1680 * WINSPOOL_GetDriverInfoFromReg [internal]
1682 * Enters the information from the registry into the DRIVER_INFO struct
1685 * zero if the printer driver does not exist in the registry
1686 * (only if Level > 1) otherwise nonzero
1688 static BOOL
WINSPOOL_GetDriverInfoFromReg(
1691 LPWSTR pEnvironment
,
1693 LPBYTE ptr
, /* DRIVER_INFO */
1694 LPBYTE pDriverStrings
, /* strings buffer */
1695 DWORD cbBuf
, /* size of string buffer */
1696 LPDWORD pcbNeeded
, /* space needed for str. */
1697 BOOL unicode
) /* type of strings */
1698 { DWORD dw
, size
, tmp
, type
;
1700 LPBYTE strPtr
= pDriverStrings
;
1702 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
1703 debugstr_w(DriverName
), debugstr_w(pEnvironment
),
1704 Level
, ptr
, pDriverStrings
, cbBuf
, unicode
);
1707 *pcbNeeded
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
1708 if (*pcbNeeded
<= cbBuf
)
1709 strcpyW((LPWSTR
)strPtr
, DriverName
);
1711 *pcbNeeded
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0,
1713 if(*pcbNeeded
<= cbBuf
)
1714 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, strPtr
, *pcbNeeded
,
1719 ((PDRIVER_INFO_1W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1723 ((PDRIVER_INFO_3W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1724 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1727 if(RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
) != ERROR_SUCCESS
) {
1728 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName
));
1729 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
1734 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
, &size
) !=
1736 WARN("Can't get Version\n");
1738 ((PDRIVER_INFO_3A
) ptr
)->cVersion
= dw
;
1741 pEnvironment
= DefaultEnvironmentW
;
1743 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
1745 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
1748 if(*pcbNeeded
<= cbBuf
) {
1750 strcpyW((LPWSTR
)strPtr
, pEnvironment
);
1752 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, strPtr
, size
,
1755 ((PDRIVER_INFO_3W
) ptr
)->pEnvironment
= (LPWSTR
)strPtr
;
1756 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1759 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, 0, &size
,
1762 if(*pcbNeeded
<= cbBuf
)
1763 WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, size
, &tmp
,
1766 ((PDRIVER_INFO_3W
) ptr
)->pDriverPath
= (LPWSTR
)strPtr
;
1767 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1770 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, 0, &size
,
1773 if(*pcbNeeded
<= cbBuf
)
1774 WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, size
,
1777 ((PDRIVER_INFO_3W
) ptr
)->pDataFile
= (LPWSTR
)strPtr
;
1778 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1781 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1782 0, &size
, unicode
)) {
1784 if(*pcbNeeded
<= cbBuf
)
1785 WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1786 size
, &tmp
, unicode
);
1788 ((PDRIVER_INFO_3W
) ptr
)->pConfigFile
= (LPWSTR
)strPtr
;
1789 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1793 RegCloseKey(hkeyDriver
);
1794 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1798 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
, 0, &size
,
1801 if(*pcbNeeded
<= cbBuf
)
1802 WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
,
1803 size
, &tmp
, unicode
);
1805 ((PDRIVER_INFO_3W
) ptr
)->pHelpFile
= (LPWSTR
)strPtr
;
1806 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1809 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
, 0,
1812 if(*pcbNeeded
<= cbBuf
)
1813 WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
,
1814 size
, &tmp
, unicode
);
1816 ((PDRIVER_INFO_3W
) ptr
)->pDependentFiles
= (LPWSTR
)strPtr
;
1817 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1820 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
, 0, &size
,
1823 if(*pcbNeeded
<= cbBuf
)
1824 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1825 size
, &tmp
, unicode
);
1827 ((PDRIVER_INFO_3W
) ptr
)->pMonitorName
= (LPWSTR
)strPtr
;
1828 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1831 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, strPtr
, 0, &size
,
1834 if(*pcbNeeded
<= cbBuf
)
1835 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1836 size
, &tmp
, unicode
);
1838 ((PDRIVER_INFO_3W
) ptr
)->pDefaultDataType
= (LPWSTR
)strPtr
;
1839 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1842 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1843 RegCloseKey(hkeyDriver
);
1847 /*****************************************************************************
1848 * WINSPOOL_GetPrinterDriver
1850 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
1851 DWORD Level
, LPBYTE pDriverInfo
,
1852 DWORD cbBuf
, LPDWORD pcbNeeded
,
1856 WCHAR DriverName
[100];
1857 DWORD ret
, type
, size
, needed
= 0;
1859 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDrivers
;
1861 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
1862 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1864 ZeroMemory(pDriverInfo
, cbBuf
);
1866 if (!(name
= WINSPOOL_GetOpenedPrinter(hPrinter
))) return FALSE
;
1868 if(Level
< 1 || Level
> 3) {
1869 SetLastError(ERROR_INVALID_LEVEL
);
1872 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1874 ERR("Can't create Printers key\n");
1877 if(RegOpenKeyW(hkeyPrinters
, name
, &hkeyPrinter
)
1879 ERR("Can't find opened printer %s in registry\n", debugstr_w(name
));
1880 RegCloseKey(hkeyPrinters
);
1881 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1884 size
= sizeof(DriverName
);
1885 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
1886 (LPBYTE
)DriverName
, &size
);
1887 RegCloseKey(hkeyPrinter
);
1888 RegCloseKey(hkeyPrinters
);
1889 if(ret
!= ERROR_SUCCESS
) {
1890 ERR("Can't get DriverName for printer %s\n", debugstr_w(name
));
1894 hkeyDrivers
= WINSPOOL_OpenDriverReg( pEnvironment
, TRUE
);
1896 ERR("Can't create Drivers key\n");
1902 size
= sizeof(DRIVER_INFO_1W
);
1905 size
= sizeof(DRIVER_INFO_2W
);
1908 size
= sizeof(DRIVER_INFO_3W
);
1911 ERR("Invalid level\n");
1916 ptr
= pDriverInfo
+ size
;
1918 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverName
,
1919 pEnvironment
, Level
, pDriverInfo
,
1920 (cbBuf
< size
) ? NULL
: ptr
,
1921 (cbBuf
< size
) ? 0 : cbBuf
- size
,
1922 &needed
, unicode
)) {
1923 RegCloseKey(hkeyDrivers
);
1927 RegCloseKey(hkeyDrivers
);
1929 if(pcbNeeded
) *pcbNeeded
= size
+ needed
;
1930 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1931 if(cbBuf
>= needed
) return TRUE
;
1932 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1936 /*****************************************************************************
1937 * GetPrinterDriverA [WINSPOOL.190]
1939 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
1940 DWORD Level
, LPBYTE pDriverInfo
,
1941 DWORD cbBuf
, LPDWORD pcbNeeded
)
1944 LPWSTR pEnvW
= HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment
);
1945 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pEnvW
, Level
, pDriverInfo
,
1946 cbBuf
, pcbNeeded
, FALSE
);
1947 HeapFree(GetProcessHeap(),0,pEnvW
);
1950 /*****************************************************************************
1951 * GetPrinterDriverW [WINSPOOL.193]
1953 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
1954 DWORD Level
, LPBYTE pDriverInfo
,
1955 DWORD cbBuf
, LPDWORD pcbNeeded
)
1957 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
1958 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
1961 /*****************************************************************************
1962 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1964 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
1965 DWORD Level
, LPBYTE pDriverDirectory
,
1966 DWORD cbBuf
, LPDWORD pcbNeeded
)
1970 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName
, pEnvironment
, Level
,
1971 pDriverDirectory
, cbBuf
, pcbNeeded
);
1973 FIXME("pName = `%s' - unsupported\n", pName
);
1974 SetLastError(ERROR_INVALID_PARAMETER
);
1977 if(pEnvironment
!= NULL
) {
1978 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment
);
1979 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1982 if(Level
!= 1) /* win95 ignores this so we just carry on */
1983 WARN("Level = %ld - assuming 1\n", Level
);
1985 /* FIXME should read from registry */
1986 needed
= GetSystemDirectoryA(pDriverDirectory
, cbBuf
);
1989 *pcbNeeded
= needed
;
1990 if(needed
> cbBuf
) {
1991 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1998 /*****************************************************************************
1999 * GetPrinterDriverDirectoryW [WINSPOOL.192]
2001 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
2002 DWORD Level
, LPBYTE pDriverDirectory
,
2003 DWORD cbBuf
, LPDWORD pcbNeeded
)
2005 LPSTR pNameA
= NULL
, pEnvironmentA
= NULL
;
2009 pNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pName
);
2011 pEnvironmentA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
);
2012 ret
= GetPrinterDriverDirectoryA( pNameA
, pEnvironmentA
, Level
,
2013 pDriverDirectory
, cbBuf
, pcbNeeded
);
2015 HeapFree( GetProcessHeap(), 0, pNameA
);
2017 HeapFree( GetProcessHeap(), 0, pEnvironmentA
);
2022 /*****************************************************************************
2023 * AddPrinterDriverA [WINSPOOL.120]
2025 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
2028 HKEY hkeyDrivers
, hkeyName
;
2030 TRACE("(%s,%ld,%p)\n",pName
,level
,pDriverInfo
);
2032 if(level
!= 2 && level
!= 3) {
2033 SetLastError(ERROR_INVALID_LEVEL
);
2037 FIXME("pName= `%s' - unsupported\n", pName
);
2038 SetLastError(ERROR_INVALID_PARAMETER
);
2042 WARN("pDriverInfo == NULL");
2043 SetLastError(ERROR_INVALID_PARAMETER
);
2048 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
2050 memset(&di3
, 0, sizeof(di3
));
2051 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
2054 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
2056 SetLastError(ERROR_INVALID_PARAMETER
);
2059 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
2060 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
2061 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
2062 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
2064 hkeyDrivers
= WINSPOOL_OpenDriverReg(di3
.pEnvironment
, FALSE
);
2067 ERR("Can't create Drivers key\n");
2071 if(level
== 2) { /* apparently can't overwrite with level2 */
2072 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2073 RegCloseKey(hkeyName
);
2074 RegCloseKey(hkeyDrivers
);
2075 WARN("Trying to create existing printer driver `%s'\n", di3
.pName
);
2076 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2080 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2081 RegCloseKey(hkeyDrivers
);
2082 ERR("Can't create Name key\n");
2085 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2087 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2088 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2089 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2091 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2092 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2093 di3
.pDependentFiles
, 0);
2094 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2095 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2096 RegCloseKey(hkeyName
);
2097 RegCloseKey(hkeyDrivers
);
2101 /*****************************************************************************
2102 * AddPrinterDriverW [WINSPOOL.121]
2104 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2107 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2113 /*****************************************************************************
2114 * PrinterProperties [WINSPOOL.201]
2116 * Displays a dialog to set the properties of the printer.
2119 * nonzero on success or zero on failure
2122 * implemented as stub only
2124 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* [in] handle to parent window */
2125 HANDLE hPrinter
/* [in] handle to printer object */
2127 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
2128 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2132 /*****************************************************************************
2133 * EnumJobsA [WINSPOOL.162]
2136 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2137 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2141 if(pcbNeeded
) *pcbNeeded
= 0;
2142 if(pcReturned
) *pcReturned
= 0;
2147 /*****************************************************************************
2148 * EnumJobsW [WINSPOOL.163]
2151 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2152 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2156 if(pcbNeeded
) *pcbNeeded
= 0;
2157 if(pcReturned
) *pcReturned
= 0;
2161 /*****************************************************************************
2162 * WINSPOOL_EnumPrinterDrivers [internal]
2164 * Delivers information about all printer drivers installed on the
2165 * localhost or a given server
2168 * nonzero on success or zero on failure. If the buffer for the returned
2169 * information is too small the function will return an error
2172 * - only implemented for localhost, foreign hosts will return an error
2174 static BOOL
WINSPOOL_EnumPrinterDrivers(LPWSTR pName
, LPWSTR pEnvironment
,
2175 DWORD Level
, LPBYTE pDriverInfo
,
2176 DWORD cbBuf
, LPDWORD pcbNeeded
,
2177 LPDWORD pcReturned
, BOOL unicode
)
2180 DWORD i
, needed
, number
= 0, size
= 0;
2181 WCHAR DriverNameW
[255];
2184 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2185 debugstr_w(pName
), debugstr_w(pEnvironment
),
2186 Level
, pDriverInfo
, cbBuf
, unicode
);
2188 /* check for local drivers */
2190 ERR("remote drivers unsupported! Current remote host is %s\n",
2195 /* check input parameter */
2196 if((Level
< 1) || (Level
> 3)) {
2197 ERR("unsupported level %ld \n", Level
);
2201 /* initialize return values */
2203 memset( pDriverInfo
, 0, cbBuf
);
2207 hkeyDrivers
= WINSPOOL_OpenDriverReg(pEnvironment
, TRUE
);
2209 ERR("Can't open Drivers key\n");
2213 if(RegQueryInfoKeyA(hkeyDrivers
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2214 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2215 RegCloseKey(hkeyDrivers
);
2216 ERR("Can't query Drivers key\n");
2219 TRACE("Found %ld Drivers\n", number
);
2221 /* get size of single struct
2222 * unicode and ascii structure have the same size
2226 size
= sizeof(DRIVER_INFO_1A
);
2229 size
= sizeof(DRIVER_INFO_2A
);
2232 size
= sizeof(DRIVER_INFO_3A
);
2236 /* calculate required buffer size */
2237 *pcbNeeded
= size
* number
;
2239 for( i
= 0, ptr
= (pDriverInfo
&& (cbBuf
>= size
)) ? pDriverInfo
: NULL
;
2241 i
++, ptr
= (ptr
&& (cbBuf
>= size
* i
)) ? ptr
+ size
: NULL
) {
2242 if(RegEnumKeyW(hkeyDrivers
, i
, DriverNameW
, sizeof(DriverNameW
))
2244 ERR("Can't enum key number %ld\n", i
);
2245 RegCloseKey(hkeyDrivers
);
2248 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverNameW
,
2249 pEnvironment
, Level
, ptr
,
2250 (cbBuf
< *pcbNeeded
) ? NULL
: pDriverInfo
+ *pcbNeeded
,
2251 (cbBuf
< *pcbNeeded
) ? 0 : cbBuf
- *pcbNeeded
,
2252 &needed
, unicode
)) {
2253 RegCloseKey(hkeyDrivers
);
2256 (*pcbNeeded
) += needed
;
2259 RegCloseKey(hkeyDrivers
);
2261 if(cbBuf
< *pcbNeeded
){
2262 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2269 /*****************************************************************************
2270 * EnumPrinterDriversW [WINSPOOL.173]
2272 * see function EnumPrinterDrivers for RETURNS, BUGS
2274 BOOL WINAPI
EnumPrinterDriversW(LPWSTR pName
, LPWSTR pEnvironment
, DWORD Level
,
2275 LPBYTE pDriverInfo
, DWORD cbBuf
,
2276 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2278 return WINSPOOL_EnumPrinterDrivers(pName
, pEnvironment
, Level
, pDriverInfo
,
2279 cbBuf
, pcbNeeded
, pcReturned
, TRUE
);
2282 /*****************************************************************************
2283 * EnumPrinterDriversA [WINSPOOL.172]
2285 * see function EnumPrinterDrivers for RETURNS, BUGS
2287 BOOL WINAPI
EnumPrinterDriversA(LPSTR pName
, LPSTR pEnvironment
, DWORD Level
,
2288 LPBYTE pDriverInfo
, DWORD cbBuf
,
2289 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2291 WCHAR
*pNameW
= NULL
, *pEnvironmentW
= NULL
;
2294 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
2296 pEnvironmentW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment
);
2298 ret
= WINSPOOL_EnumPrinterDrivers(pNameW
, pEnvironmentW
, Level
, pDriverInfo
,
2299 cbBuf
, pcbNeeded
, pcReturned
, FALSE
);
2301 HeapFree(GetProcessHeap(), 0, pNameW
);
2303 HeapFree(GetProcessHeap(), 0, pEnvironmentW
);
2309 /******************************************************************************
2310 * EnumPortsA (WINSPOOL.166)
2312 BOOL WINAPI
EnumPortsA(LPSTR name
,DWORD level
,LPBYTE ports
,DWORD bufsize
,
2313 LPDWORD bufneeded
,LPDWORD bufreturned
)
2315 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name
,level
,ports
,bufsize
,bufneeded
,bufreturned
);
2319 /******************************************************************************
2320 * SetPrinterDataExA (WINSPOOL)
2322 DWORD WINAPI
SetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2323 LPSTR pValueName
, DWORD Type
,
2324 LPBYTE pData
, DWORD cbData
)
2326 HKEY hkeyPrinter
, hkeySubkey
;
2329 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_a(pKeyName
),
2330 debugstr_a(pValueName
), Type
, pData
, cbData
);
2332 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2336 if((ret
= RegCreateKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2338 ERR("Can't create subkey %s\n", debugstr_a(pKeyName
));
2339 RegCloseKey(hkeyPrinter
);
2342 ret
= RegSetValueExA(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2343 RegCloseKey(hkeySubkey
);
2344 RegCloseKey(hkeyPrinter
);
2348 /******************************************************************************
2349 * SetPrinterDataExW (WINSPOOL)
2351 DWORD WINAPI
SetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
2352 LPWSTR pValueName
, DWORD Type
,
2353 LPBYTE pData
, DWORD cbData
)
2355 HKEY hkeyPrinter
, hkeySubkey
;
2358 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_w(pKeyName
),
2359 debugstr_w(pValueName
), Type
, pData
, cbData
);
2361 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2365 if((ret
= RegCreateKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2367 ERR("Can't create subkey %s\n", debugstr_w(pKeyName
));
2368 RegCloseKey(hkeyPrinter
);
2371 ret
= RegSetValueExW(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2372 RegCloseKey(hkeySubkey
);
2373 RegCloseKey(hkeyPrinter
);
2377 /******************************************************************************
2378 * SetPrinterDataA (WINSPOOL)
2380 DWORD WINAPI
SetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, DWORD Type
,
2381 LPBYTE pData
, DWORD cbData
)
2383 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
,
2387 /******************************************************************************
2388 * SetPrinterDataW (WINSPOOL)
2390 DWORD WINAPI
SetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, DWORD Type
,
2391 LPBYTE pData
, DWORD cbData
)
2393 return SetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, Type
,
2397 /******************************************************************************
2398 * GetPrinterDataExA (WINSPOOL)
2400 DWORD WINAPI
GetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2401 LPSTR pValueName
, LPDWORD pType
,
2402 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2404 HKEY hkeyPrinter
, hkeySubkey
;
2407 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
2408 debugstr_a(pKeyName
), debugstr_a(pValueName
), pType
, pData
, nSize
,
2411 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2415 if((ret
= RegOpenKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2417 WARN("Can't open subkey %s\n", debugstr_a(pKeyName
));
2418 RegCloseKey(hkeyPrinter
);
2422 ret
= RegQueryValueExA(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
2423 RegCloseKey(hkeySubkey
);
2424 RegCloseKey(hkeyPrinter
);
2428 /******************************************************************************
2429 * GetPrinterDataExW (WINSPOOL)
2431 DWORD WINAPI
GetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
2432 LPWSTR pValueName
, LPDWORD pType
,
2433 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2435 HKEY hkeyPrinter
, hkeySubkey
;
2438 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
2439 debugstr_w(pKeyName
), debugstr_w(pValueName
), pType
, pData
, nSize
,
2442 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2446 if((ret
= RegOpenKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2448 WARN("Can't open subkey %s\n", debugstr_w(pKeyName
));
2449 RegCloseKey(hkeyPrinter
);
2453 ret
= RegQueryValueExW(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
2454 RegCloseKey(hkeySubkey
);
2455 RegCloseKey(hkeyPrinter
);
2459 /******************************************************************************
2460 * GetPrinterDataA (WINSPOOL)
2462 DWORD WINAPI
GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
,
2463 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2465 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
,
2466 pData
, nSize
, pcbNeeded
);
2469 /******************************************************************************
2470 * GetPrinterDataW (WINSPOOL)
2472 DWORD WINAPI
GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
,
2473 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2475 return GetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, pType
,
2476 pData
, nSize
, pcbNeeded
);
2479 /*******************************************************************************
2480 * EnumPrinterDataExW [WINSPOOL.197]
2482 DWORD WINAPI
EnumPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
,
2483 LPBYTE pEnumValues
, DWORD cbEnumValues
,
2484 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
2486 HKEY hkPrinter
, hkSubKey
;
2487 DWORD r
, ret
, dwIndex
, cValues
, cbMaxValueNameLen
,
2488 cbValueNameLen
, cbMaxValueLen
, cbValueLen
,
2493 PPRINTER_ENUM_VALUESW ppev
;
2495 TRACE ("%08x %s\n", hPrinter
, debugstr_w (pKeyName
));
2497 if (pKeyName
== NULL
|| *pKeyName
== 0)
2498 return ERROR_INVALID_PARAMETER
;
2500 ret
= WINSPOOL_GetOpenedPrinterRegKey (hPrinter
, &hkPrinter
);
2501 if (ret
!= ERROR_SUCCESS
)
2503 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%08x) returned %li\n",
2508 ret
= RegOpenKeyExW (hkPrinter
, pKeyName
, 0, KEY_READ
, &hkSubKey
);
2509 if (ret
!= ERROR_SUCCESS
)
2511 r
= RegCloseKey (hkPrinter
);
2512 if (r
!= ERROR_SUCCESS
)
2513 WARN ("RegCloseKey returned %li\n", r
);
2514 TRACE ("RegOpenKeyExW (%08x, %s) returned %li\n", hPrinter
,
2515 debugstr_w (pKeyName
), ret
);
2519 ret
= RegCloseKey (hkPrinter
);
2520 if (ret
!= ERROR_SUCCESS
)
2522 ERR ("RegCloseKey returned %li\n", ret
);
2523 r
= RegCloseKey (hkSubKey
);
2524 if (r
!= ERROR_SUCCESS
)
2525 WARN ("RegCloseKey returned %li\n", r
);
2529 ret
= RegQueryInfoKeyW (hkSubKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
2530 &cValues
, &cbMaxValueNameLen
, &cbMaxValueLen
, NULL
, NULL
);
2531 if (ret
!= ERROR_SUCCESS
)
2533 r
= RegCloseKey (hkSubKey
);
2534 if (r
!= ERROR_SUCCESS
)
2535 WARN ("RegCloseKey returned %li\n", r
);
2536 TRACE ("RegQueryInfoKeyW (%08x) returned %li\n", hkSubKey
, ret
);
2540 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
2541 "cbMaxValueLen = %li\n", cValues
, cbMaxValueNameLen
, cbMaxValueLen
);
2543 if (cValues
== 0) /* empty key */
2545 r
= RegCloseKey (hkSubKey
);
2546 if (r
!= ERROR_SUCCESS
)
2547 WARN ("RegCloseKey returned %li\n", r
);
2548 *pcbEnumValues
= *pnEnumValues
= 0;
2549 return ERROR_SUCCESS
;
2552 ++cbMaxValueNameLen
; /* allow for trailing '\0' */
2554 hHeap
= GetProcessHeap ();
2555 if (hHeap
== (HANDLE
) NULL
)
2557 ERR ("GetProcessHeap failed\n");
2558 r
= RegCloseKey (hkSubKey
);
2559 if (r
!= ERROR_SUCCESS
)
2560 WARN ("RegCloseKey returned %li\n", r
);
2561 return ERROR_OUTOFMEMORY
;
2564 lpValueName
= HeapAlloc (hHeap
, 0, cbMaxValueNameLen
* sizeof (WCHAR
));
2565 if (lpValueName
== NULL
)
2567 ERR ("Failed to allocate %li bytes from process heap\n",
2568 cbMaxValueNameLen
* sizeof (WCHAR
));
2569 r
= RegCloseKey (hkSubKey
);
2570 if (r
!= ERROR_SUCCESS
)
2571 WARN ("RegCloseKey returned %li\n", r
);
2572 return ERROR_OUTOFMEMORY
;
2575 lpValue
= HeapAlloc (hHeap
, 0, cbMaxValueLen
);
2576 if (lpValue
== NULL
)
2578 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen
);
2579 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2580 WARN ("HeapFree failed with code %li\n", GetLastError ());
2581 r
= RegCloseKey (hkSubKey
);
2582 if (r
!= ERROR_SUCCESS
)
2583 WARN ("RegCloseKey returned %li\n", r
);
2584 return ERROR_OUTOFMEMORY
;
2587 TRACE ("pass 1: calculating buffer required for all names and values\n");
2589 cbBufSize
= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
2591 TRACE ("%li bytes required for %li headers\n", cbBufSize
, cValues
);
2593 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
2595 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
2596 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
2597 NULL
, NULL
, lpValue
, &cbValueLen
);
2598 if (ret
!= ERROR_SUCCESS
)
2600 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2601 WARN ("HeapFree failed with code %li\n", GetLastError ());
2602 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2603 WARN ("HeapFree failed with code %li\n", GetLastError ());
2604 r
= RegCloseKey (hkSubKey
);
2605 if (r
!= ERROR_SUCCESS
)
2606 WARN ("RegCloseKey returned %li\n", r
);
2607 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
2611 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
2612 debugstr_w (lpValueName
), dwIndex
,
2613 (cbValueNameLen
+ 1) * sizeof (WCHAR
), cbValueLen
);
2615 cbBufSize
+= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
2616 cbBufSize
+= cbValueLen
;
2619 TRACE ("%li bytes required for all %li values\n", cbBufSize
, cValues
);
2621 *pcbEnumValues
= cbBufSize
;
2622 *pnEnumValues
= cValues
;
2624 if (cbEnumValues
< cbBufSize
) /* buffer too small */
2626 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2627 WARN ("HeapFree failed with code %li\n", GetLastError ());
2628 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2629 WARN ("HeapFree failed with code %li\n", GetLastError ());
2630 r
= RegCloseKey (hkSubKey
);
2631 if (r
!= ERROR_SUCCESS
)
2632 WARN ("RegCloseKey returned %li\n", r
);
2633 TRACE ("%li byte buffer is not large enough\n", cbEnumValues
);
2634 return ERROR_MORE_DATA
;
2637 TRACE ("pass 2: copying all names and values to buffer\n");
2639 ppev
= (PPRINTER_ENUM_VALUESW
) pEnumValues
; /* array of structs */
2640 pEnumValues
+= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
2642 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
2644 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
2645 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
2646 NULL
, &dwType
, lpValue
, &cbValueLen
);
2647 if (ret
!= ERROR_SUCCESS
)
2649 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2650 WARN ("HeapFree failed with code %li\n", GetLastError ());
2651 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2652 WARN ("HeapFree failed with code %li\n", GetLastError ());
2653 r
= RegCloseKey (hkSubKey
);
2654 if (r
!= ERROR_SUCCESS
)
2655 WARN ("RegCloseKey returned %li\n", r
);
2656 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
2660 cbValueNameLen
= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
2661 memcpy (pEnumValues
, lpValueName
, cbValueNameLen
);
2662 ppev
[dwIndex
].pValueName
= (LPWSTR
) pEnumValues
;
2663 pEnumValues
+= cbValueNameLen
;
2665 /* return # of *bytes* (including trailing \0), not # of chars */
2666 ppev
[dwIndex
].cbValueName
= cbValueNameLen
;
2668 ppev
[dwIndex
].dwType
= dwType
;
2670 memcpy (pEnumValues
, lpValue
, cbValueLen
);
2671 ppev
[dwIndex
].pData
= pEnumValues
;
2672 pEnumValues
+= cbValueLen
;
2674 ppev
[dwIndex
].cbData
= cbValueLen
;
2676 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
2677 debugstr_w (lpValueName
), dwIndex
, cbValueNameLen
, cbValueLen
);
2680 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2682 ret
= GetLastError ();
2683 ERR ("HeapFree failed with code %li\n", ret
);
2684 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2685 WARN ("HeapFree failed with code %li\n", GetLastError ());
2686 r
= RegCloseKey (hkSubKey
);
2687 if (r
!= ERROR_SUCCESS
)
2688 WARN ("RegCloseKey returned %li\n", r
);
2692 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2694 ret
= GetLastError ();
2695 ERR ("HeapFree failed with code %li\n", ret
);
2696 r
= RegCloseKey (hkSubKey
);
2697 if (r
!= ERROR_SUCCESS
)
2698 WARN ("RegCloseKey returned %li\n", r
);
2702 ret
= RegCloseKey (hkSubKey
);
2703 if (ret
!= ERROR_SUCCESS
)
2705 ERR ("RegCloseKey returned %li\n", ret
);
2709 return ERROR_SUCCESS
;
2712 /*******************************************************************************
2713 * EnumPrinterDataExA [WINSPOOL.196]
2715 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
2716 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
2717 * what Windows 2000 SP1 does.
2720 DWORD WINAPI
EnumPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
,
2721 LPBYTE pEnumValues
, DWORD cbEnumValues
,
2722 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
2726 DWORD ret
, dwIndex
, dwBufSize
;
2730 TRACE ("%08x %s\n", hPrinter
, pKeyName
);
2732 if (pKeyName
== NULL
|| *pKeyName
== 0)
2733 return ERROR_INVALID_PARAMETER
;
2735 len
= MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, NULL
, 0);
2738 ret
= GetLastError ();
2739 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
2743 hHeap
= GetProcessHeap ();
2744 if (hHeap
== (HANDLE
) NULL
)
2746 ERR ("GetProcessHeap failed\n");
2747 return ERROR_OUTOFMEMORY
;
2750 pKeyNameW
= HeapAlloc (hHeap
, 0, len
* sizeof (WCHAR
));
2751 if (pKeyNameW
== NULL
)
2753 ERR ("Failed to allocate %li bytes from process heap\n",
2754 (LONG
) len
* sizeof (WCHAR
));
2755 return ERROR_OUTOFMEMORY
;
2758 if (MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, pKeyNameW
, len
) == 0)
2760 ret
= GetLastError ();
2761 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
2762 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
2763 WARN ("HeapFree failed with code %li\n", GetLastError ());
2767 ret
= EnumPrinterDataExW (hPrinter
, pKeyNameW
, pEnumValues
, cbEnumValues
,
2768 pcbEnumValues
, pnEnumValues
);
2769 if (ret
!= ERROR_SUCCESS
)
2771 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
2772 WARN ("HeapFree failed with code %li\n", GetLastError ());
2773 TRACE ("EnumPrinterDataExW returned %li\n", ret
);
2777 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
2779 ret
= GetLastError ();
2780 ERR ("HeapFree failed with code %li\n", ret
);
2784 if (*pnEnumValues
== 0) /* empty key */
2785 return ERROR_SUCCESS
;
2788 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
2790 PPRINTER_ENUM_VALUESW ppev
=
2791 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
2793 if (dwBufSize
< ppev
->cbValueName
)
2794 dwBufSize
= ppev
->cbValueName
;
2796 if (dwBufSize
< ppev
->cbData
&& (ppev
->dwType
== REG_SZ
||
2797 ppev
->dwType
== REG_EXPAND_SZ
|| ppev
->dwType
== REG_MULTI_SZ
))
2798 dwBufSize
= ppev
->cbData
;
2801 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize
);
2803 pBuffer
= HeapAlloc (hHeap
, 0, dwBufSize
);
2804 if (pBuffer
== NULL
)
2806 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize
);
2807 return ERROR_OUTOFMEMORY
;
2810 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
2812 PPRINTER_ENUM_VALUESW ppev
=
2813 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
2815 len
= WideCharToMultiByte (CP_ACP
, 0, ppev
->pValueName
,
2816 ppev
->cbValueName
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
,
2820 ret
= GetLastError ();
2821 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
2822 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
2823 WARN ("HeapFree failed with code %li\n", GetLastError ());
2827 memcpy (ppev
->pValueName
, pBuffer
, len
);
2829 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
2831 if (ppev
->dwType
!= REG_SZ
&& ppev
->dwType
!= REG_EXPAND_SZ
&&
2832 ppev
->dwType
!= REG_MULTI_SZ
)
2835 len
= WideCharToMultiByte (CP_ACP
, 0, (LPWSTR
) ppev
->pData
,
2836 ppev
->cbData
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
, NULL
);
2839 ret
= GetLastError ();
2840 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
2841 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
2842 WARN ("HeapFree failed with code %li\n", GetLastError ());
2846 memcpy (ppev
->pData
, pBuffer
, len
);
2848 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
2849 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
2852 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
2854 ret
= GetLastError ();
2855 ERR ("HeapFree failed with code %li\n", ret
);
2859 return ERROR_SUCCESS
;