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"
26 DEFAULT_DEBUG_CHANNEL(winspool
);
28 typedef struct _OPENEDPRINTER
30 LPWSTR lpsPrinterName
;
32 } OPENEDPRINTER
, *LPOPENEDPRINTER
;
34 /* The OpenedPrinter Table dynamic array */
35 static HDPA pOpenedPrinterDPA
= NULL
;
37 extern HDPA
WINAPI (*WINSPOOL_DPA_CreateEx
) (INT
, HANDLE
);
38 extern LPVOID
WINAPI (*WINSPOOL_DPA_GetPtr
) (const HDPA
, INT
);
39 extern INT
WINAPI (*WINSPOOL_DPA_InsertPtr
) (const HDPA
, INT
, LPVOID
);
41 static DWORD
WINAPI (*GDI_CallDeviceCapabilities16
)( LPCSTR lpszDevice
, LPCSTR lpszPort
,
42 WORD fwCapability
, LPSTR lpszOutput
,
44 static INT
WINAPI (*GDI_CallExtDeviceMode16
)( HWND hwnd
, LPDEVMODEA lpdmOutput
,
45 LPSTR lpszDevice
, LPSTR lpszPort
,
46 LPDEVMODEA lpdmInput
, LPSTR lpszProfile
,
49 static char Printers
[] =
50 "System\\CurrentControlSet\\control\\Print\\Printers\\";
51 static char Drivers
[] =
52 "System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
54 static WCHAR DefaultEnvironmentW
[] = {'W','i','n','e',0};
56 static WCHAR Configuration_FileW
[] = {'C','o','n','f','i','g','u','r','a','t',
57 'i','o','n',' ','F','i','l','e',0};
58 static WCHAR DatatypeW
[] = {'D','a','t','a','t','y','p','e',0};
59 static WCHAR Data_FileW
[] = {'D','a','t','a',' ','F','i','l','e',0};
60 static WCHAR Default_DevModeW
[] = {'D','e','f','a','u','l','t',' ','D','e','v',
62 static WCHAR Dependent_FilesW
[] = {'D','e','p','e','n','d','e','n','t',' ','F',
64 static WCHAR DescriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
65 static WCHAR DriverW
[] = {'D','r','i','v','e','r',0};
66 static WCHAR Help_FileW
[] = {'H','e','l','p',' ','F','i','l','e',0};
67 static WCHAR LocationW
[] = {'L','o','c','a','t','i','o','n',0};
68 static WCHAR MonitorW
[] = {'M','o','n','i','t','o','r',0};
69 static WCHAR NameW
[] = {'N','a','m','e',0};
70 static WCHAR ParametersW
[] = {'P','a','r','a','m','e','t','e','r','s',0};
71 static WCHAR PortW
[] = {'P','o','r','t',0};
72 static WCHAR Print_ProcessorW
[] = {'P','r','i','n','t',' ','P','r','o','c','e',
74 static WCHAR Printer_DriverW
[] = {'P','r','i','n','t','e','r',' ','D','r','i',
76 static WCHAR PrinterDriverDataW
[] = {'P','r','i','n','t','e','r','D','r','i',
77 'v','e','r','D','a','t','a',0};
78 static WCHAR Separator_FileW
[] = {'S','e','p','a','r','a','t','o','r',' ','F',
80 static WCHAR Share_NameW
[] = {'S','h','a','r','e',' ','N','a','m','e',0};
81 static WCHAR WinPrintW
[] = {'W','i','n','P','r','i','n','t',0};
83 /******************************************************************
84 * WINSPOOL_GetOpenedPrinterEntry
85 * Get the first place empty in the opened printer table
87 static LPOPENEDPRINTER
WINSPOOL_GetOpenedPrinterEntry()
90 LPOPENEDPRINTER pOpenedPrinter
;
93 * Create the opened printers' handle dynamic array.
95 if (!pOpenedPrinterDPA
)
97 pOpenedPrinterDPA
= WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
98 for (i
= 0; i
< 10; i
++)
100 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
102 sizeof(OPENEDPRINTER
));
103 pOpenedPrinter
->hPrinter
= -1;
104 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
109 * Search for a handle not yet allocated.
111 for (i
= 0; i
< pOpenedPrinterDPA
->nItemCount
; i
++)
113 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, i
);
115 if (pOpenedPrinter
->hPrinter
== -1)
117 pOpenedPrinter
->hPrinter
= i
+ 1;
118 return pOpenedPrinter
;
123 * Didn't find one, insert new element in the array.
125 if (i
== pOpenedPrinterDPA
->nItemCount
)
127 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
129 sizeof(OPENEDPRINTER
));
130 pOpenedPrinter
->hPrinter
= i
+ 1;
131 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
132 return pOpenedPrinter
;
138 /******************************************************************
139 * WINSPOOL_GetOpenedPrinter
140 * Get the pointer to the opened printer referred by the handle
142 static LPOPENEDPRINTER
WINSPOOL_GetOpenedPrinter(int printerHandle
)
144 LPOPENEDPRINTER pOpenedPrinter
;
146 if(!pOpenedPrinterDPA
) return NULL
;
147 if((printerHandle
<=0) ||
148 (printerHandle
> (pOpenedPrinterDPA
->nItemCount
- 1)))
151 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, printerHandle
-1);
153 return pOpenedPrinter
;
156 /******************************************************************
157 * WINSPOOL_GetOpenedPrinterRegKey
160 static DWORD
WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter
, HKEY
*phkey
)
162 LPOPENEDPRINTER lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
167 return ERROR_INVALID_HANDLE
;
169 if((ret
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
)) !=
173 if(RegOpenKeyW(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, phkey
)
175 ERR("Can't find opened printer %s in registry\n",
176 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
177 RegCloseKey(hkeyPrinters
);
178 return ERROR_INVALID_PRINTER_NAME
; /* ? */
180 RegCloseKey(hkeyPrinters
);
181 return ERROR_SUCCESS
;
184 /***********************************************************
187 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
190 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
193 Formname
= (dmA
->dmSize
> off_formname
);
194 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
195 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
198 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
199 dmA
->dmSize
- CCHDEVICENAME
);
201 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
202 off_formname
- CCHDEVICENAME
);
203 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
205 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
206 (off_formname
+ CCHFORMNAME
));
209 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
214 /***********************************************************
216 * Creates a unicode copy of supplied devmode on heap
218 static LPDEVMODEW
DEVMODEdupAtoW(HANDLE heap
, const DEVMODEA
*dmA
)
223 ptrdiff_t off_formname
;
226 if(!dmA
) return NULL
;
228 off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
229 Formname
= (dmA
->dmSize
> off_formname
);
230 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
231 dmW
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmA
->dmDriverExtra
);
232 return DEVMODEcpyAtoW(dmW
, dmA
);
235 /***********************************************************
237 * Creates an ascii copy of supplied devmode on heap
239 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
244 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
246 if(!dmW
) return NULL
;
247 Formname
= (dmW
->dmSize
> off_formname
);
248 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
249 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
250 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
251 CCHDEVICENAME
, NULL
, NULL
);
253 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
254 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
256 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
257 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
258 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
259 CCHFORMNAME
, NULL
, NULL
);
260 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
261 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
264 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
269 /***********************************************************
271 * Creates a unicode copy of PRINTER_INFO_2A on heap
273 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
275 LPPRINTER_INFO_2W piW
;
276 if(!piA
) return NULL
;
277 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
278 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
279 piW
->pServerName
= HEAP_strdupAtoW(heap
, 0, piA
->pServerName
);
280 piW
->pPrinterName
= HEAP_strdupAtoW(heap
, 0, piA
->pPrinterName
);
281 piW
->pShareName
= HEAP_strdupAtoW(heap
, 0, piA
->pShareName
);
282 piW
->pPortName
= HEAP_strdupAtoW(heap
, 0, piA
->pPortName
);
283 piW
->pDriverName
= HEAP_strdupAtoW(heap
, 0, piA
->pDriverName
);
284 piW
->pComment
= HEAP_strdupAtoW(heap
, 0, piA
->pComment
);
285 piW
->pLocation
= HEAP_strdupAtoW(heap
, 0, piA
->pLocation
);
286 piW
->pDevMode
= DEVMODEdupAtoW(heap
, piA
->pDevMode
);
287 piW
->pSepFile
= HEAP_strdupAtoW(heap
, 0, piA
->pSepFile
);
288 piW
->pPrintProcessor
= HEAP_strdupAtoW(heap
, 0, piA
->pPrintProcessor
);
289 piW
->pDatatype
= HEAP_strdupAtoW(heap
, 0, piA
->pDatatype
);
290 piW
->pParameters
= HEAP_strdupAtoW(heap
, 0, piA
->pParameters
);
294 /***********************************************************
295 * FREE_PRINTER_INFO_2W
296 * Free PRINTER_INFO_2W and all strings
298 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
302 HeapFree(heap
,0,piW
->pServerName
);
303 HeapFree(heap
,0,piW
->pPrinterName
);
304 HeapFree(heap
,0,piW
->pShareName
);
305 HeapFree(heap
,0,piW
->pPortName
);
306 HeapFree(heap
,0,piW
->pDriverName
);
307 HeapFree(heap
,0,piW
->pComment
);
308 HeapFree(heap
,0,piW
->pLocation
);
309 HeapFree(heap
,0,piW
->pDevMode
);
310 HeapFree(heap
,0,piW
->pSepFile
);
311 HeapFree(heap
,0,piW
->pPrintProcessor
);
312 HeapFree(heap
,0,piW
->pDatatype
);
313 HeapFree(heap
,0,piW
->pParameters
);
314 HeapFree(heap
,0,piW
);
318 /******************************************************************
319 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
322 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
323 LPSTR pOutput
, LPDEVMODEA lpdm
)
327 if (!GDI_CallDeviceCapabilities16
)
329 GDI_CallDeviceCapabilities16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
331 if (!GDI_CallDeviceCapabilities16
) return -1;
333 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
335 /* If DC_PAPERSIZE map POINT16s to POINTs */
336 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
337 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
338 POINT
*pt
= (POINT
*)pOutput
;
340 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
341 for(i
= 0; i
< ret
; i
++, pt
++)
346 HeapFree( GetProcessHeap(), 0, tmp
);
352 /*****************************************************************************
353 * DeviceCapabilitiesW [WINSPOOL.152]
355 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
358 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
359 WORD fwCapability
, LPWSTR pOutput
,
360 const DEVMODEW
*pDevMode
)
362 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
363 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
364 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
367 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
368 fwCapability
== DC_FILEDEPENDENCIES
||
369 fwCapability
== DC_PAPERNAMES
)) {
370 /* These need A -> W translation */
373 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
377 switch(fwCapability
) {
382 case DC_FILEDEPENDENCIES
:
386 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
387 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
389 for(i
= 0; i
< ret
; i
++)
390 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
391 pOutput
+ (i
* size
), size
);
392 HeapFree(GetProcessHeap(), 0, pOutputA
);
394 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
395 (LPSTR
)pOutput
, dmA
);
397 HeapFree(GetProcessHeap(),0,pPortA
);
398 HeapFree(GetProcessHeap(),0,pDeviceA
);
399 HeapFree(GetProcessHeap(),0,dmA
);
403 /******************************************************************
404 * DocumentPropertiesA [WINSPOOL.155]
407 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
408 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
409 LPDEVMODEA pDevModeInput
,DWORD fMode
)
411 LPOPENEDPRINTER lpOpenedPrinter
;
412 LPSTR lpName
= pDeviceName
;
415 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
416 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
421 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
422 if(!lpOpenedPrinter
) {
423 SetLastError(ERROR_INVALID_HANDLE
);
426 lpNameW
= lpOpenedPrinter
->lpsPrinterName
;
427 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
430 if (!GDI_CallExtDeviceMode16
)
432 GDI_CallExtDeviceMode16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
434 if (!GDI_CallExtDeviceMode16
) return -1;
436 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
437 pDevModeInput
, NULL
, fMode
);
440 HeapFree(GetProcessHeap(),0,lpName
);
445 /*****************************************************************************
446 * DocumentPropertiesW
448 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
450 LPDEVMODEW pDevModeOutput
,
451 LPDEVMODEW pDevModeInput
, DWORD fMode
)
454 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
455 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
456 LPDEVMODEA pDevModeOutputA
= NULL
;
459 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
460 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
463 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
464 if(ret
< 0) return ret
;
465 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
467 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
468 pDevModeInputA
, fMode
);
470 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
471 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
473 if(fMode
== 0 && ret
> 0)
474 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
475 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
476 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
480 /******************************************************************
481 * OpenPrinterA [WINSPOOL.196]
484 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
485 LPPRINTER_DEFAULTSA pDefault
)
487 LPWSTR lpPrinterNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName
);
488 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
492 DefaultW
.pDatatype
= HEAP_strdupAtoW(GetProcessHeap(), 0,
493 pDefault
->pDatatype
);
494 DefaultW
.pDevMode
= DEVMODEdupAtoW(GetProcessHeap(),
496 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
497 pDefaultW
= &DefaultW
;
499 ret
= OpenPrinterW(lpPrinterNameW
, phPrinter
, pDefaultW
);
501 HeapFree(GetProcessHeap(), 0, DefaultW
.pDatatype
);
502 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
504 HeapFree(GetProcessHeap(), 0, lpPrinterNameW
);
508 /******************************************************************
509 * OpenPrinterW [WINSPOOL.197]
512 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
513 LPPRINTER_DEFAULTSW pDefault
)
515 LPOPENEDPRINTER lpOpenedPrinter
;
516 HKEY hkeyPrinters
, hkeyPrinter
;
518 if (!lpPrinterName
) {
519 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
520 SetLastError(ERROR_INVALID_PARAMETER
);
524 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
527 /* Check Printer exists */
528 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
530 ERR("Can't create Printers key\n");
531 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
535 if(RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
537 WARN("Can't find printer %s in registry\n", debugstr_w(lpPrinterName
));
538 RegCloseKey(hkeyPrinters
);
539 SetLastError(ERROR_INVALID_PARAMETER
);
542 RegCloseKey(hkeyPrinter
);
543 RegCloseKey(hkeyPrinters
);
545 if(!phPrinter
) /* This seems to be what win95 does anyway */
548 /* Get a place in the opened printer buffer*/
549 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterEntry();
550 if(!lpOpenedPrinter
) {
551 ERR("Can't allocate printer slot\n");
552 SetLastError(ERROR_OUTOFMEMORY
);
556 /* Get the name of the printer */
557 lpOpenedPrinter
->lpsPrinterName
= HeapAlloc( GetProcessHeap(), 0,
558 (strlenW(lpPrinterName
)+1)*sizeof(WCHAR
) );
559 strcpyW( lpOpenedPrinter
->lpsPrinterName
, lpPrinterName
);
561 /* Get the unique handle of the printer*/
562 *phPrinter
= lpOpenedPrinter
->hPrinter
;
564 if (pDefault
!= NULL
)
565 FIXME("Not handling pDefault\n");
570 /******************************************************************
571 * AddMonitorA [WINSPOOL.107]
574 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
576 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
577 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
581 /******************************************************************
582 * DeletePrinterDriverA [WINSPOOL.146]
586 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
588 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
589 debugstr_a(pDriverName
));
590 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
595 /******************************************************************
596 * DeleteMonitorA [WINSPOOL.135]
600 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
602 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
603 debugstr_a(pMonitorName
));
604 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
609 /******************************************************************
610 * DeletePortA [WINSPOOL.137]
614 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
616 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
617 debugstr_a(pPortName
));
618 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
622 /******************************************************************************
623 * SetPrinterW [WINSPOOL.214]
633 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
637 /******************************************************************************
638 * WritePrinter [WINSPOOL.223]
648 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
652 /*****************************************************************************
653 * AddFormA [WINSPOOL.103]
655 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
657 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
661 /*****************************************************************************
662 * AddFormW [WINSPOOL.104]
664 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
666 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
670 /*****************************************************************************
671 * AddJobA [WINSPOOL.105]
673 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
674 DWORD cbBuf
, LPDWORD pcbNeeded
)
676 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
681 /*****************************************************************************
682 * AddJobW [WINSPOOL.106]
684 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
687 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
692 /*****************************************************************************
693 * WINSPOOL_OpenDriverReg [internal]
695 * opens the registry for the printer drivers depending on the given input
696 * variable pEnvironment
699 * the opened hkey on success
702 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
)
704 LPSTR lpKey
, p
= NULL
;
707 (unicode
) ? debugstr_w(pEnvironment
) : debugstr_a(pEnvironment
));
710 p
= (unicode
) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
) :
714 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
716 if(!GetVersionExA( &ver
))
719 switch (ver
.dwPlatformId
) {
720 case VER_PLATFORM_WIN32s
:
722 case VER_PLATFORM_WIN32_NT
:
723 p
= "Windows NT x86";
729 TRACE("set environment to %s\n", p
);
732 lpKey
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
733 strlen(p
) + strlen(Drivers
));
734 sprintf( lpKey
, Drivers
, p
);
736 TRACE("%s\n", lpKey
);
738 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, lpKey
, &retval
) !=
742 if(pEnvironment
&& unicode
)
743 HeapFree( GetProcessHeap(), 0, p
);
744 HeapFree( GetProcessHeap(), 0, lpKey
);
749 /*****************************************************************************
750 * AddPrinterW [WINSPOOL.122]
752 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
754 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
758 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
761 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
764 FIXME("pName = %s - unsupported\n", debugstr_w(pName
));
765 SetLastError(ERROR_INVALID_PARAMETER
);
769 WARN("Level = %ld\n", Level
);
770 SetLastError(ERROR_INVALID_LEVEL
);
774 SetLastError(ERROR_INVALID_PARAMETER
);
777 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
779 ERR("Can't create Printers key\n");
782 if(RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) ==
784 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
785 RegCloseKey(hkeyPrinter
);
786 RegCloseKey(hkeyPrinters
);
789 hkeyDrivers
= WINSPOOL_OpenDriverReg( NULL
, TRUE
);
791 ERR("Can't create Drivers key\n");
792 RegCloseKey(hkeyPrinters
);
795 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
797 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
798 RegCloseKey(hkeyPrinters
);
799 RegCloseKey(hkeyDrivers
);
800 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
803 RegCloseKey(hkeyDriver
);
804 RegCloseKey(hkeyDrivers
);
806 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
807 WARN("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
808 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
809 RegCloseKey(hkeyPrinters
);
813 /* See if we can load the driver. We may need the devmode structure anyway
815 size
= DocumentPropertiesW(0, -1, pi
->pPrinterName
, NULL
, NULL
, 0);
817 WARN("DocumentProperties fails\n");
818 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
824 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
825 DocumentPropertiesW(0, -1, pi
->pPrinterName
, dmW
, NULL
, DM_OUT_BUFFER
);
828 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
830 WARN("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
831 SetLastError(ERROR_INVALID_PRINTER_NAME
);
832 RegCloseKey(hkeyPrinters
);
834 HeapFree(GetProcessHeap(), 0, dmW
);
837 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
838 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
839 RegSetValueExW(hkeyPrinter
, DatatypeW
, 0, REG_SZ
, (LPBYTE
)pi
->pDatatype
,
842 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
843 and we support these drivers. NT writes DEVMODEW so somehow
844 we'll need to distinguish between these when we support NT
846 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
847 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
, (LPBYTE
)dmA
,
848 dmA
->dmSize
+ dmA
->dmDriverExtra
);
849 HeapFree(GetProcessHeap(), 0, dmA
);
851 HeapFree(GetProcessHeap(), 0, dmW
);
852 RegSetValueExW(hkeyPrinter
, DescriptionW
, 0, REG_SZ
, (LPBYTE
)pi
->pComment
,
854 RegSetValueExW(hkeyPrinter
, LocationW
, 0, REG_SZ
, (LPBYTE
)pi
->pLocation
,
856 RegSetValueExW(hkeyPrinter
, NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pPrinterName
, 0);
857 RegSetValueExW(hkeyPrinter
, ParametersW
, 0, REG_SZ
,
858 (LPBYTE
)pi
->pParameters
, 0);
859 RegSetValueExW(hkeyPrinter
, PortW
, 0, REG_SZ
, (LPBYTE
)pi
->pPortName
, 0);
860 RegSetValueExW(hkeyPrinter
, Print_ProcessorW
, 0, REG_SZ
,
861 (LPBYTE
)pi
->pPrintProcessor
, 0);
862 RegSetValueExW(hkeyPrinter
, Printer_DriverW
, 0, REG_SZ
,
863 (LPBYTE
)pi
->pDriverName
, 0);
864 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
865 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
866 RegSetValueExW(hkeyPrinter
, Separator_FileW
, 0, REG_SZ
,
867 (LPBYTE
)pi
->pSepFile
, 0);
868 RegSetValueExW(hkeyPrinter
, Share_NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pShareName
,
870 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
871 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
872 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
873 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
874 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
875 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
877 RegCloseKey(hkeyPrinter
);
878 RegCloseKey(hkeyPrinters
);
879 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
880 ERR("OpenPrinter failing\n");
886 /*****************************************************************************
887 * AddPrinterA [WINSPOOL.117]
889 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
892 PRINTER_INFO_2W
*piW
;
893 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
896 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
898 WARN("Level = %ld\n", Level
);
899 SetLastError(ERROR_INVALID_LEVEL
);
902 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
903 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
905 ret
= AddPrinterW(pNameW
, Level
, (LPBYTE
)piW
);
907 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
908 HeapFree(GetProcessHeap(),0,pNameW
);
913 /*****************************************************************************
914 * ClosePrinter [WINSPOOL.126]
916 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
918 LPOPENEDPRINTER lpOpenedPrinter
;
920 TRACE("Handle %d\n", hPrinter
);
922 if (!pOpenedPrinterDPA
)
925 if ((hPrinter
!= -1) && (hPrinter
< (pOpenedPrinterDPA
->nItemCount
- 1)))
927 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
928 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter
->lpsPrinterName
);
929 lpOpenedPrinter
->lpsPrinterName
= NULL
;
930 lpOpenedPrinter
->hPrinter
= -1;
937 /*****************************************************************************
938 * DeleteFormA [WINSPOOL.133]
940 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
942 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
946 /*****************************************************************************
947 * DeleteFormW [WINSPOOL.134]
949 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
951 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
955 /*****************************************************************************
956 * DeletePrinter [WINSPOOL.143]
958 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
963 LPOPENEDPRINTER lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
964 if(!lpOpenedPrinter
) {
965 SetLastError(ERROR_INVALID_HANDLE
);
968 lpNameW
= lpOpenedPrinter
->lpsPrinterName
;
969 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
971 ERR("Can't open Printers key\n");
975 /* This should use a recursive delete see Q142491 or SHDeleteKey */
976 if(RegDeleteKeyW(hkeyPrinters
, lpNameW
) == ERROR_SUCCESS
) {
977 SetLastError(ERROR_PRINTER_NOT_FOUND
); /* ?? */
978 RegCloseKey(hkeyPrinters
);
982 ClosePrinter(hPrinter
);
986 /*****************************************************************************
987 * SetPrinterA [WINSPOOL.211]
989 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
992 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
996 /*****************************************************************************
997 * SetJobA [WINSPOOL.209]
999 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1000 LPBYTE pJob
, DWORD Command
)
1002 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1007 /*****************************************************************************
1008 * SetJobW [WINSPOOL.210]
1010 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1011 LPBYTE pJob
, DWORD Command
)
1013 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1018 /*****************************************************************************
1019 * GetFormA [WINSPOOL.181]
1021 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1022 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1024 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1025 Level
,pForm
,cbBuf
,pcbNeeded
);
1029 /*****************************************************************************
1030 * GetFormW [WINSPOOL.182]
1032 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1033 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1035 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1036 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1040 /*****************************************************************************
1041 * SetFormA [WINSPOOL.207]
1043 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1046 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1050 /*****************************************************************************
1051 * SetFormW [WINSPOOL.208]
1053 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1056 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1060 /*****************************************************************************
1061 * ReadPrinter [WINSPOOL.202]
1063 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1064 LPDWORD pNoBytesRead
)
1066 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1070 /*****************************************************************************
1071 * ResetPrinterA [WINSPOOL.203]
1073 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1075 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1079 /*****************************************************************************
1080 * ResetPrinterW [WINSPOOL.204]
1082 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1084 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1088 /*****************************************************************************
1089 * WINSPOOL_GetDWORDFromReg
1091 * Return DWORD associated with ValueName from hkey.
1093 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
1095 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
1098 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
1100 if(ret
!= ERROR_SUCCESS
) {
1101 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
1104 if(type
!= REG_DWORD
) {
1105 ERR("Got type %ld\n", type
);
1111 /*****************************************************************************
1112 * WINSPOOL_GetStringFromReg
1114 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1115 * String is stored either as unicode or ascii.
1116 * Bit of a hack here to get the ValueName if we want ascii.
1118 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1119 DWORD buflen
, DWORD
*needed
,
1122 DWORD sz
= buflen
, type
;
1126 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1128 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1129 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1130 HeapFree(GetProcessHeap(),0,ValueNameA
);
1132 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1133 WARN("Got ret = %ld\n", ret
);
1141 /*****************************************************************************
1142 * WINSPOOL_GetDevModeFromReg
1144 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1145 * DevMode is stored either as unicode or ascii.
1147 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1149 DWORD buflen
, DWORD
*needed
,
1152 DWORD sz
= buflen
, type
;
1155 if (ptr
) memset(ptr
, 0, sizeof(DEVMODEA
));
1156 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1157 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1158 if (sz
< sizeof(DEVMODEA
))
1160 ERR("corrupted registry for %s\n", debugstr_w(ValueName
));
1161 sz
= sizeof(DEVMODEA
);
1163 /* ensures that dmSize is not erratically bogus if registry is invalid */
1164 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1165 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1167 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1169 DEVMODEW
*dmW
= DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA
*)ptr
);
1170 memcpy(ptr
, dmW
, sz
);
1171 HeapFree(GetProcessHeap(),0,dmW
);
1178 /*********************************************************************
1179 * WINSPOOL_GetPrinter_2
1181 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1182 * The strings are either stored as unicode or ascii.
1184 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1185 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1188 DWORD size
, left
= cbBuf
;
1189 BOOL space
= (cbBuf
> 0);
1194 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1196 if(space
&& size
<= left
) {
1197 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1204 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1206 if(space
&& size
<= left
) {
1207 pi2
->pShareName
= (LPWSTR
)ptr
;
1214 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1216 if(space
&& size
<= left
) {
1217 pi2
->pPortName
= (LPWSTR
)ptr
;
1224 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1226 if(space
&& size
<= left
) {
1227 pi2
->pDriverName
= (LPWSTR
)ptr
;
1234 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1236 if(space
&& size
<= left
) {
1237 pi2
->pComment
= (LPWSTR
)ptr
;
1244 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1246 if(space
&& size
<= left
) {
1247 pi2
->pLocation
= (LPWSTR
)ptr
;
1254 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1256 if(space
&& size
<= left
) {
1257 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1264 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1266 if(space
&& size
<= left
) {
1267 pi2
->pSepFile
= (LPWSTR
)ptr
;
1274 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1276 if(space
&& size
<= left
) {
1277 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1284 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1286 if(space
&& size
<= left
) {
1287 pi2
->pDatatype
= (LPWSTR
)ptr
;
1294 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1296 if(space
&& size
<= left
) {
1297 pi2
->pParameters
= (LPWSTR
)ptr
;
1305 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1306 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1307 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1308 "Default Priority");
1309 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1310 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1313 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1314 memset(pi2
, 0, sizeof(*pi2
));
1319 /*********************************************************************
1320 * WINSPOOL_GetPrinter_4
1322 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1324 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1325 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1328 DWORD size
, left
= cbBuf
;
1329 BOOL space
= (cbBuf
> 0);
1334 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1336 if(space
&& size
<= left
) {
1337 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1345 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1348 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1349 memset(pi4
, 0, sizeof(*pi4
));
1354 /*********************************************************************
1355 * WINSPOOL_GetPrinter_5
1357 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1359 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1360 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1363 DWORD size
, left
= cbBuf
;
1364 BOOL space
= (cbBuf
> 0);
1369 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1371 if(space
&& size
<= left
) {
1372 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1379 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1381 if(space
&& size
<= left
) {
1382 pi5
->pPortName
= (LPWSTR
)ptr
;
1390 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1391 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1393 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1397 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1398 memset(pi5
, 0, sizeof(*pi5
));
1403 /*****************************************************************************
1404 * WINSPOOL_GetPrinter
1406 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1407 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1408 * just a collection of pointers to strings.
1410 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1411 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1413 OPENEDPRINTER
*lpOpenedPrinter
;
1414 DWORD size
, needed
= 0;
1416 HKEY hkeyPrinter
, hkeyPrinters
;
1419 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1421 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1422 if(!lpOpenedPrinter
) {
1423 SetLastError(ERROR_INVALID_HANDLE
);
1426 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1428 ERR("Can't create Printers key\n");
1431 if(RegOpenKeyW(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1433 ERR("Can't find opened printer %s in registry\n",
1434 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1435 RegCloseKey(hkeyPrinters
);
1436 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1443 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
1445 size
= sizeof(PRINTER_INFO_2W
);
1447 ptr
= pPrinter
+ size
;
1449 memset(pPrinter
, 0, size
);
1454 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
1462 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
1464 size
= sizeof(PRINTER_INFO_4W
);
1466 ptr
= pPrinter
+ size
;
1468 memset(pPrinter
, 0, size
);
1473 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
1482 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
1484 size
= sizeof(PRINTER_INFO_5W
);
1486 ptr
= pPrinter
+ size
;
1488 memset(pPrinter
, 0, size
);
1494 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
1501 FIXME("Unimplemented level %ld\n", Level
);
1502 SetLastError(ERROR_INVALID_LEVEL
);
1503 RegCloseKey(hkeyPrinters
);
1504 RegCloseKey(hkeyPrinter
);
1508 RegCloseKey(hkeyPrinter
);
1509 RegCloseKey(hkeyPrinters
);
1511 TRACE("returing %d needed = %ld\n", ret
, needed
);
1512 if(pcbNeeded
) *pcbNeeded
= needed
;
1514 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1518 /*****************************************************************************
1519 * GetPrinterW [WINSPOOL.194]
1521 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1522 DWORD cbBuf
, LPDWORD pcbNeeded
)
1524 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1528 /*****************************************************************************
1529 * GetPrinterA [WINSPOOL.187]
1531 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1532 DWORD cbBuf
, LPDWORD pcbNeeded
)
1534 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1538 /*****************************************************************************
1539 * WINSPOOL_EnumPrinters
1541 * Implementation of EnumPrintersA|W
1543 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
1544 DWORD dwLevel
, LPBYTE lpbPrinters
,
1545 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1546 LPDWORD lpdwReturned
, BOOL unicode
)
1549 HKEY hkeyPrinters
, hkeyPrinter
;
1550 WCHAR PrinterName
[255];
1551 DWORD needed
= 0, number
= 0;
1552 DWORD used
, i
, left
;
1556 memset(lpbPrinters
, 0, cbBuf
);
1562 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1563 if(dwType
== PRINTER_ENUM_DEFAULT
)
1566 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
1567 FIXME("dwType = %08lx\n", dwType
);
1568 SetLastError(ERROR_INVALID_FLAGS
);
1572 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1574 ERR("Can't create Printers key\n");
1578 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
1579 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
1580 RegCloseKey(hkeyPrinters
);
1581 ERR("Can't query Printers key\n");
1584 TRACE("Found %ld printers\n", number
);
1588 RegCloseKey(hkeyPrinters
);
1590 *lpdwReturned
= number
;
1594 used
= number
* sizeof(PRINTER_INFO_2W
);
1597 used
= number
* sizeof(PRINTER_INFO_4W
);
1600 used
= number
* sizeof(PRINTER_INFO_5W
);
1604 SetLastError(ERROR_INVALID_LEVEL
);
1605 RegCloseKey(hkeyPrinters
);
1608 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
1610 for(i
= 0; i
< number
; i
++) {
1611 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
1613 ERR("Can't enum key number %ld\n", i
);
1614 RegCloseKey(hkeyPrinters
);
1617 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
1618 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
1620 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
1621 RegCloseKey(hkeyPrinters
);
1626 buf
= lpbPrinters
+ used
;
1627 left
= cbBuf
- used
;
1635 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
1636 left
, &needed
, unicode
);
1638 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
1641 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
1642 left
, &needed
, unicode
);
1644 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
1647 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
1648 left
, &needed
, unicode
);
1650 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
1653 ERR("Shouldn't be here!\n");
1654 RegCloseKey(hkeyPrinter
);
1655 RegCloseKey(hkeyPrinters
);
1658 RegCloseKey(hkeyPrinter
);
1660 RegCloseKey(hkeyPrinters
);
1667 memset(lpbPrinters
, 0, cbBuf
);
1668 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1672 *lpdwReturned
= number
;
1673 SetLastError(ERROR_SUCCESS
);
1678 /******************************************************************
1679 * EnumPrintersW [WINSPOOL.175]
1681 * Enumerates the available printers, print servers and print
1682 * providers, depending on the specified flags, name and level.
1686 * If level is set to 1:
1687 * Not implemented yet!
1688 * Returns TRUE with an empty list.
1690 * If level is set to 2:
1691 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1692 * Returns an array of PRINTER_INFO_2 data structures in the
1693 * lpbPrinters buffer. Note that according to MSDN also an
1694 * OpenPrinter should be performed on every remote printer.
1696 * If level is set to 4 (officially WinNT only):
1697 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1698 * Fast: Only the registry is queried to retrieve printer names,
1699 * no connection to the driver is made.
1700 * Returns an array of PRINTER_INFO_4 data structures in the
1701 * lpbPrinters buffer.
1703 * If level is set to 5 (officially WinNT4/Win9x only):
1704 * Fast: Only the registry is queried to retrieve printer names,
1705 * no connection to the driver is made.
1706 * Returns an array of PRINTER_INFO_5 data structures in the
1707 * lpbPrinters buffer.
1709 * If level set to 3 or 6+:
1710 * returns zero (faillure!)
1712 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
1716 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1717 * - Only levels 2, 4 and 5 are implemented at the moment.
1718 * - 16-bit printer drivers are not enumerated.
1719 * - Returned amount of bytes used/needed does not match the real Windoze
1720 * implementation (as in this implementation, all strings are part
1721 * of the buffer, whereas Win32 keeps them somewhere else)
1722 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1725 * - In a regular Wine installation, no registry settings for printers
1726 * exist, which makes this function return an empty list.
1728 BOOL WINAPI
EnumPrintersW(
1729 DWORD dwType
, /* [in] Types of print objects to enumerate */
1730 LPWSTR lpszName
, /* [in] name of objects to enumerate */
1731 DWORD dwLevel
, /* [in] type of printer info structure */
1732 LPBYTE lpbPrinters
, /* [out] buffer which receives info */
1733 DWORD cbBuf
, /* [in] max size of buffer in bytes */
1734 LPDWORD lpdwNeeded
, /* [out] pointer to var: # bytes used/needed */
1735 LPDWORD lpdwReturned
/* [out] number of entries returned */
1738 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
1739 lpdwNeeded
, lpdwReturned
, TRUE
);
1742 /******************************************************************
1743 * EnumPrintersA [WINSPOOL.174]
1746 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
1747 DWORD dwLevel
, LPBYTE lpbPrinters
,
1748 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1749 LPDWORD lpdwReturned
)
1752 LPWSTR lpszNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpszName
);
1754 ret
= WINSPOOL_EnumPrinters(dwType
, lpszNameW
, dwLevel
, lpbPrinters
, cbBuf
,
1755 lpdwNeeded
, lpdwReturned
, FALSE
);
1756 HeapFree(GetProcessHeap(),0,lpszNameW
);
1760 /*****************************************************************************
1761 * WINSPOOL_GetDriverInfoFromReg [internal]
1763 * Enters the information from the registry into the DRIVER_INFO struct
1766 * zero if the printer driver does not exist in the registry
1767 * (only if Level > 1) otherwise nonzero
1769 static BOOL
WINSPOOL_GetDriverInfoFromReg(
1772 LPWSTR pEnvironment
,
1774 LPBYTE ptr
, /* DRIVER_INFO */
1775 LPBYTE pDriverStrings
, /* strings buffer */
1776 DWORD cbBuf
, /* size of string buffer */
1777 LPDWORD pcbNeeded
, /* space needed for str. */
1778 BOOL unicode
) /* type of strings */
1779 { DWORD dw
, size
, tmp
, type
;
1781 LPBYTE strPtr
= pDriverStrings
;
1783 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
1784 debugstr_w(DriverName
), debugstr_w(pEnvironment
),
1785 Level
, ptr
, pDriverStrings
, cbBuf
, unicode
);
1788 *pcbNeeded
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
1789 if (*pcbNeeded
<= cbBuf
)
1790 strcpyW((LPWSTR
)strPtr
, DriverName
);
1792 *pcbNeeded
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0,
1794 if(*pcbNeeded
<= cbBuf
)
1795 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, strPtr
, *pcbNeeded
,
1800 ((PDRIVER_INFO_1W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1804 ((PDRIVER_INFO_3W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1805 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1808 if(RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
) != ERROR_SUCCESS
) {
1809 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName
));
1810 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
1815 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
, &size
) !=
1817 WARN("Can't get Version\n");
1819 ((PDRIVER_INFO_3A
) ptr
)->cVersion
= dw
;
1822 pEnvironment
= DefaultEnvironmentW
;
1824 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
1826 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
1829 if(*pcbNeeded
<= cbBuf
) {
1831 strcpyW((LPWSTR
)strPtr
, pEnvironment
);
1833 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, strPtr
, size
,
1836 ((PDRIVER_INFO_3W
) ptr
)->pEnvironment
= (LPWSTR
)strPtr
;
1837 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1840 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, 0, &size
,
1843 if(*pcbNeeded
<= cbBuf
)
1844 WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, size
, &tmp
,
1847 ((PDRIVER_INFO_3W
) ptr
)->pDriverPath
= (LPWSTR
)strPtr
;
1848 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1851 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, 0, &size
,
1854 if(*pcbNeeded
<= cbBuf
)
1855 WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, size
,
1858 ((PDRIVER_INFO_3W
) ptr
)->pDataFile
= (LPWSTR
)strPtr
;
1859 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1862 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1863 0, &size
, unicode
)) {
1865 if(*pcbNeeded
<= cbBuf
)
1866 WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1867 size
, &tmp
, unicode
);
1869 ((PDRIVER_INFO_3W
) ptr
)->pConfigFile
= (LPWSTR
)strPtr
;
1870 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1874 RegCloseKey(hkeyDriver
);
1875 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1879 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
, 0, &size
,
1882 if(*pcbNeeded
<= cbBuf
)
1883 WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
,
1884 size
, &tmp
, unicode
);
1886 ((PDRIVER_INFO_3W
) ptr
)->pHelpFile
= (LPWSTR
)strPtr
;
1887 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1890 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
, 0,
1893 if(*pcbNeeded
<= cbBuf
)
1894 WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
,
1895 size
, &tmp
, unicode
);
1897 ((PDRIVER_INFO_3W
) ptr
)->pDependentFiles
= (LPWSTR
)strPtr
;
1898 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1901 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
, 0, &size
,
1904 if(*pcbNeeded
<= cbBuf
)
1905 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1906 size
, &tmp
, unicode
);
1908 ((PDRIVER_INFO_3W
) ptr
)->pMonitorName
= (LPWSTR
)strPtr
;
1909 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1912 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, strPtr
, 0, &size
,
1915 if(*pcbNeeded
<= cbBuf
)
1916 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1917 size
, &tmp
, unicode
);
1919 ((PDRIVER_INFO_3W
) ptr
)->pDefaultDataType
= (LPWSTR
)strPtr
;
1920 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1923 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1924 RegCloseKey(hkeyDriver
);
1928 /*****************************************************************************
1929 * WINSPOOL_GetPrinterDriver
1931 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
1932 DWORD Level
, LPBYTE pDriverInfo
,
1933 DWORD cbBuf
, LPDWORD pcbNeeded
,
1936 OPENEDPRINTER
*lpOpenedPrinter
;
1937 WCHAR DriverName
[100];
1938 DWORD ret
, type
, size
, needed
= 0;
1940 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDrivers
;
1942 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
1943 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1945 ZeroMemory(pDriverInfo
, cbBuf
);
1947 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1948 if(!lpOpenedPrinter
) {
1949 SetLastError(ERROR_INVALID_HANDLE
);
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
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1963 ERR("Can't find opened printer %s in registry\n",
1964 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1965 RegCloseKey(hkeyPrinters
);
1966 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1969 size
= sizeof(DriverName
);
1970 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
1971 (LPBYTE
)DriverName
, &size
);
1972 RegCloseKey(hkeyPrinter
);
1973 RegCloseKey(hkeyPrinters
);
1974 if(ret
!= ERROR_SUCCESS
) {
1975 ERR("Can't get DriverName for printer %s\n",
1976 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1980 hkeyDrivers
= WINSPOOL_OpenDriverReg( pEnvironment
, TRUE
);
1982 ERR("Can't create Drivers key\n");
1988 size
= sizeof(DRIVER_INFO_1W
);
1991 size
= sizeof(DRIVER_INFO_2W
);
1994 size
= sizeof(DRIVER_INFO_3W
);
1997 ERR("Invalid level\n");
2002 ptr
= pDriverInfo
+ size
;
2004 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverName
,
2005 pEnvironment
, Level
, pDriverInfo
,
2006 (cbBuf
< size
) ? NULL
: ptr
,
2007 (cbBuf
< size
) ? 0 : cbBuf
- size
,
2008 &needed
, unicode
)) {
2009 RegCloseKey(hkeyDrivers
);
2013 RegCloseKey(hkeyDrivers
);
2015 if(pcbNeeded
) *pcbNeeded
= size
+ needed
;
2016 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
2017 if(cbBuf
>= needed
) return TRUE
;
2018 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2022 /*****************************************************************************
2023 * GetPrinterDriverA [WINSPOOL.190]
2025 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
2026 DWORD Level
, LPBYTE pDriverInfo
,
2027 DWORD cbBuf
, LPDWORD pcbNeeded
)
2030 LPWSTR pEnvW
= HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment
);
2031 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pEnvW
, Level
, pDriverInfo
,
2032 cbBuf
, pcbNeeded
, FALSE
);
2033 HeapFree(GetProcessHeap(),0,pEnvW
);
2036 /*****************************************************************************
2037 * GetPrinterDriverW [WINSPOOL.193]
2039 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
2040 DWORD Level
, LPBYTE pDriverInfo
,
2041 DWORD cbBuf
, LPDWORD pcbNeeded
)
2043 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
2044 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
2047 /*****************************************************************************
2048 * GetPrinterDriverDirectoryA [WINSPOOL.191]
2050 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
2051 DWORD Level
, LPBYTE pDriverDirectory
,
2052 DWORD cbBuf
, LPDWORD pcbNeeded
)
2056 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName
, pEnvironment
, Level
,
2057 pDriverDirectory
, cbBuf
, pcbNeeded
);
2059 FIXME("pName = `%s' - unsupported\n", pName
);
2060 SetLastError(ERROR_INVALID_PARAMETER
);
2063 if(pEnvironment
!= NULL
) {
2064 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment
);
2065 SetLastError(ERROR_INVALID_ENVIRONMENT
);
2068 if(Level
!= 1) /* win95 ignores this so we just carry on */
2069 WARN("Level = %ld - assuming 1\n", Level
);
2071 /* FIXME should read from registry */
2072 needed
= GetSystemDirectoryA(pDriverDirectory
, cbBuf
);
2075 *pcbNeeded
= needed
;
2076 if(needed
> cbBuf
) {
2077 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2084 /*****************************************************************************
2085 * GetPrinterDriverDirectoryW [WINSPOOL.192]
2087 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
2088 DWORD Level
, LPBYTE pDriverDirectory
,
2089 DWORD cbBuf
, LPDWORD pcbNeeded
)
2091 LPSTR pNameA
= NULL
, pEnvironmentA
= NULL
;
2095 pNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pName
);
2097 pEnvironmentA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
);
2098 ret
= GetPrinterDriverDirectoryA( pNameA
, pEnvironmentA
, Level
,
2099 pDriverDirectory
, cbBuf
, pcbNeeded
);
2101 HeapFree( GetProcessHeap(), 0, pNameA
);
2103 HeapFree( GetProcessHeap(), 0, pEnvironmentA
);
2108 /*****************************************************************************
2109 * AddPrinterDriverA [WINSPOOL.120]
2111 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
2114 HKEY hkeyDrivers
, hkeyName
;
2116 TRACE("(%s,%ld,%p)\n",pName
,level
,pDriverInfo
);
2118 if(level
!= 2 && level
!= 3) {
2119 SetLastError(ERROR_INVALID_LEVEL
);
2123 FIXME("pName= `%s' - unsupported\n", pName
);
2124 SetLastError(ERROR_INVALID_PARAMETER
);
2128 WARN("pDriverInfo == NULL");
2129 SetLastError(ERROR_INVALID_PARAMETER
);
2134 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
2136 memset(&di3
, 0, sizeof(di3
));
2137 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
2140 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
2142 SetLastError(ERROR_INVALID_PARAMETER
);
2145 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
2146 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
2147 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
2148 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
2150 hkeyDrivers
= WINSPOOL_OpenDriverReg(di3
.pEnvironment
, FALSE
);
2153 ERR("Can't create Drivers key\n");
2157 if(level
== 2) { /* apparently can't overwrite with level2 */
2158 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2159 RegCloseKey(hkeyName
);
2160 RegCloseKey(hkeyDrivers
);
2161 WARN("Trying to create existing printer driver `%s'\n", di3
.pName
);
2162 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2166 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2167 RegCloseKey(hkeyDrivers
);
2168 ERR("Can't create Name key\n");
2171 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2173 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2174 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2175 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2177 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2178 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2179 di3
.pDependentFiles
, 0);
2180 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2181 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2182 RegCloseKey(hkeyName
);
2183 RegCloseKey(hkeyDrivers
);
2187 /*****************************************************************************
2188 * AddPrinterDriverW [WINSPOOL.121]
2190 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2193 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2199 /*****************************************************************************
2200 * PrinterProperties [WINSPOOL.201]
2202 * Displays a dialog to set the properties of the printer.
2205 * nonzero on succes or zero on faillure
2208 * implemented as stub only
2210 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* [in] handle to parent window */
2211 HANDLE hPrinter
/* [in] handle to printer object */
2213 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
2214 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2218 /*****************************************************************************
2219 * EnumJobsA [WINSPOOL.162]
2222 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2223 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2227 if(pcbNeeded
) *pcbNeeded
= 0;
2228 if(pcReturned
) *pcReturned
= 0;
2233 /*****************************************************************************
2234 * EnumJobsW [WINSPOOL.163]
2237 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2238 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2242 if(pcbNeeded
) *pcbNeeded
= 0;
2243 if(pcReturned
) *pcReturned
= 0;
2247 /*****************************************************************************
2248 * WINSPOOL_EnumPrinterDrivers [internal]
2250 * Delivers information about all installed printer drivers installed on
2251 * localhost or a given server
2254 * nonzero on succes or zero on failure, if the buffer for the returned
2255 * information is too small the function will return an error
2258 * - only implemented for localhost, foreign hosts will return an error
2260 static BOOL
WINSPOOL_EnumPrinterDrivers(LPWSTR pName
, LPWSTR pEnvironment
,
2261 DWORD Level
, LPBYTE pDriverInfo
,
2262 DWORD cbBuf
, LPDWORD pcbNeeded
,
2263 LPDWORD pcReturned
, BOOL unicode
)
2266 DWORD i
, needed
, number
= 0, size
= 0;
2267 WCHAR DriverNameW
[255];
2270 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2271 debugstr_w(pName
), debugstr_w(pEnvironment
),
2272 Level
, pDriverInfo
, cbBuf
, unicode
);
2274 /* check for local drivers */
2276 ERR("remote drivers unsupported! Current remote host is %s\n",
2281 /* check input parameter */
2282 if((Level
< 1) || (Level
> 3)) {
2283 ERR("unsupported level %ld \n", Level
);
2287 /* initialize return values */
2289 memset( pDriverInfo
, 0, cbBuf
);
2293 hkeyDrivers
= WINSPOOL_OpenDriverReg(pEnvironment
, TRUE
);
2295 ERR("Can't open Drivers key\n");
2299 if(RegQueryInfoKeyA(hkeyDrivers
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2300 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2301 RegCloseKey(hkeyDrivers
);
2302 ERR("Can't query Drivers key\n");
2305 TRACE("Found %ld Drivers\n", number
);
2307 /* get size of single struct
2308 * unicode and ascii structure have the same size
2312 size
= sizeof(DRIVER_INFO_1A
);
2315 size
= sizeof(DRIVER_INFO_2A
);
2318 size
= sizeof(DRIVER_INFO_3A
);
2322 /* calculate required buffer size */
2323 *pcbNeeded
= size
* number
;
2325 for( i
= 0, ptr
= (pDriverInfo
&& (cbBuf
>= size
)) ? pDriverInfo
: NULL
;
2327 i
++, ptr
= (ptr
&& (cbBuf
>= size
* i
)) ? ptr
+ size
: NULL
) {
2328 if(RegEnumKeyW(hkeyDrivers
, i
, DriverNameW
, sizeof(DriverNameW
))
2330 ERR("Can't enum key number %ld\n", i
);
2331 RegCloseKey(hkeyDrivers
);
2334 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverNameW
,
2335 pEnvironment
, Level
, ptr
,
2336 (cbBuf
< *pcbNeeded
) ? NULL
: pDriverInfo
+ *pcbNeeded
,
2337 (cbBuf
< *pcbNeeded
) ? 0 : cbBuf
- *pcbNeeded
,
2338 &needed
, unicode
)) {
2339 RegCloseKey(hkeyDrivers
);
2342 (*pcbNeeded
) += needed
;
2345 RegCloseKey(hkeyDrivers
);
2347 if(cbBuf
< *pcbNeeded
){
2348 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2355 /*****************************************************************************
2356 * EnumPrinterDriversW [WINSPOOL.173]
2358 * see function EnumPrinterDrivers for RETURNS, BUGS
2360 BOOL WINAPI
EnumPrinterDriversW(LPWSTR pName
, LPWSTR pEnvironment
, DWORD Level
,
2361 LPBYTE pDriverInfo
, DWORD cbBuf
,
2362 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2364 return WINSPOOL_EnumPrinterDrivers(pName
, pEnvironment
, Level
, pDriverInfo
,
2365 cbBuf
, pcbNeeded
, pcReturned
, TRUE
);
2368 /*****************************************************************************
2369 * EnumPrinterDriversA [WINSPOOL.172]
2371 * see function EnumPrinterDrivers for RETURNS, BUGS
2373 BOOL WINAPI
EnumPrinterDriversA(LPSTR pName
, LPSTR pEnvironment
, DWORD Level
,
2374 LPBYTE pDriverInfo
, DWORD cbBuf
,
2375 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2377 WCHAR
*pNameW
= NULL
, *pEnvironmentW
= NULL
;
2380 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
2382 pEnvironmentW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment
);
2384 ret
= WINSPOOL_EnumPrinterDrivers(pNameW
, pEnvironmentW
, Level
, pDriverInfo
,
2385 cbBuf
, pcbNeeded
, pcReturned
, FALSE
);
2387 HeapFree(GetProcessHeap(), 0, pNameW
);
2389 HeapFree(GetProcessHeap(), 0, pEnvironmentW
);
2395 /******************************************************************************
2396 * EnumPortsA (WINSPOOL.166)
2398 BOOL WINAPI
EnumPortsA(LPSTR name
,DWORD level
,LPBYTE ports
,DWORD bufsize
,
2399 LPDWORD bufneeded
,LPDWORD bufreturned
)
2401 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name
,level
,ports
,bufsize
,bufneeded
,bufreturned
);
2405 /******************************************************************************
2406 * SetPrinterDataExA (WINSPOOL)
2408 DWORD WINAPI
SetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2409 LPSTR pValueName
, DWORD Type
,
2410 LPBYTE pData
, DWORD cbData
)
2412 HKEY hkeyPrinter
, hkeySubkey
;
2415 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_a(pKeyName
),
2416 debugstr_a(pValueName
), Type
, pData
, cbData
);
2418 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2422 if((ret
= RegCreateKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2424 ERR("Can't create subkey %s\n", debugstr_a(pKeyName
));
2425 RegCloseKey(hkeyPrinter
);
2428 ret
= RegSetValueExA(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2429 RegCloseKey(hkeySubkey
);
2430 RegCloseKey(hkeyPrinter
);
2434 /******************************************************************************
2435 * SetPrinterDataExW (WINSPOOL)
2437 DWORD WINAPI
SetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
2438 LPWSTR pValueName
, DWORD Type
,
2439 LPBYTE pData
, DWORD cbData
)
2441 HKEY hkeyPrinter
, hkeySubkey
;
2444 TRACE("(%08x, %s, %s %08lx, %p, %08lx)\n", hPrinter
, debugstr_w(pKeyName
),
2445 debugstr_w(pValueName
), Type
, pData
, cbData
);
2447 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2451 if((ret
= RegCreateKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2453 ERR("Can't create subkey %s\n", debugstr_w(pKeyName
));
2454 RegCloseKey(hkeyPrinter
);
2457 ret
= RegSetValueExW(hkeySubkey
, pValueName
, 0, Type
, pData
, cbData
);
2458 RegCloseKey(hkeySubkey
);
2459 RegCloseKey(hkeyPrinter
);
2463 /******************************************************************************
2464 * SetPrinterDataA (WINSPOOL)
2466 DWORD WINAPI
SetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, DWORD Type
,
2467 LPBYTE pData
, DWORD cbData
)
2469 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
,
2473 /******************************************************************************
2474 * SetPrinterDataW (WINSPOOL)
2476 DWORD WINAPI
SetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, DWORD Type
,
2477 LPBYTE pData
, DWORD cbData
)
2479 return SetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, Type
,
2483 /******************************************************************************
2484 * GetPrinterDataExA (WINSPOOL)
2486 DWORD WINAPI
GetPrinterDataExA(HANDLE hPrinter
, LPSTR pKeyName
,
2487 LPSTR pValueName
, LPDWORD pType
,
2488 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2490 HKEY hkeyPrinter
, hkeySubkey
;
2493 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
2494 debugstr_a(pKeyName
), debugstr_a(pValueName
), pType
, pData
, nSize
,
2497 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2501 if((ret
= RegOpenKeyA(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2503 WARN("Can't open subkey %s\n", debugstr_a(pKeyName
));
2504 RegCloseKey(hkeyPrinter
);
2508 ret
= RegQueryValueExA(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
2509 RegCloseKey(hkeySubkey
);
2510 RegCloseKey(hkeyPrinter
);
2514 /******************************************************************************
2515 * GetPrinterDataExW (WINSPOOL)
2517 DWORD WINAPI
GetPrinterDataExW(HANDLE hPrinter
, LPWSTR pKeyName
,
2518 LPWSTR pValueName
, LPDWORD pType
,
2519 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2521 HKEY hkeyPrinter
, hkeySubkey
;
2524 TRACE("(%08x, %s, %s %p, %p, %08lx, %p)\n", hPrinter
,
2525 debugstr_w(pKeyName
), debugstr_w(pValueName
), pType
, pData
, nSize
,
2528 if((ret
= WINSPOOL_GetOpenedPrinterRegKey(hPrinter
, &hkeyPrinter
))
2532 if((ret
= RegOpenKeyW(hkeyPrinter
, pKeyName
, &hkeySubkey
))
2534 WARN("Can't open subkey %s\n", debugstr_w(pKeyName
));
2535 RegCloseKey(hkeyPrinter
);
2539 ret
= RegQueryValueExW(hkeySubkey
, pValueName
, 0, pType
, pData
, pcbNeeded
);
2540 RegCloseKey(hkeySubkey
);
2541 RegCloseKey(hkeyPrinter
);
2545 /******************************************************************************
2546 * GetPrinterDataA (WINSPOOL)
2548 DWORD WINAPI
GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
,
2549 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2551 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
,
2552 pData
, nSize
, pcbNeeded
);
2555 /******************************************************************************
2556 * GetPrinterDataW (WINSPOOL)
2558 DWORD WINAPI
GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
,
2559 LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
2561 return GetPrinterDataExW(hPrinter
, PrinterDriverDataW
, pValueName
, pType
,
2562 pData
, nSize
, pcbNeeded
);
2565 /*******************************************************************************
2566 * EnumPrinterDataExW [WINSPOOL.197]
2568 DWORD WINAPI
EnumPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
,
2569 LPBYTE pEnumValues
, DWORD cbEnumValues
,
2570 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
2572 HKEY hkPrinter
, hkSubKey
;
2573 DWORD r
, ret
, dwIndex
, cValues
, cbMaxValueNameLen
,
2574 cbValueNameLen
, cbMaxValueLen
, cbValueLen
,
2579 PPRINTER_ENUM_VALUESW ppev
;
2581 TRACE ("%08x %s\n", hPrinter
, debugstr_w (pKeyName
));
2583 if (pKeyName
== NULL
|| *pKeyName
== 0)
2584 return ERROR_INVALID_PARAMETER
;
2586 ret
= WINSPOOL_GetOpenedPrinterRegKey (hPrinter
, &hkPrinter
);
2587 if (ret
!= ERROR_SUCCESS
)
2589 TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%08x) returned %li\n",
2594 ret
= RegOpenKeyExW (hkPrinter
, pKeyName
, 0, KEY_READ
, &hkSubKey
);
2595 if (ret
!= ERROR_SUCCESS
)
2597 r
= RegCloseKey (hkPrinter
);
2598 if (r
!= ERROR_SUCCESS
)
2599 WARN ("RegCloseKey returned %li\n", r
);
2600 TRACE ("RegOpenKeyExW (%08x, %s) returned %li\n", hPrinter
,
2601 debugstr_w (pKeyName
), ret
);
2605 ret
= RegCloseKey (hkPrinter
);
2606 if (ret
!= ERROR_SUCCESS
)
2608 ERR ("RegCloseKey returned %li\n", ret
);
2609 r
= RegCloseKey (hkSubKey
);
2610 if (r
!= ERROR_SUCCESS
)
2611 WARN ("RegCloseKey returned %li\n", r
);
2615 ret
= RegQueryInfoKeyW (hkSubKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
2616 &cValues
, &cbMaxValueNameLen
, &cbMaxValueLen
, NULL
, NULL
);
2617 if (ret
!= ERROR_SUCCESS
)
2619 r
= RegCloseKey (hkSubKey
);
2620 if (r
!= ERROR_SUCCESS
)
2621 WARN ("RegCloseKey returned %li\n", r
);
2622 TRACE ("RegQueryInfoKeyW (%08x) returned %li\n", hkSubKey
, ret
);
2626 TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, "
2627 "cbMaxValueLen = %li\n", cValues
, cbMaxValueNameLen
, cbMaxValueLen
);
2629 if (cValues
== 0) /* empty key */
2631 r
= RegCloseKey (hkSubKey
);
2632 if (r
!= ERROR_SUCCESS
)
2633 WARN ("RegCloseKey returned %li\n", r
);
2634 *pcbEnumValues
= *pnEnumValues
= 0;
2635 return ERROR_SUCCESS
;
2638 ++cbMaxValueNameLen
; /* allow for trailing '\0' */
2640 hHeap
= GetProcessHeap ();
2641 if (hHeap
== (HANDLE
) NULL
)
2643 ERR ("GetProcessHeap failed\n");
2644 r
= RegCloseKey (hkSubKey
);
2645 if (r
!= ERROR_SUCCESS
)
2646 WARN ("RegCloseKey returned %li\n", r
);
2647 return ERROR_OUTOFMEMORY
;
2650 lpValueName
= HeapAlloc (hHeap
, 0, cbMaxValueNameLen
* sizeof (WCHAR
));
2651 if (lpValueName
== NULL
)
2653 ERR ("Failed to allocate %li bytes from process heap\n",
2654 cbMaxValueNameLen
* sizeof (WCHAR
));
2655 r
= RegCloseKey (hkSubKey
);
2656 if (r
!= ERROR_SUCCESS
)
2657 WARN ("RegCloseKey returned %li\n", r
);
2658 return ERROR_OUTOFMEMORY
;
2661 lpValue
= HeapAlloc (hHeap
, 0, cbMaxValueLen
);
2662 if (lpValue
== NULL
)
2664 ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen
);
2665 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2666 WARN ("HeapFree failed with code %li\n", GetLastError ());
2667 r
= RegCloseKey (hkSubKey
);
2668 if (r
!= ERROR_SUCCESS
)
2669 WARN ("RegCloseKey returned %li\n", r
);
2670 return ERROR_OUTOFMEMORY
;
2673 TRACE ("pass 1: calculating buffer required for all names and values\n");
2675 cbBufSize
= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
2677 TRACE ("%li bytes required for %li headers\n", cbBufSize
, cValues
);
2679 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
2681 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
2682 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
2683 NULL
, NULL
, lpValue
, &cbValueLen
);
2684 if (ret
!= ERROR_SUCCESS
)
2686 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2687 WARN ("HeapFree failed with code %li\n", GetLastError ());
2688 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2689 WARN ("HeapFree failed with code %li\n", GetLastError ());
2690 r
= RegCloseKey (hkSubKey
);
2691 if (r
!= ERROR_SUCCESS
)
2692 WARN ("RegCloseKey returned %li\n", r
);
2693 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
2697 TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n",
2698 debugstr_w (lpValueName
), dwIndex
,
2699 (cbValueNameLen
+ 1) * sizeof (WCHAR
), cbValueLen
);
2701 cbBufSize
+= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
2702 cbBufSize
+= cbValueLen
;
2705 TRACE ("%li bytes required for all %li values\n", cbBufSize
, cValues
);
2707 *pcbEnumValues
= cbBufSize
;
2708 *pnEnumValues
= cValues
;
2710 if (cbEnumValues
< cbBufSize
) /* buffer too small */
2712 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2713 WARN ("HeapFree failed with code %li\n", GetLastError ());
2714 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2715 WARN ("HeapFree failed with code %li\n", GetLastError ());
2716 r
= RegCloseKey (hkSubKey
);
2717 if (r
!= ERROR_SUCCESS
)
2718 WARN ("RegCloseKey returned %li\n", r
);
2719 TRACE ("%li byte buffer is not large enough\n", cbEnumValues
);
2720 return ERROR_MORE_DATA
;
2723 TRACE ("pass 2: copying all names and values to buffer\n");
2725 ppev
= (PPRINTER_ENUM_VALUESW
) pEnumValues
; /* array of structs */
2726 pEnumValues
+= cValues
* sizeof (PRINTER_ENUM_VALUESW
);
2728 for (dwIndex
= 0; dwIndex
< cValues
; ++dwIndex
)
2730 cbValueNameLen
= cbMaxValueNameLen
; cbValueLen
= cbMaxValueLen
;
2731 ret
= RegEnumValueW (hkSubKey
, dwIndex
, lpValueName
, &cbValueNameLen
,
2732 NULL
, &dwType
, lpValue
, &cbValueLen
);
2733 if (ret
!= ERROR_SUCCESS
)
2735 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2736 WARN ("HeapFree failed with code %li\n", GetLastError ());
2737 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2738 WARN ("HeapFree failed with code %li\n", GetLastError ());
2739 r
= RegCloseKey (hkSubKey
);
2740 if (r
!= ERROR_SUCCESS
)
2741 WARN ("RegCloseKey returned %li\n", r
);
2742 TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex
, ret
);
2746 cbValueNameLen
= (cbValueNameLen
+ 1) * sizeof (WCHAR
);
2747 memcpy (pEnumValues
, lpValueName
, cbValueNameLen
);
2748 ppev
[dwIndex
].pValueName
= (LPWSTR
) pEnumValues
;
2749 pEnumValues
+= cbValueNameLen
;
2751 /* return # of *bytes* (including trailing \0), not # of chars */
2752 ppev
[dwIndex
].cbValueName
= cbValueNameLen
;
2754 ppev
[dwIndex
].dwType
= dwType
;
2756 memcpy (pEnumValues
, lpValue
, cbValueLen
);
2757 ppev
[dwIndex
].pData
= pEnumValues
;
2758 pEnumValues
+= cbValueLen
;
2760 ppev
[dwIndex
].cbData
= cbValueLen
;
2762 TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n",
2763 debugstr_w (lpValueName
), dwIndex
, cbValueNameLen
, cbValueLen
);
2766 if (HeapFree (hHeap
, 0, lpValue
) == 0)
2768 ret
= GetLastError ();
2769 ERR ("HeapFree failed with code %li\n", ret
);
2770 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2771 WARN ("HeapFree failed with code %li\n", GetLastError ());
2772 r
= RegCloseKey (hkSubKey
);
2773 if (r
!= ERROR_SUCCESS
)
2774 WARN ("RegCloseKey returned %li\n", r
);
2778 if (HeapFree (hHeap
, 0, lpValueName
) == 0)
2780 ret
= GetLastError ();
2781 ERR ("HeapFree failed with code %li\n", ret
);
2782 r
= RegCloseKey (hkSubKey
);
2783 if (r
!= ERROR_SUCCESS
)
2784 WARN ("RegCloseKey returned %li\n", r
);
2788 ret
= RegCloseKey (hkSubKey
);
2789 if (ret
!= ERROR_SUCCESS
)
2791 ERR ("RegCloseKey returned %li\n", ret
);
2795 return ERROR_SUCCESS
;
2798 /*******************************************************************************
2799 * EnumPrinterDataExA [WINSPOOL.196]
2801 * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and
2802 * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is
2803 * what Windows 2000 SP1 does.
2806 DWORD WINAPI
EnumPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
,
2807 LPBYTE pEnumValues
, DWORD cbEnumValues
,
2808 LPDWORD pcbEnumValues
, LPDWORD pnEnumValues
)
2812 DWORD ret
, dwIndex
, dwBufSize
;
2816 TRACE ("%08x %s\n", hPrinter
, pKeyName
);
2818 if (pKeyName
== NULL
|| *pKeyName
== 0)
2819 return ERROR_INVALID_PARAMETER
;
2821 len
= MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, NULL
, 0);
2824 ret
= GetLastError ();
2825 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
2829 hHeap
= GetProcessHeap ();
2830 if (hHeap
== (HANDLE
) NULL
)
2832 ERR ("GetProcessHeap failed\n");
2833 return ERROR_OUTOFMEMORY
;
2836 pKeyNameW
= HeapAlloc (hHeap
, 0, len
* sizeof (WCHAR
));
2837 if (pKeyNameW
== NULL
)
2839 ERR ("Failed to allocate %li bytes from process heap\n",
2840 (LONG
) len
* sizeof (WCHAR
));
2841 return ERROR_OUTOFMEMORY
;
2844 if (MultiByteToWideChar (CP_ACP
, 0, pKeyName
, -1, pKeyNameW
, len
) == 0)
2846 ret
= GetLastError ();
2847 ERR ("MultiByteToWideChar failed with code %li\n", ret
);
2848 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
2849 WARN ("HeapFree failed with code %li\n", GetLastError ());
2853 ret
= EnumPrinterDataExW (hPrinter
, pKeyNameW
, pEnumValues
, cbEnumValues
,
2854 pcbEnumValues
, pnEnumValues
);
2855 if (ret
!= ERROR_SUCCESS
)
2857 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
2858 WARN ("HeapFree failed with code %li\n", GetLastError ());
2859 TRACE ("EnumPrinterDataExW returned %li\n", ret
);
2863 if (HeapFree (hHeap
, 0, pKeyNameW
) == 0)
2865 ret
= GetLastError ();
2866 ERR ("HeapFree failed with code %li\n", ret
);
2870 if (*pnEnumValues
== 0) /* empty key */
2871 return ERROR_SUCCESS
;
2874 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
2876 PPRINTER_ENUM_VALUESW ppev
=
2877 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
2879 if (dwBufSize
< ppev
->cbValueName
)
2880 dwBufSize
= ppev
->cbValueName
;
2882 if (dwBufSize
< ppev
->cbData
&& (ppev
->dwType
== REG_SZ
||
2883 ppev
->dwType
== REG_EXPAND_SZ
|| ppev
->dwType
== REG_MULTI_SZ
))
2884 dwBufSize
= ppev
->cbData
;
2887 TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize
);
2889 pBuffer
= HeapAlloc (hHeap
, 0, dwBufSize
);
2890 if (pBuffer
== NULL
)
2892 ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize
);
2893 return ERROR_OUTOFMEMORY
;
2896 for (dwIndex
= 0; dwIndex
< *pnEnumValues
; ++dwIndex
)
2898 PPRINTER_ENUM_VALUESW ppev
=
2899 &((PPRINTER_ENUM_VALUESW
) pEnumValues
)[dwIndex
];
2901 len
= WideCharToMultiByte (CP_ACP
, 0, ppev
->pValueName
,
2902 ppev
->cbValueName
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
,
2906 ret
= GetLastError ();
2907 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
2908 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
2909 WARN ("HeapFree failed with code %li\n", GetLastError ());
2913 memcpy (ppev
->pValueName
, pBuffer
, len
);
2915 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
2917 if (ppev
->dwType
!= REG_SZ
&& ppev
->dwType
!= REG_EXPAND_SZ
&&
2918 ppev
->dwType
!= REG_MULTI_SZ
)
2921 len
= WideCharToMultiByte (CP_ACP
, 0, (LPWSTR
) ppev
->pData
,
2922 ppev
->cbData
/ sizeof (WCHAR
), pBuffer
, dwBufSize
, NULL
, NULL
);
2925 ret
= GetLastError ();
2926 ERR ("WideCharToMultiByte failed with code %li\n", ret
);
2927 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
2928 WARN ("HeapFree failed with code %li\n", GetLastError ());
2932 memcpy (ppev
->pData
, pBuffer
, len
);
2934 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer
);
2935 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
2938 if (HeapFree (hHeap
, 0, pBuffer
) == 0)
2940 ret
= GetLastError ();
2941 ERR ("HeapFree failed with code %li\n", ret
);
2945 return ERROR_SUCCESS
;