4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
7 * Copyright 1999, 2000 Huw D M Davies
18 #include "wine/windef16.h"
19 #include "wine/unicode.h"
20 #include "debugtools.h"
25 DEFAULT_DEBUG_CHANNEL(winspool
);
27 typedef struct _OPENEDPRINTER
29 LPWSTR lpsPrinterName
;
31 } OPENEDPRINTER
, *LPOPENEDPRINTER
;
33 /* The OpenedPrinter Table dynamic array */
34 static HDPA pOpenedPrinterDPA
= NULL
;
36 extern HDPA (WINAPI
* WINSPOOL_DPA_CreateEx
) (INT
, HANDLE
);
37 extern LPVOID (WINAPI
* WINSPOOL_DPA_GetPtr
) (const HDPA
, INT
);
38 extern INT (WINAPI
* WINSPOOL_DPA_InsertPtr
) (const HDPA
, INT
, LPVOID
);
40 static char Printers
[] =
41 "System\\CurrentControlSet\\control\\Print\\Printers\\";
42 static char Drivers
[] =
43 "System\\CurrentControlSet\\control\\Print\\Environments\\Windows 4.0\\Drivers\\"; /* Hmm, well */
45 static WCHAR DefaultEnvironmentW
[] = {'W','i','n','e',0};
47 static WCHAR Configuration_FileW
[] = {'C','o','n','f','i','g','u','r','a','t',
48 'i','o','n',' ','F','i','l','e',0};
49 static WCHAR DatatypeW
[] = {'D','a','t','a','t','y','p','e',0};
50 static WCHAR Data_FileW
[] = {'D','a','t','a',' ','F','i','l','e',0};
51 static WCHAR Default_DevModeW
[] = {'D','e','f','a','u','l','t',' ','D','e','v',
53 static WCHAR Dependent_FilesW
[] = {'D','e','p','e','n','d','e','n','t',' ','F',
55 static WCHAR DescriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
56 static WCHAR DriverW
[] = {'D','r','i','v','e','r',0};
57 static WCHAR Help_FileW
[] = {'H','e','l','p',' ','F','i','l','e',0};
58 static WCHAR LocationW
[] = {'L','o','c','a','t','i','o','n',0};
59 static WCHAR MonitorW
[] = {'M','o','n','i','t','o','r',0};
60 static WCHAR NameW
[] = {'N','a','m','e',0};
61 static WCHAR ParametersW
[] = {'P','a','r','a','m','e','t','e','r','s',0};
62 static WCHAR PortW
[] = {'P','o','r','t',0};
63 static WCHAR Print_ProcessorW
[] = {'P','r','i','n','t',' ','P','r','o','c','e',
65 static WCHAR Printer_DriverW
[] = {'P','r','i','n','t','e','r',' ','D','r','i',
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 LPOPENEDPRINTER
WINSPOOL_GetOpenedPrinterEntry()
79 LPOPENEDPRINTER pOpenedPrinter
;
82 * Create the opened printers' handle dynamic array.
84 if (!pOpenedPrinterDPA
)
86 pOpenedPrinterDPA
= WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
87 for (i
= 0; i
< 10; i
++)
89 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
91 sizeof(OPENEDPRINTER
));
92 pOpenedPrinter
->hPrinter
= -1;
93 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
98 * Search for a handle not yet allocated.
100 for (i
= 0; i
< pOpenedPrinterDPA
->nItemCount
; i
++)
102 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, i
);
104 if (pOpenedPrinter
->hPrinter
== -1)
106 pOpenedPrinter
->hPrinter
= i
+ 1;
107 return pOpenedPrinter
;
112 * Didn't find one, insert new element in the array.
114 if (i
== pOpenedPrinterDPA
->nItemCount
)
116 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
118 sizeof(OPENEDPRINTER
));
119 pOpenedPrinter
->hPrinter
= i
+ 1;
120 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
121 return pOpenedPrinter
;
127 /******************************************************************
128 * WINSPOOL_GetOpenedPrinter
129 * Get the pointer to the opened printer referred by the handle
131 static LPOPENEDPRINTER
WINSPOOL_GetOpenedPrinter(int printerHandle
)
133 LPOPENEDPRINTER pOpenedPrinter
;
135 if(!pOpenedPrinterDPA
) return NULL
;
136 if((printerHandle
<=0) ||
137 (printerHandle
> (pOpenedPrinterDPA
->nItemCount
- 1)))
140 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, printerHandle
-1);
142 return pOpenedPrinter
;
145 /***********************************************************
148 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
151 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
154 Formname
= (dmA
->dmSize
> off_formname
);
155 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
156 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
159 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
160 dmA
->dmSize
- CCHDEVICENAME
);
162 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
163 off_formname
- CCHDEVICENAME
);
164 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
166 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
167 (off_formname
+ CCHFORMNAME
));
170 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
175 /***********************************************************
177 * Creates a unicode copy of supplied devmode on heap
179 static LPDEVMODEW
DEVMODEdupAtoW(HANDLE heap
, const DEVMODEA
*dmA
)
184 ptrdiff_t off_formname
;
187 if(!dmA
) return NULL
;
189 off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
190 Formname
= (dmA
->dmSize
> off_formname
);
191 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
192 dmW
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmA
->dmDriverExtra
);
193 return DEVMODEcpyAtoW(dmW
, dmA
);
196 /***********************************************************
198 * Creates an ascii copy of supplied devmode on heap
200 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
205 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
207 if(!dmW
) return NULL
;
208 Formname
= (dmW
->dmSize
> off_formname
);
209 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
210 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
211 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
212 CCHDEVICENAME
, NULL
, NULL
);
214 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
215 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
217 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
218 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
219 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
220 CCHFORMNAME
, NULL
, NULL
);
221 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
222 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
225 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
230 /***********************************************************
232 * Creates a unicode copy of PRINTER_INFO_2A on heap
234 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
236 LPPRINTER_INFO_2W piW
;
237 if(!piA
) return NULL
;
238 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
239 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
240 piW
->pServerName
= HEAP_strdupAtoW(heap
, 0, piA
->pServerName
);
241 piW
->pPrinterName
= HEAP_strdupAtoW(heap
, 0, piA
->pPrinterName
);
242 piW
->pShareName
= HEAP_strdupAtoW(heap
, 0, piA
->pShareName
);
243 piW
->pPortName
= HEAP_strdupAtoW(heap
, 0, piA
->pPortName
);
244 piW
->pDriverName
= HEAP_strdupAtoW(heap
, 0, piA
->pDriverName
);
245 piW
->pComment
= HEAP_strdupAtoW(heap
, 0, piA
->pComment
);
246 piW
->pLocation
= HEAP_strdupAtoW(heap
, 0, piA
->pLocation
);
247 piW
->pDevMode
= DEVMODEdupAtoW(heap
, piA
->pDevMode
);
248 piW
->pSepFile
= HEAP_strdupAtoW(heap
, 0, piA
->pSepFile
);
249 piW
->pPrintProcessor
= HEAP_strdupAtoW(heap
, 0, piA
->pPrintProcessor
);
250 piW
->pDatatype
= HEAP_strdupAtoW(heap
, 0, piA
->pDatatype
);
251 piW
->pParameters
= HEAP_strdupAtoW(heap
, 0, piA
->pParameters
);
255 /***********************************************************
256 * FREE_PRINTER_INFO_2W
257 * Free PRINTER_INFO_2W and all strings
259 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
263 HeapFree(heap
,0,piW
->pServerName
);
264 HeapFree(heap
,0,piW
->pPrinterName
);
265 HeapFree(heap
,0,piW
->pShareName
);
266 HeapFree(heap
,0,piW
->pPortName
);
267 HeapFree(heap
,0,piW
->pDriverName
);
268 HeapFree(heap
,0,piW
->pComment
);
269 HeapFree(heap
,0,piW
->pLocation
);
270 HeapFree(heap
,0,piW
->pDevMode
);
271 HeapFree(heap
,0,piW
->pSepFile
);
272 HeapFree(heap
,0,piW
->pPrintProcessor
);
273 HeapFree(heap
,0,piW
->pDatatype
);
274 HeapFree(heap
,0,piW
->pParameters
);
275 HeapFree(heap
,0,piW
);
279 /******************************************************************
280 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
283 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
284 LPSTR pOutput
, LPDEVMODEA lpdm
)
287 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
289 /* If DC_PAPERSIZE map POINT16s to POINTs */
290 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
291 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
293 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
294 for(i
= 0; i
< ret
; i
++)
295 CONV_POINT16TO32(tmp
+ i
, (POINT
*)pOutput
+ i
);
296 HeapFree( GetProcessHeap(), 0, tmp
);
302 /*****************************************************************************
303 * DeviceCapabilitiesW [WINSPOOL.152]
305 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
308 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
309 WORD fwCapability
, LPWSTR pOutput
,
310 const DEVMODEW
*pDevMode
)
312 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
313 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
314 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
317 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
318 fwCapability
== DC_FILEDEPENDENCIES
||
319 fwCapability
== DC_PAPERNAMES
)) {
320 /* These need A -> W translation */
323 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
327 switch(fwCapability
) {
332 case DC_FILEDEPENDENCIES
:
336 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
337 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
339 for(i
= 0; i
< ret
; i
++)
340 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
341 pOutput
+ (i
* size
), size
);
342 HeapFree(GetProcessHeap(), 0, pOutputA
);
344 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
345 (LPSTR
)pOutput
, dmA
);
347 HeapFree(GetProcessHeap(),0,pPortA
);
348 HeapFree(GetProcessHeap(),0,pDeviceA
);
349 HeapFree(GetProcessHeap(),0,dmA
);
353 /******************************************************************
354 * DocumentPropertiesA [WINSPOOL.155]
357 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
358 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
359 LPDEVMODEA pDevModeInput
,DWORD fMode
)
361 LPOPENEDPRINTER lpOpenedPrinter
;
362 LPSTR lpName
= pDeviceName
;
365 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
366 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
371 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
372 if(!lpOpenedPrinter
) {
373 SetLastError(ERROR_INVALID_HANDLE
);
376 lpNameW
= lpOpenedPrinter
->lpsPrinterName
;
377 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
380 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
381 pDevModeInput
, NULL
, fMode
);
384 HeapFree(GetProcessHeap(),0,lpName
);
389 /*****************************************************************************
390 * DocumentPropertiesW
392 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
394 LPDEVMODEW pDevModeOutput
,
395 LPDEVMODEW pDevModeInput
, DWORD fMode
)
398 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
399 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
400 LPDEVMODEA pDevModeOutputA
= NULL
;
403 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
404 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
407 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
408 if(ret
< 0) return ret
;
409 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
411 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
412 pDevModeInputA
, fMode
);
414 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
415 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
417 if(fMode
== 0 && ret
> 0)
418 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
419 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
420 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
424 /******************************************************************
425 * OpenPrinterA [WINSPOOL.196]
428 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
429 LPPRINTER_DEFAULTSA pDefault
)
431 LPWSTR lpPrinterNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName
);
432 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
436 DefaultW
.pDatatype
= HEAP_strdupAtoW(GetProcessHeap(), 0,
437 pDefault
->pDatatype
);
438 DefaultW
.pDevMode
= DEVMODEdupAtoW(GetProcessHeap(),
440 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
441 pDefaultW
= &DefaultW
;
443 ret
= OpenPrinterW(lpPrinterNameW
, phPrinter
, pDefaultW
);
445 HeapFree(GetProcessHeap(), 0, DefaultW
.pDatatype
);
446 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
448 HeapFree(GetProcessHeap(), 0, lpPrinterNameW
);
452 /******************************************************************
453 * OpenPrinterW [WINSPOOL.197]
456 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
457 LPPRINTER_DEFAULTSW pDefault
)
459 LPOPENEDPRINTER lpOpenedPrinter
;
460 HKEY hkeyPrinters
, hkeyPrinter
;
462 if (!lpPrinterName
) {
463 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
464 SetLastError(ERROR_INVALID_PARAMETER
);
468 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
471 /* Check Printer exists */
472 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
474 ERR("Can't create Printers key\n");
475 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
479 if(RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
481 WARN("Can't find printer %s in registry\n", debugstr_w(lpPrinterName
));
482 RegCloseKey(hkeyPrinters
);
483 SetLastError(ERROR_INVALID_PARAMETER
);
486 RegCloseKey(hkeyPrinter
);
487 RegCloseKey(hkeyPrinters
);
489 if(!phPrinter
) /* This seems to be what win95 does anyway */
492 /* Get a place in the opened printer buffer*/
493 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterEntry();
494 if(!lpOpenedPrinter
) {
495 ERR("Can't allocate printer slot\n");
496 SetLastError(ERROR_OUTOFMEMORY
);
500 /* Get the name of the printer */
501 lpOpenedPrinter
->lpsPrinterName
=
502 HEAP_strdupW( GetProcessHeap(), 0, lpPrinterName
);
504 /* Get the unique handle of the printer*/
505 *phPrinter
= lpOpenedPrinter
->hPrinter
;
507 if (pDefault
!= NULL
)
508 FIXME("Not handling pDefault\n");
513 /******************************************************************
514 * AddMonitorA [WINSPOOL.107]
517 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
519 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
520 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
524 /******************************************************************
525 * DeletePrinterDriverA [WINSPOOL.146]
529 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
531 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
532 debugstr_a(pDriverName
));
533 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
538 /******************************************************************
539 * DeleteMonitorA [WINSPOOL.135]
543 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
545 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
546 debugstr_a(pMonitorName
));
547 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
552 /******************************************************************
553 * DeletePortA [WINSPOOL.137]
557 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
559 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
560 debugstr_a(pPortName
));
561 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
565 /******************************************************************************
566 * SetPrinterW [WINSPOOL.214]
576 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
580 /******************************************************************************
581 * WritePrinter [WINSPOOL.223]
591 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
595 /*****************************************************************************
596 * AddFormA [WINSPOOL.103]
598 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
600 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
604 /*****************************************************************************
605 * AddFormW [WINSPOOL.104]
607 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
609 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
613 /*****************************************************************************
614 * AddJobA [WINSPOOL.105]
616 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
617 DWORD cbBuf
, LPDWORD pcbNeeded
)
619 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
624 /*****************************************************************************
625 * AddJobW [WINSPOOL.106]
627 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
630 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
635 /*****************************************************************************
636 * AddPrinterW [WINSPOOL.122]
638 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
640 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
644 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
647 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
650 FIXME("pName = %s - unsupported\n", debugstr_w(pName
));
651 SetLastError(ERROR_INVALID_PARAMETER
);
655 WARN("Level = %ld\n", Level
);
656 SetLastError(ERROR_INVALID_LEVEL
);
660 SetLastError(ERROR_INVALID_PARAMETER
);
663 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
665 ERR("Can't create Printers key\n");
668 if(RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) ==
670 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
671 RegCloseKey(hkeyPrinter
);
672 RegCloseKey(hkeyPrinters
);
675 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
677 ERR("Can't create Drivers key\n");
678 RegCloseKey(hkeyPrinters
);
681 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
683 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
684 RegCloseKey(hkeyPrinters
);
685 RegCloseKey(hkeyDrivers
);
686 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
689 RegCloseKey(hkeyDriver
);
690 RegCloseKey(hkeyDrivers
);
692 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
693 WARN("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
694 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
695 RegCloseKey(hkeyPrinters
);
699 /* See if we can load the driver. We may need the devmode structure anyway
701 size
= DocumentPropertiesW(0, -1, pi
->pPrinterName
, NULL
, NULL
, 0);
703 WARN("DocumentProperties fails\n");
704 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
710 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
711 DocumentPropertiesW(0, -1, pi
->pPrinterName
, dmW
, NULL
, DM_OUT_BUFFER
);
714 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
716 WARN("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
717 SetLastError(ERROR_INVALID_PRINTER_NAME
);
718 RegCloseKey(hkeyPrinters
);
720 HeapFree(GetProcessHeap(), 0, dmW
);
723 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
724 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
725 RegSetValueExW(hkeyPrinter
, DatatypeW
, 0, REG_SZ
, (LPBYTE
)pi
->pDatatype
,
728 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
729 and we support these drivers. NT writes DEVMODEW so somehow
730 we'll need to distinguish between these when we support NT
732 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
733 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
, (LPBYTE
)dmA
,
734 dmA
->dmSize
+ dmA
->dmDriverExtra
);
735 HeapFree(GetProcessHeap(), 0, dmA
);
737 HeapFree(GetProcessHeap(), 0, dmW
);
738 RegSetValueExW(hkeyPrinter
, DescriptionW
, 0, REG_SZ
, (LPBYTE
)pi
->pComment
,
740 RegSetValueExW(hkeyPrinter
, LocationW
, 0, REG_SZ
, (LPBYTE
)pi
->pLocation
,
742 RegSetValueExW(hkeyPrinter
, NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pPrinterName
, 0);
743 RegSetValueExW(hkeyPrinter
, ParametersW
, 0, REG_SZ
,
744 (LPBYTE
)pi
->pParameters
, 0);
745 RegSetValueExW(hkeyPrinter
, PortW
, 0, REG_SZ
, (LPBYTE
)pi
->pPortName
, 0);
746 RegSetValueExW(hkeyPrinter
, Print_ProcessorW
, 0, REG_SZ
,
747 (LPBYTE
)pi
->pPrintProcessor
, 0);
748 RegSetValueExW(hkeyPrinter
, Printer_DriverW
, 0, REG_SZ
,
749 (LPBYTE
)pi
->pDriverName
, 0);
750 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
751 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
752 RegSetValueExW(hkeyPrinter
, Separator_FileW
, 0, REG_SZ
,
753 (LPBYTE
)pi
->pSepFile
, 0);
754 RegSetValueExW(hkeyPrinter
, Share_NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pShareName
,
756 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
757 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
758 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
759 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
760 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
761 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
763 RegCloseKey(hkeyPrinter
);
764 RegCloseKey(hkeyPrinters
);
765 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
766 ERR("OpenPrinter failing\n");
772 /*****************************************************************************
773 * AddPrinterA [WINSPOOL.117]
775 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
778 PRINTER_INFO_2W
*piW
;
779 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
782 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
784 WARN("Level = %ld\n", Level
);
785 SetLastError(ERROR_INVALID_LEVEL
);
788 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
789 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
791 ret
= AddPrinterW(pNameW
, Level
, (LPBYTE
)piW
);
793 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
794 HeapFree(GetProcessHeap(),0,pNameW
);
799 /*****************************************************************************
800 * ClosePrinter [WINSPOOL.126]
802 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
804 LPOPENEDPRINTER lpOpenedPrinter
;
806 TRACE("Handle %d\n", hPrinter
);
808 if (!pOpenedPrinterDPA
)
811 if ((hPrinter
!= -1) && (hPrinter
< (pOpenedPrinterDPA
->nItemCount
- 1)))
813 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
814 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter
->lpsPrinterName
);
815 lpOpenedPrinter
->lpsPrinterName
= NULL
;
816 lpOpenedPrinter
->hPrinter
= -1;
823 /*****************************************************************************
824 * DeleteFormA [WINSPOOL.133]
826 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
828 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
832 /*****************************************************************************
833 * DeleteFormW [WINSPOOL.134]
835 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
837 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
841 /*****************************************************************************
842 * DeletePrinter [WINSPOOL.143]
844 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
849 LPOPENEDPRINTER lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
850 if(!lpOpenedPrinter
) {
851 SetLastError(ERROR_INVALID_HANDLE
);
854 lpNameW
= lpOpenedPrinter
->lpsPrinterName
;
855 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
857 ERR("Can't open Printers key\n");
861 /* This should use a recursive delete see Q142491 or SHDeleteKey */
862 if(RegDeleteKeyW(hkeyPrinters
, lpNameW
) == ERROR_SUCCESS
) {
863 SetLastError(ERROR_PRINTER_NOT_FOUND
); /* ?? */
864 RegCloseKey(hkeyPrinters
);
868 ClosePrinter(hPrinter
);
872 /*****************************************************************************
873 * SetPrinterA [WINSPOOL.211]
875 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
878 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
882 /*****************************************************************************
883 * SetJobA [WINSPOOL.209]
885 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
886 LPBYTE pJob
, DWORD Command
)
888 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
893 /*****************************************************************************
894 * SetJobW [WINSPOOL.210]
896 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
897 LPBYTE pJob
, DWORD Command
)
899 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
904 /*****************************************************************************
905 * GetFormA [WINSPOOL.181]
907 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
908 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
910 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
911 Level
,pForm
,cbBuf
,pcbNeeded
);
915 /*****************************************************************************
916 * GetFormW [WINSPOOL.182]
918 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
919 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
921 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
922 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
926 /*****************************************************************************
927 * SetFormA [WINSPOOL.207]
929 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
932 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
936 /*****************************************************************************
937 * SetFormW [WINSPOOL.208]
939 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
942 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
946 /*****************************************************************************
947 * ReadPrinter [WINSPOOL.202]
949 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
950 LPDWORD pNoBytesRead
)
952 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
956 /*****************************************************************************
957 * ResetPrinterA [WINSPOOL.203]
959 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
961 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
965 /*****************************************************************************
966 * ResetPrinterW [WINSPOOL.204]
968 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
970 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
974 /*****************************************************************************
975 * WINSPOOL_GetDWORDFromReg
977 * Return DWORD associated with ValueName from hkey.
979 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
981 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
984 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
986 if(ret
!= ERROR_SUCCESS
) {
987 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
990 if(type
!= REG_DWORD
) {
991 ERR("Got type %ld\n", type
);
997 /*****************************************************************************
998 * WINSPOOL_GetStringFromReg
1000 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1001 * String is stored either as unicode or ascii.
1002 * Bit of a hack here to get the ValueName if we want ascii.
1004 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1005 DWORD buflen
, DWORD
*needed
,
1008 DWORD sz
= buflen
, type
;
1012 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1014 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1015 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1016 HeapFree(GetProcessHeap(),0,ValueNameA
);
1018 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1019 WARN("Got ret = %ld\n", ret
);
1027 /*****************************************************************************
1028 * WINSPOOL_GetDevModeFromReg
1030 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1031 * DevMode is stored either as unicode or ascii.
1033 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1035 DWORD buflen
, DWORD
*needed
,
1038 DWORD sz
= buflen
, type
;
1041 if (ptr
) memset(ptr
, 0, sizeof(DEVMODEA
));
1042 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1043 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1044 if (sz
< sizeof(DEVMODEA
))
1046 ERR("corrupted registry for %s\n", debugstr_w(ValueName
));
1047 sz
= sizeof(DEVMODEA
);
1049 /* ensures that dmSize is not erratically bogus if registry is invalid */
1050 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1051 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1053 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1055 DEVMODEW
*dmW
= DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA
*)ptr
);
1056 memcpy(ptr
, dmW
, sz
);
1057 HeapFree(GetProcessHeap(),0,dmW
);
1064 /*********************************************************************
1065 * WINSPOOL_GetPrinter_2
1067 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1068 * The strings are either stored as unicode or ascii.
1070 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1071 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1074 DWORD size
, left
= cbBuf
;
1075 BOOL space
= (cbBuf
> 0);
1080 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1082 if(space
&& size
<= left
) {
1083 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1090 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1092 if(space
&& size
<= left
) {
1093 pi2
->pShareName
= (LPWSTR
)ptr
;
1100 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1102 if(space
&& size
<= left
) {
1103 pi2
->pPortName
= (LPWSTR
)ptr
;
1110 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1112 if(space
&& size
<= left
) {
1113 pi2
->pDriverName
= (LPWSTR
)ptr
;
1120 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1122 if(space
&& size
<= left
) {
1123 pi2
->pComment
= (LPWSTR
)ptr
;
1130 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1132 if(space
&& size
<= left
) {
1133 pi2
->pLocation
= (LPWSTR
)ptr
;
1140 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1142 if(space
&& size
<= left
) {
1143 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1150 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1152 if(space
&& size
<= left
) {
1153 pi2
->pSepFile
= (LPWSTR
)ptr
;
1160 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1162 if(space
&& size
<= left
) {
1163 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1170 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1172 if(space
&& size
<= left
) {
1173 pi2
->pDatatype
= (LPWSTR
)ptr
;
1180 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1182 if(space
&& size
<= left
) {
1183 pi2
->pParameters
= (LPWSTR
)ptr
;
1191 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1192 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1193 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1194 "Default Priority");
1195 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1196 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1199 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1200 memset(pi2
, 0, sizeof(*pi2
));
1205 /*********************************************************************
1206 * WINSPOOL_GetPrinter_4
1208 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1210 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1211 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1214 DWORD size
, left
= cbBuf
;
1215 BOOL space
= (cbBuf
> 0);
1220 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1222 if(space
&& size
<= left
) {
1223 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1231 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1234 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1235 memset(pi4
, 0, sizeof(*pi4
));
1240 /*********************************************************************
1241 * WINSPOOL_GetPrinter_5
1243 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1245 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1246 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1249 DWORD size
, left
= cbBuf
;
1250 BOOL space
= (cbBuf
> 0);
1255 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1257 if(space
&& size
<= left
) {
1258 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1265 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1267 if(space
&& size
<= left
) {
1268 pi5
->pPortName
= (LPWSTR
)ptr
;
1276 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1277 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1279 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1283 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1284 memset(pi5
, 0, sizeof(*pi5
));
1289 /*****************************************************************************
1290 * WINSPOOL_GetPrinter
1292 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1293 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1294 * just a collection of pointers to strings.
1296 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1297 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1299 OPENEDPRINTER
*lpOpenedPrinter
;
1300 DWORD size
, needed
= 0;
1302 HKEY hkeyPrinter
, hkeyPrinters
;
1305 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1307 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1308 if(!lpOpenedPrinter
) {
1309 SetLastError(ERROR_INVALID_HANDLE
);
1312 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1314 ERR("Can't create Printers key\n");
1317 if(RegOpenKeyW(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1319 ERR("Can't find opened printer %s in registry\n",
1320 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1321 RegCloseKey(hkeyPrinters
);
1322 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1329 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
1331 size
= sizeof(PRINTER_INFO_2W
);
1333 ptr
= pPrinter
+ size
;
1335 memset(pPrinter
, 0, size
);
1340 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
1348 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
1350 size
= sizeof(PRINTER_INFO_4W
);
1352 ptr
= pPrinter
+ size
;
1354 memset(pPrinter
, 0, size
);
1359 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
1368 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
1370 size
= sizeof(PRINTER_INFO_5W
);
1372 ptr
= pPrinter
+ size
;
1374 memset(pPrinter
, 0, size
);
1380 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
1387 FIXME("Unimplemented level %ld\n", Level
);
1388 SetLastError(ERROR_INVALID_LEVEL
);
1389 RegCloseKey(hkeyPrinters
);
1390 RegCloseKey(hkeyPrinter
);
1394 RegCloseKey(hkeyPrinter
);
1395 RegCloseKey(hkeyPrinters
);
1397 TRACE("returing %d needed = %ld\n", ret
, needed
);
1398 if(pcbNeeded
) *pcbNeeded
= needed
;
1400 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1404 /*****************************************************************************
1405 * GetPrinterW [WINSPOOL.194]
1407 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1408 DWORD cbBuf
, LPDWORD pcbNeeded
)
1410 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1414 /*****************************************************************************
1415 * GetPrinterA [WINSPOOL.187]
1417 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1418 DWORD cbBuf
, LPDWORD pcbNeeded
)
1420 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1424 /*****************************************************************************
1425 * WINSPOOL_EnumPrinters
1427 * Implementation of EnumPrintersA|W
1429 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
1430 DWORD dwLevel
, LPBYTE lpbPrinters
,
1431 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1432 LPDWORD lpdwReturned
, BOOL unicode
)
1435 HKEY hkeyPrinters
, hkeyPrinter
;
1436 WCHAR PrinterName
[255];
1437 DWORD needed
= 0, number
= 0;
1438 DWORD used
, i
, left
;
1442 memset(lpbPrinters
, 0, cbBuf
);
1446 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
1447 FIXME("dwType = %08lx\n", dwType
);
1448 SetLastError(ERROR_INVALID_FLAGS
);
1452 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1454 ERR("Can't create Printers key\n");
1458 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
1459 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
1460 RegCloseKey(hkeyPrinters
);
1461 ERR("Can't query Printers key\n");
1464 TRACE("Found %ld printers\n", number
);
1468 RegCloseKey(hkeyPrinters
);
1470 *lpdwReturned
= number
;
1474 used
= number
* sizeof(PRINTER_INFO_2W
);
1477 used
= number
* sizeof(PRINTER_INFO_4W
);
1480 used
= number
* sizeof(PRINTER_INFO_5W
);
1484 SetLastError(ERROR_INVALID_LEVEL
);
1485 RegCloseKey(hkeyPrinters
);
1488 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
1490 for(i
= 0; i
< number
; i
++) {
1491 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
1493 ERR("Can't enum key number %ld\n", i
);
1494 RegCloseKey(hkeyPrinters
);
1497 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
1498 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
1500 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
1501 RegCloseKey(hkeyPrinters
);
1506 buf
= lpbPrinters
+ used
;
1507 left
= cbBuf
- used
;
1515 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
1516 left
, &needed
, unicode
);
1518 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
1521 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
1522 left
, &needed
, unicode
);
1524 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
1527 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
1528 left
, &needed
, unicode
);
1530 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
1533 ERR("Shouldn't be here!\n");
1534 RegCloseKey(hkeyPrinter
);
1535 RegCloseKey(hkeyPrinters
);
1538 RegCloseKey(hkeyPrinter
);
1540 RegCloseKey(hkeyPrinters
);
1547 memset(lpbPrinters
, 0, cbBuf
);
1548 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1552 *lpdwReturned
= number
;
1553 SetLastError(ERROR_SUCCESS
);
1558 /******************************************************************
1559 * EnumPrintersW [WINSPOOL.175]
1561 * Enumerates the available printers, print servers and print
1562 * providers, depending on the specified flags, name and level.
1566 * If level is set to 1:
1567 * Not implemented yet!
1568 * Returns TRUE with an empty list.
1570 * If level is set to 2:
1571 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1572 * Returns an array of PRINTER_INFO_2 data structures in the
1573 * lpbPrinters buffer. Note that according to MSDN also an
1574 * OpenPrinter should be performed on every remote printer.
1576 * If level is set to 4 (officially WinNT only):
1577 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1578 * Fast: Only the registry is queried to retrieve printer names,
1579 * no connection to the driver is made.
1580 * Returns an array of PRINTER_INFO_4 data structures in the
1581 * lpbPrinters buffer.
1583 * If level is set to 5 (officially WinNT4/Win9x only):
1584 * Fast: Only the registry is queried to retrieve printer names,
1585 * no connection to the driver is made.
1586 * Returns an array of PRINTER_INFO_5 data structures in the
1587 * lpbPrinters buffer.
1589 * If level set to 3 or 6+:
1590 * returns zero (faillure!)
1592 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
1596 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1597 * - Only levels 2, 4 and 5 are implemented at the moment.
1598 * - 16-bit printer drivers are not enumerated.
1599 * - Returned amount of bytes used/needed does not match the real Windoze
1600 * implementation (as in this implementation, all strings are part
1601 * of the buffer, whereas Win32 keeps them somewhere else)
1602 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1605 * - In a regular Wine installation, no registry settings for printers
1606 * exist, which makes this function return an empty list.
1608 BOOL WINAPI
EnumPrintersW(
1609 DWORD dwType
, /* Types of print objects to enumerate */
1610 LPWSTR lpszName
, /* name of objects to enumerate */
1611 DWORD dwLevel
, /* type of printer info structure */
1612 LPBYTE lpbPrinters
, /* buffer which receives info */
1613 DWORD cbBuf
, /* max size of buffer in bytes */
1614 LPDWORD lpdwNeeded
, /* pointer to var: # bytes used/needed */
1615 LPDWORD lpdwReturned
/* number of entries returned */
1618 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
1619 lpdwNeeded
, lpdwReturned
, TRUE
);
1622 /******************************************************************
1623 * EnumPrintersA [WINSPOOL.174]
1626 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
1627 DWORD dwLevel
, LPBYTE lpbPrinters
,
1628 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1629 LPDWORD lpdwReturned
)
1632 LPWSTR lpszNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpszName
);
1634 ret
= WINSPOOL_EnumPrinters(dwType
, lpszNameW
, dwLevel
, lpbPrinters
, cbBuf
,
1635 lpdwNeeded
, lpdwReturned
, FALSE
);
1636 HeapFree(GetProcessHeap(),0,lpszNameW
);
1640 /*****************************************************************************
1641 * WINSPOOL_GetDriverInfoFromReg [internal]
1643 * Enters the information from the registry into the DRIVER_INFO struct
1646 * zero if the printer driver does not exist in the registry
1647 * (only if Level > 1) otherwise nonzero
1649 static BOOL
WINSPOOL_GetDriverInfoFromReg(
1652 LPWSTR pEnvironment
,
1654 LPBYTE ptr
, /* DRIVER_INFO */
1655 LPBYTE pDriverStrings
, /* strings buffer */
1656 DWORD cbBuf
, /* size of string buffer */
1657 LPDWORD pcbNeeded
, /* space needed for str. */
1658 BOOL unicode
) /* type of strings */
1659 { DWORD dw
, size
, type
;
1661 LPBYTE strPtr
= pDriverStrings
;
1663 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
1664 debugstr_w(DriverName
), debugstr_w(pEnvironment
),
1665 Level
, ptr
, pDriverStrings
, cbBuf
, unicode
);
1668 *pcbNeeded
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
1669 if (*pcbNeeded
<= cbBuf
)
1670 strcpyW((LPWSTR
)strPtr
, DriverName
);
1672 *pcbNeeded
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0,
1674 if(*pcbNeeded
<= cbBuf
)
1675 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, strPtr
, *pcbNeeded
,
1680 ((PDRIVER_INFO_1W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1684 ((PDRIVER_INFO_3W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1685 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1688 if(RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
) != ERROR_SUCCESS
) {
1689 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName
));
1690 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
1695 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
, &size
) !=
1697 WARN("Can't get Version\n");
1699 ((PDRIVER_INFO_3A
) ptr
)->cVersion
= dw
;
1702 pEnvironment
= DefaultEnvironmentW
;
1704 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
1706 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
1709 if(*pcbNeeded
<= cbBuf
) {
1711 strcpyW((LPWSTR
)strPtr
, pEnvironment
);
1713 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, strPtr
, size
,
1716 ((PDRIVER_INFO_3W
) ptr
)->pEnvironment
= (LPWSTR
)strPtr
;
1717 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1720 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, 0, &size
,
1723 if(*pcbNeeded
<= cbBuf
)
1724 WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, cbBuf
, &size
,
1727 ((PDRIVER_INFO_3W
) ptr
)->pDriverPath
= (LPWSTR
)strPtr
;
1728 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1731 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, 0, &size
,
1734 if(*pcbNeeded
<= cbBuf
)
1735 WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, cbBuf
,
1738 ((PDRIVER_INFO_3W
) ptr
)->pDataFile
= (LPWSTR
)strPtr
;
1739 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1742 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1743 cbBuf
, &size
, unicode
)) {
1745 if(*pcbNeeded
<= cbBuf
)
1746 WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1747 cbBuf
, &size
, unicode
);
1749 ((PDRIVER_INFO_3W
) ptr
)->pConfigFile
= (LPWSTR
)strPtr
;
1750 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1754 RegCloseKey(hkeyDriver
);
1758 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
, 0, &size
,
1761 if(*pcbNeeded
<= cbBuf
)
1762 WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
,
1763 cbBuf
, &size
, unicode
);
1765 ((PDRIVER_INFO_3W
) ptr
)->pHelpFile
= (LPWSTR
)strPtr
;
1766 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1769 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
, 0,
1772 if(*pcbNeeded
<= cbBuf
)
1773 WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
,
1774 cbBuf
, &size
, unicode
);
1776 ((PDRIVER_INFO_3W
) ptr
)->pDependentFiles
= (LPWSTR
)strPtr
;
1777 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1780 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
, 0, &size
,
1783 if(*pcbNeeded
<= cbBuf
)
1784 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1785 cbBuf
, &size
, unicode
);
1787 ((PDRIVER_INFO_3W
) ptr
)->pMonitorName
= (LPWSTR
)strPtr
;
1788 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1791 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, strPtr
, 0, &size
,
1794 if(*pcbNeeded
<= cbBuf
)
1795 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1796 cbBuf
, &size
, unicode
);
1798 ((PDRIVER_INFO_3W
) ptr
)->pDefaultDataType
= (LPWSTR
)strPtr
;
1799 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1802 RegCloseKey(hkeyDriver
);
1806 /*****************************************************************************
1807 * WINSPOOL_GetPrinterDriver
1809 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
1810 DWORD Level
, LPBYTE pDriverInfo
,
1811 DWORD cbBuf
, LPDWORD pcbNeeded
,
1814 OPENEDPRINTER
*lpOpenedPrinter
;
1815 WCHAR DriverName
[100];
1816 DWORD ret
, type
, size
, needed
= 0;
1818 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDrivers
;
1820 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
1821 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1823 ZeroMemory(pDriverInfo
, cbBuf
);
1825 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1826 if(!lpOpenedPrinter
) {
1827 SetLastError(ERROR_INVALID_HANDLE
);
1831 FIXME("pEnvironment = %s\n", debugstr_w(pEnvironment
));
1832 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1835 if(Level
< 1 || Level
> 3) {
1836 SetLastError(ERROR_INVALID_LEVEL
);
1839 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1841 ERR("Can't create Printers key\n");
1844 if(RegOpenKeyW(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1846 ERR("Can't find opened printer %s in registry\n",
1847 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1848 RegCloseKey(hkeyPrinters
);
1849 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1852 size
= sizeof(DriverName
);
1853 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
1854 (LPBYTE
)DriverName
, &size
);
1855 RegCloseKey(hkeyPrinter
);
1856 RegCloseKey(hkeyPrinters
);
1857 if(ret
!= ERROR_SUCCESS
) {
1858 ERR("Can't get DriverName for printer %s\n",
1859 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1862 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
1864 ERR("Can't create Drivers key\n");
1870 size
= sizeof(DRIVER_INFO_1W
);
1873 size
= sizeof(DRIVER_INFO_2W
);
1876 size
= sizeof(DRIVER_INFO_3W
);
1879 ERR("Invalid level\n");
1884 ptr
= pDriverInfo
+ size
;
1886 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverName
,
1887 pEnvironment
, Level
, pDriverInfo
,
1888 (cbBuf
< size
) ? NULL
: ptr
,
1889 (cbBuf
< size
) ? 0 : cbBuf
- size
,
1890 &needed
, unicode
)) {
1891 RegCloseKey(hkeyDrivers
);
1895 RegCloseKey(hkeyDrivers
);
1897 if(pcbNeeded
) *pcbNeeded
= needed
;
1898 if(cbBuf
>= needed
) return TRUE
;
1899 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1903 /*****************************************************************************
1904 * GetPrinterDriverA [WINSPOOL.190]
1906 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
1907 DWORD Level
, LPBYTE pDriverInfo
,
1908 DWORD cbBuf
, LPDWORD pcbNeeded
)
1911 LPWSTR pEnvW
= HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment
);
1912 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pEnvW
, Level
, pDriverInfo
,
1913 cbBuf
, pcbNeeded
, FALSE
);
1914 HeapFree(GetProcessHeap(),0,pEnvW
);
1917 /*****************************************************************************
1918 * GetPrinterDriverW [WINSPOOL.193]
1920 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
1921 DWORD Level
, LPBYTE pDriverInfo
,
1922 DWORD cbBuf
, LPDWORD pcbNeeded
)
1924 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
1925 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
1928 /*****************************************************************************
1929 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1931 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
1932 DWORD Level
, LPBYTE pDriverDirectory
,
1933 DWORD cbBuf
, LPDWORD pcbNeeded
)
1937 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName
, pEnvironment
, Level
,
1938 pDriverDirectory
, cbBuf
, pcbNeeded
);
1940 FIXME("pName = `%s' - unsupported\n", pName
);
1941 SetLastError(ERROR_INVALID_PARAMETER
);
1944 if(pEnvironment
!= NULL
) {
1945 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment
);
1946 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1949 if(Level
!= 1) /* win95 ignores this so we just carry on */
1950 WARN("Level = %ld - assuming 1\n", Level
);
1952 /* FIXME should read from registry */
1953 needed
= GetSystemDirectoryA(pDriverDirectory
, cbBuf
);
1956 *pcbNeeded
= needed
;
1957 if(needed
> cbBuf
) {
1958 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1965 /*****************************************************************************
1966 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1968 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
1969 DWORD Level
, LPBYTE pDriverDirectory
,
1970 DWORD cbBuf
, LPDWORD pcbNeeded
)
1972 LPSTR pNameA
= NULL
, pEnvironmentA
= NULL
;
1976 pNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pName
);
1978 pEnvironmentA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
);
1979 ret
= GetPrinterDriverDirectoryA( pNameA
, pEnvironmentA
, Level
,
1980 pDriverDirectory
, cbBuf
, pcbNeeded
);
1982 HeapFree( GetProcessHeap(), 0, pNameA
);
1984 HeapFree( GetProcessHeap(), 0, pEnvironmentA
);
1989 /*****************************************************************************
1990 * AddPrinterDriverA [WINSPOOL.120]
1992 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
1995 HKEY hkeyDrivers
, hkeyName
;
1997 TRACE("(%s,%ld,%p)\n",pName
,level
,pDriverInfo
);
1999 if(level
!= 2 && level
!= 3) {
2000 SetLastError(ERROR_INVALID_LEVEL
);
2004 FIXME("pName= `%s' - unsupported\n", pName
);
2005 SetLastError(ERROR_INVALID_PARAMETER
);
2009 WARN("pDriverInfo == NULL");
2010 SetLastError(ERROR_INVALID_PARAMETER
);
2015 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
2017 memset(&di3
, 0, sizeof(di3
));
2018 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
2021 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
2023 SetLastError(ERROR_INVALID_PARAMETER
);
2026 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
2027 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
2028 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
2029 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
2031 if(di3
.pEnvironment
) {
2032 FIXME("pEnvironment = `%s'\n", di3
.pEnvironment
);
2033 SetLastError(ERROR_INVALID_ENVIRONMENT
);
2036 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
2038 ERR("Can't create Drivers key\n");
2042 if(level
== 2) { /* apparently can't overwrite with level2 */
2043 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2044 RegCloseKey(hkeyName
);
2045 RegCloseKey(hkeyDrivers
);
2046 WARN("Trying to create existing printer driver `%s'\n", di3
.pName
);
2047 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2051 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2052 RegCloseKey(hkeyDrivers
);
2053 ERR("Can't create Name key\n");
2056 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2058 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2059 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2060 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2062 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2063 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2064 di3
.pDependentFiles
, 0);
2065 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2066 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2067 RegCloseKey(hkeyName
);
2068 RegCloseKey(hkeyDrivers
);
2072 /*****************************************************************************
2073 * AddPrinterDriverW [WINSPOOL.121]
2075 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2078 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2084 /*****************************************************************************
2085 * PrinterProperties [WINSPOOL.201]
2087 * Displays a dialog to set the properties of the printer.
2090 * nonzero on succes or zero on faillure
2093 * implemented as stub only
2095 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* handle to parent window */
2096 HANDLE hPrinter
/* handle to printer object */
2098 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
2099 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2103 /*****************************************************************************
2104 * EnumJobsA [WINSPOOL.162]
2107 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2108 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2112 if(pcbNeeded
) *pcbNeeded
= 0;
2113 if(pcReturned
) *pcReturned
= 0;
2118 /*****************************************************************************
2119 * EnumJobsW [WINSPOOL.163]
2122 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2123 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2127 if(pcbNeeded
) *pcbNeeded
= 0;
2128 if(pcReturned
) *pcReturned
= 0;
2132 /*****************************************************************************
2133 * WINSPOOL_EnumPrinterDrivers [internal]
2135 * Delivers information about all installed printer drivers installed on
2136 * localhost or a given server
2139 * nonzero on succes or zero on failure, if the buffer for the returned
2140 * information is too small the function will return an error
2143 * - only implemented for localhost, foreign hosts will return an error
2144 * - the parameter pEnvironment is ignored
2146 static BOOL
WINSPOOL_EnumPrinterDrivers(LPWSTR pName
, LPWSTR pEnvironment
,
2147 DWORD Level
, LPBYTE pDriverInfo
,
2148 DWORD cbBuf
, LPDWORD pcbNeeded
,
2149 LPDWORD pcReturned
, BOOL unicode
)
2152 DWORD i
, needed
, number
= 0, size
= 0;
2153 WCHAR DriverNameW
[255];
2156 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2157 debugstr_w(pName
), debugstr_w(pEnvironment
),
2158 Level
, pDriverInfo
, cbBuf
, unicode
);
2160 /* check for local drivers */
2162 ERR("remote drivers unsupported! Current remote host is %s\n",
2167 /* check input parameter */
2168 if((Level
< 1) || (Level
> 3)) {
2169 ERR("unsupported level %ld \n", Level
);
2173 /* initialize return values */
2175 memset( pDriverInfo
, 0, cbBuf
);
2179 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
2181 ERR("Can't open Drivers key\n");
2185 if(RegQueryInfoKeyA(hkeyDrivers
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2186 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2187 RegCloseKey(hkeyDrivers
);
2188 ERR("Can't query Drivers key\n");
2191 TRACE("Found %ld Drivers\n", number
);
2193 /* get size of single struct
2194 * unicode and ascii structure have the same size
2198 size
= sizeof(DRIVER_INFO_1A
);
2201 size
= sizeof(DRIVER_INFO_2A
);
2204 size
= sizeof(DRIVER_INFO_3A
);
2208 /* calculate required buffer size */
2209 *pcbNeeded
= size
* number
;
2211 for( i
= 0, ptr
= (pDriverInfo
&& (cbBuf
>= size
)) ? pDriverInfo
: NULL
;
2213 i
++, ptr
= (ptr
&& (cbBuf
>= size
* i
)) ? ptr
+ size
: NULL
) {
2214 if(RegEnumKeyW(hkeyDrivers
, i
, DriverNameW
, sizeof(DriverNameW
))
2216 ERR("Can't enum key number %ld\n", i
);
2217 RegCloseKey(hkeyDrivers
);
2220 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverNameW
,
2221 pEnvironment
, Level
, ptr
,
2222 (cbBuf
< *pcbNeeded
) ? NULL
: pDriverInfo
+ *pcbNeeded
,
2223 (cbBuf
< *pcbNeeded
) ? 0 : cbBuf
- *pcbNeeded
,
2224 &needed
, unicode
)) {
2225 RegCloseKey(hkeyDrivers
);
2228 (*pcbNeeded
) += needed
;
2231 RegCloseKey(hkeyDrivers
);
2233 if(cbBuf
< *pcbNeeded
){
2234 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2241 /*****************************************************************************
2242 * EnumPrinterDriversW [WINSPOOL.173]
2244 * see function EnumPrinterDrivers for RETURNS, BUGS
2246 BOOL WINAPI
EnumPrinterDriversW(LPWSTR pName
, LPWSTR pEnvironment
, DWORD Level
,
2247 LPBYTE pDriverInfo
, DWORD cbBuf
,
2248 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2250 return WINSPOOL_EnumPrinterDrivers(pName
, pEnvironment
, Level
, pDriverInfo
,
2251 cbBuf
, pcbNeeded
, pcReturned
, TRUE
);
2254 /*****************************************************************************
2255 * EnumPrinterDriversA [WINSPOOL.172]
2257 * see function EnumPrinterDrivers for RETURNS, BUGS
2259 BOOL WINAPI
EnumPrinterDriversA(LPSTR pName
, LPSTR pEnvironment
, DWORD Level
,
2260 LPBYTE pDriverInfo
, DWORD cbBuf
,
2261 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2263 WCHAR
*pNameW
= NULL
, *pEnvironmentW
= NULL
;
2266 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
2268 pEnvironmentW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment
);
2270 ret
= WINSPOOL_EnumPrinterDrivers(pNameW
, pEnvironmentW
, Level
, pDriverInfo
,
2271 cbBuf
, pcbNeeded
, pcReturned
, FALSE
);
2273 HeapFree(GetProcessHeap(), 0, pNameW
);
2275 HeapFree(GetProcessHeap(), 0, pEnvironmentW
);