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/unicode.h"
19 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(winspool
);
26 typedef struct _OPENEDPRINTER
28 LPWSTR lpsPrinterName
;
30 } OPENEDPRINTER
, *LPOPENEDPRINTER
;
32 /* The OpenedPrinter Table dynamic array */
33 static HDPA pOpenedPrinterDPA
= NULL
;
35 extern HDPA (WINAPI
* WINSPOOL_DPA_CreateEx
) (INT
, HANDLE
);
36 extern LPVOID (WINAPI
* WINSPOOL_DPA_GetPtr
) (const HDPA
, INT
);
37 extern INT (WINAPI
* WINSPOOL_DPA_InsertPtr
) (const HDPA
, INT
, LPVOID
);
39 static char Printers
[] =
40 "System\\CurrentControlSet\\control\\Print\\Printers\\";
41 static char Drivers
[] =
42 "System\\CurrentControlSet\\control\\Print\\Environments\\Windows 4.0\\Drivers\\"; /* Hmm, well */
44 static WCHAR DefaultEnvironmentW
[] = {'W','i','n','e',0};
46 static WCHAR Configuration_FileW
[] = {'C','o','n','f','i','g','u','r','a','t',
47 'i','o','n',' ','F','i','l','e',0};
48 static WCHAR DatatypeW
[] = {'D','a','t','a','t','y','p','e',0};
49 static WCHAR Data_FileW
[] = {'D','a','t','a',' ','F','i','l','e',0};
50 static WCHAR Default_DevModeW
[] = {'D','e','f','a','u','l','t',' ','D','e','v',
52 static WCHAR Dependent_FilesW
[] = {'D','e','p','e','n','d','e','n','t',' ','F',
54 static WCHAR DescriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
55 static WCHAR DriverW
[] = {'D','r','i','v','e','r',0};
56 static WCHAR Help_FileW
[] = {'H','e','l','p',' ','F','i','l','e',0};
57 static WCHAR LocationW
[] = {'L','o','c','a','t','i','o','n',0};
58 static WCHAR MonitorW
[] = {'M','o','n','i','t','o','r',0};
59 static WCHAR NameW
[] = {'N','a','m','e',0};
60 static WCHAR ParametersW
[] = {'P','a','r','a','m','e','t','e','r','s',0};
61 static WCHAR PortW
[] = {'P','o','r','t',0};
62 static WCHAR Print_ProcessorW
[] = {'P','r','i','n','t',' ','P','r','o','c','e',
64 static WCHAR Printer_DriverW
[] = {'P','r','i','n','t','e','r',' ','D','r','i',
66 static WCHAR Separator_FileW
[] = {'S','e','p','a','r','a','t','o','r',' ','F',
68 static WCHAR Share_NameW
[] = {'S','h','a','r','e',' ','N','a','m','e',0};
69 static WCHAR WinPrintW
[] = {'W','i','n','P','r','i','n','t',0};
71 /******************************************************************
72 * WINSPOOL_GetOpenedPrinterEntry
73 * Get the first place empty in the opened printer table
75 static LPOPENEDPRINTER
WINSPOOL_GetOpenedPrinterEntry()
78 LPOPENEDPRINTER pOpenedPrinter
;
81 * Create the opened printers' handle dynamic array.
83 if (!pOpenedPrinterDPA
)
85 pOpenedPrinterDPA
= WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
86 for (i
= 0; i
< 10; i
++)
88 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
90 sizeof(OPENEDPRINTER
));
91 pOpenedPrinter
->hPrinter
= -1;
92 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
97 * Search for a handle not yet allocated.
99 for (i
= 0; i
< pOpenedPrinterDPA
->nItemCount
; i
++)
101 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, i
);
103 if (pOpenedPrinter
->hPrinter
== -1)
105 pOpenedPrinter
->hPrinter
= i
+ 1;
106 return pOpenedPrinter
;
111 * Didn't find one, insert new element in the array.
113 if (i
== pOpenedPrinterDPA
->nItemCount
)
115 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
117 sizeof(OPENEDPRINTER
));
118 pOpenedPrinter
->hPrinter
= i
+ 1;
119 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
120 return pOpenedPrinter
;
126 /******************************************************************
127 * WINSPOOL_GetOpenedPrinter
128 * Get the pointer to the opened printer referred by the handle
130 static LPOPENEDPRINTER
WINSPOOL_GetOpenedPrinter(int printerHandle
)
132 LPOPENEDPRINTER pOpenedPrinter
;
134 if(!pOpenedPrinterDPA
) return NULL
;
135 if((printerHandle
<=0) ||
136 (printerHandle
> (pOpenedPrinterDPA
->nItemCount
- 1)))
139 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, printerHandle
-1);
141 return pOpenedPrinter
;
144 /***********************************************************
147 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
150 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
153 Formname
= (dmA
->dmSize
> off_formname
);
154 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
155 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
158 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
159 dmA
->dmSize
- CCHDEVICENAME
);
161 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
162 off_formname
- CCHDEVICENAME
);
163 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
165 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
166 (off_formname
+ CCHFORMNAME
));
169 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
174 /***********************************************************
176 * Creates a unicode copy of supplied devmode on heap
178 static LPDEVMODEW
DEVMODEdupAtoW(HANDLE heap
, const DEVMODEA
*dmA
)
183 ptrdiff_t off_formname
;
186 if(!dmA
) return NULL
;
188 off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
189 Formname
= (dmA
->dmSize
> off_formname
);
190 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
191 dmW
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmA
->dmDriverExtra
);
192 return DEVMODEcpyAtoW(dmW
, dmA
);
195 /***********************************************************
197 * Creates an ascii copy of supplied devmode on heap
199 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
204 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
206 if(!dmW
) return NULL
;
207 Formname
= (dmW
->dmSize
> off_formname
);
208 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
209 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
210 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
211 CCHDEVICENAME
, NULL
, NULL
);
213 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
214 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
216 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
217 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
218 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
219 CCHFORMNAME
, NULL
, NULL
);
220 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
221 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
224 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
229 /***********************************************************
231 * Creates a unicode copy of PRINTER_INFO_2A on heap
233 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
235 LPPRINTER_INFO_2W piW
;
236 if(!piA
) return NULL
;
237 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
238 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
239 piW
->pServerName
= HEAP_strdupAtoW(heap
, 0, piA
->pServerName
);
240 piW
->pPrinterName
= HEAP_strdupAtoW(heap
, 0, piA
->pPrinterName
);
241 piW
->pShareName
= HEAP_strdupAtoW(heap
, 0, piA
->pShareName
);
242 piW
->pPortName
= HEAP_strdupAtoW(heap
, 0, piA
->pPortName
);
243 piW
->pDriverName
= HEAP_strdupAtoW(heap
, 0, piA
->pDriverName
);
244 piW
->pComment
= HEAP_strdupAtoW(heap
, 0, piA
->pComment
);
245 piW
->pLocation
= HEAP_strdupAtoW(heap
, 0, piA
->pLocation
);
246 piW
->pDevMode
= DEVMODEdupAtoW(heap
, piA
->pDevMode
);
247 piW
->pSepFile
= HEAP_strdupAtoW(heap
, 0, piA
->pSepFile
);
248 piW
->pPrintProcessor
= HEAP_strdupAtoW(heap
, 0, piA
->pPrintProcessor
);
249 piW
->pDatatype
= HEAP_strdupAtoW(heap
, 0, piA
->pDatatype
);
250 piW
->pParameters
= HEAP_strdupAtoW(heap
, 0, piA
->pParameters
);
254 /***********************************************************
255 * FREE_PRINTER_INFO_2W
256 * Free PRINTER_INFO_2W and all strings
258 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
262 HeapFree(heap
,0,piW
->pServerName
);
263 HeapFree(heap
,0,piW
->pPrinterName
);
264 HeapFree(heap
,0,piW
->pShareName
);
265 HeapFree(heap
,0,piW
->pPortName
);
266 HeapFree(heap
,0,piW
->pDriverName
);
267 HeapFree(heap
,0,piW
->pComment
);
268 HeapFree(heap
,0,piW
->pLocation
);
269 HeapFree(heap
,0,piW
->pDevMode
);
270 HeapFree(heap
,0,piW
->pSepFile
);
271 HeapFree(heap
,0,piW
->pPrintProcessor
);
272 HeapFree(heap
,0,piW
->pDatatype
);
273 HeapFree(heap
,0,piW
->pParameters
);
274 HeapFree(heap
,0,piW
);
278 /******************************************************************
279 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
282 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
283 LPSTR pOutput
, LPDEVMODEA lpdm
)
286 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
288 /* If DC_PAPERSIZE map POINT16s to POINTs */
289 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
290 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
292 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
293 for(i
= 0; i
< ret
; i
++)
294 CONV_POINT16TO32(tmp
+ i
, (POINT
*)pOutput
+ i
);
295 HeapFree( GetProcessHeap(), 0, tmp
);
301 /*****************************************************************************
302 * DeviceCapabilitiesW [WINSPOOL.152]
304 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
307 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
308 WORD fwCapability
, LPWSTR pOutput
,
309 const DEVMODEW
*pDevMode
)
311 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
312 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
313 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
316 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
317 fwCapability
== DC_FILEDEPENDENCIES
||
318 fwCapability
== DC_PAPERNAMES
)) {
319 /* These need A -> W translation */
322 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
326 switch(fwCapability
) {
331 case DC_FILEDEPENDENCIES
:
335 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
336 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
338 for(i
= 0; i
< ret
; i
++)
339 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
340 pOutput
+ (i
* size
), size
);
341 HeapFree(GetProcessHeap(), 0, pOutputA
);
343 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
344 (LPSTR
)pOutput
, dmA
);
346 HeapFree(GetProcessHeap(),0,pPortA
);
347 HeapFree(GetProcessHeap(),0,pDeviceA
);
348 HeapFree(GetProcessHeap(),0,dmA
);
352 /******************************************************************
353 * DocumentPropertiesA [WINSPOOL.155]
356 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
357 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
358 LPDEVMODEA pDevModeInput
,DWORD fMode
)
360 LPOPENEDPRINTER lpOpenedPrinter
;
361 LPSTR lpName
= pDeviceName
;
364 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
365 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
370 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
371 if(!lpOpenedPrinter
) {
372 SetLastError(ERROR_INVALID_HANDLE
);
375 lpNameW
= lpOpenedPrinter
->lpsPrinterName
;
376 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
379 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
380 pDevModeInput
, NULL
, fMode
);
383 HeapFree(GetProcessHeap(),0,lpName
);
388 /*****************************************************************************
389 * DocumentPropertiesW
391 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
393 LPDEVMODEW pDevModeOutput
,
394 LPDEVMODEW pDevModeInput
, DWORD fMode
)
397 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
398 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
399 LPDEVMODEA pDevModeOutputA
= NULL
;
402 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
403 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
406 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
407 if(ret
< 0) return ret
;
408 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
410 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
411 pDevModeInputA
, fMode
);
413 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
414 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
416 if(fMode
== 0 && ret
> 0)
417 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
418 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
419 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
423 /******************************************************************
424 * OpenPrinterA [WINSPOOL.196]
427 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
428 LPPRINTER_DEFAULTSA pDefault
)
430 LPWSTR lpPrinterNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName
);
431 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
435 DefaultW
.pDatatype
= HEAP_strdupAtoW(GetProcessHeap(), 0,
436 pDefault
->pDatatype
);
437 DefaultW
.pDevMode
= DEVMODEdupAtoW(GetProcessHeap(),
439 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
440 pDefaultW
= &DefaultW
;
442 ret
= OpenPrinterW(lpPrinterNameW
, phPrinter
, pDefaultW
);
444 HeapFree(GetProcessHeap(), 0, DefaultW
.pDatatype
);
445 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
447 HeapFree(GetProcessHeap(), 0, lpPrinterNameW
);
451 /******************************************************************
452 * OpenPrinterW [WINSPOOL.197]
455 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
456 LPPRINTER_DEFAULTSW pDefault
)
458 LPOPENEDPRINTER lpOpenedPrinter
;
459 HKEY hkeyPrinters
, hkeyPrinter
;
461 if (!lpPrinterName
) {
462 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
463 SetLastError(ERROR_INVALID_PARAMETER
);
467 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
470 /* Check Printer exists */
471 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
473 ERR("Can't create Printers key\n");
474 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
478 if(RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
480 WARN("Can't find printer %s in registry\n", debugstr_w(lpPrinterName
));
481 RegCloseKey(hkeyPrinters
);
482 SetLastError(ERROR_INVALID_PARAMETER
);
485 RegCloseKey(hkeyPrinter
);
486 RegCloseKey(hkeyPrinters
);
488 if(!phPrinter
) /* This seems to be what win95 does anyway */
491 /* Get a place in the opened printer buffer*/
492 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterEntry();
493 if(!lpOpenedPrinter
) {
494 ERR("Can't allocate printer slot\n");
495 SetLastError(ERROR_OUTOFMEMORY
);
499 /* Get the name of the printer */
500 lpOpenedPrinter
->lpsPrinterName
=
501 HEAP_strdupW( GetProcessHeap(), 0, lpPrinterName
);
503 /* Get the unique handle of the printer*/
504 *phPrinter
= lpOpenedPrinter
->hPrinter
;
506 if (pDefault
!= NULL
)
507 FIXME("Not handling pDefault\n");
512 /******************************************************************
513 * AddMonitorA [WINSPOOL.107]
516 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
518 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
519 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
523 /******************************************************************
524 * DeletePrinterDriverA [WINSPOOL.146]
528 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
530 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
531 debugstr_a(pDriverName
));
532 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
537 /******************************************************************
538 * DeleteMonitorA [WINSPOOL.135]
542 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
544 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
545 debugstr_a(pMonitorName
));
546 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
551 /******************************************************************
552 * DeletePortA [WINSPOOL.137]
556 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
558 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
559 debugstr_a(pPortName
));
560 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
564 /******************************************************************************
565 * SetPrinterW [WINSPOOL.214]
575 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
579 /******************************************************************************
580 * WritePrinter [WINSPOOL.223]
590 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
594 /*****************************************************************************
595 * AddFormA [WINSPOOL.103]
597 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
599 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
603 /*****************************************************************************
604 * AddFormW [WINSPOOL.104]
606 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
608 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
612 /*****************************************************************************
613 * AddJobA [WINSPOOL.105]
615 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
616 DWORD cbBuf
, LPDWORD pcbNeeded
)
618 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
623 /*****************************************************************************
624 * AddJobW [WINSPOOL.106]
626 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
629 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
634 /*****************************************************************************
635 * AddPrinterW [WINSPOOL.122]
637 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
639 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
643 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
646 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
649 FIXME("pName = %s - unsupported\n", debugstr_w(pName
));
650 SetLastError(ERROR_INVALID_PARAMETER
);
654 WARN("Level = %ld\n", Level
);
655 SetLastError(ERROR_INVALID_LEVEL
);
659 SetLastError(ERROR_INVALID_PARAMETER
);
662 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
664 ERR("Can't create Printers key\n");
667 if(RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) ==
669 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
670 RegCloseKey(hkeyPrinter
);
671 RegCloseKey(hkeyPrinters
);
674 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
676 ERR("Can't create Drivers key\n");
677 RegCloseKey(hkeyPrinters
);
680 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
682 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
683 RegCloseKey(hkeyPrinters
);
684 RegCloseKey(hkeyDrivers
);
685 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
688 RegCloseKey(hkeyDriver
);
689 RegCloseKey(hkeyDrivers
);
691 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
692 WARN("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
693 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
694 RegCloseKey(hkeyPrinters
);
698 /* See if we can load the driver. We may need the devmode structure anyway
700 size
= DocumentPropertiesW(0, -1, pi
->pPrinterName
, NULL
, NULL
, 0);
702 WARN("DocumentProperties fails\n");
703 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
709 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
710 DocumentPropertiesW(0, -1, pi
->pPrinterName
, dmW
, NULL
, DM_OUT_BUFFER
);
713 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
715 WARN("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
716 SetLastError(ERROR_INVALID_PRINTER_NAME
);
717 RegCloseKey(hkeyPrinters
);
719 HeapFree(GetProcessHeap(), 0, dmW
);
722 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
723 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
724 RegSetValueExW(hkeyPrinter
, DatatypeW
, 0, REG_SZ
, (LPBYTE
)pi
->pDatatype
,
727 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
728 and we support these drivers. NT writes DEVMODEW so somehow
729 we'll need to distinguish between these when we support NT
731 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
732 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
, (LPBYTE
)dmA
,
733 dmA
->dmSize
+ dmA
->dmDriverExtra
);
734 HeapFree(GetProcessHeap(), 0, dmA
);
736 HeapFree(GetProcessHeap(), 0, dmW
);
737 RegSetValueExW(hkeyPrinter
, DescriptionW
, 0, REG_SZ
, (LPBYTE
)pi
->pComment
,
739 RegSetValueExW(hkeyPrinter
, LocationW
, 0, REG_SZ
, (LPBYTE
)pi
->pLocation
,
741 RegSetValueExW(hkeyPrinter
, NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pPrinterName
, 0);
742 RegSetValueExW(hkeyPrinter
, ParametersW
, 0, REG_SZ
,
743 (LPBYTE
)pi
->pParameters
, 0);
744 RegSetValueExW(hkeyPrinter
, PortW
, 0, REG_SZ
, (LPBYTE
)pi
->pPortName
, 0);
745 RegSetValueExW(hkeyPrinter
, Print_ProcessorW
, 0, REG_SZ
,
746 (LPBYTE
)pi
->pPrintProcessor
, 0);
747 RegSetValueExW(hkeyPrinter
, Printer_DriverW
, 0, REG_SZ
,
748 (LPBYTE
)pi
->pDriverName
, 0);
749 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
750 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
751 RegSetValueExW(hkeyPrinter
, Separator_FileW
, 0, REG_SZ
,
752 (LPBYTE
)pi
->pSepFile
, 0);
753 RegSetValueExW(hkeyPrinter
, Share_NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pShareName
,
755 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
756 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
757 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
758 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
759 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
760 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
762 RegCloseKey(hkeyPrinter
);
763 RegCloseKey(hkeyPrinters
);
764 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
765 ERR("OpenPrinter failing\n");
771 /*****************************************************************************
772 * AddPrinterA [WINSPOOL.117]
774 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
777 PRINTER_INFO_2W
*piW
;
778 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
781 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
783 WARN("Level = %ld\n", Level
);
784 SetLastError(ERROR_INVALID_LEVEL
);
787 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
788 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
790 ret
= AddPrinterW(pNameW
, Level
, (LPBYTE
)piW
);
792 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
793 HeapFree(GetProcessHeap(),0,pNameW
);
798 /*****************************************************************************
799 * ClosePrinter [WINSPOOL.126]
801 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
803 LPOPENEDPRINTER lpOpenedPrinter
;
805 TRACE("Handle %d\n", hPrinter
);
807 if (!pOpenedPrinterDPA
)
810 if ((hPrinter
!= -1) && (hPrinter
< (pOpenedPrinterDPA
->nItemCount
- 1)))
812 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
813 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter
->lpsPrinterName
);
814 lpOpenedPrinter
->lpsPrinterName
= NULL
;
815 lpOpenedPrinter
->hPrinter
= -1;
822 /*****************************************************************************
823 * DeleteFormA [WINSPOOL.133]
825 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
827 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
831 /*****************************************************************************
832 * DeleteFormW [WINSPOOL.134]
834 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
836 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
840 /*****************************************************************************
841 * DeletePrinter [WINSPOOL.143]
843 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
848 LPOPENEDPRINTER lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
849 if(!lpOpenedPrinter
) {
850 SetLastError(ERROR_INVALID_HANDLE
);
853 lpNameW
= lpOpenedPrinter
->lpsPrinterName
;
854 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
856 ERR("Can't open Printers key\n");
860 /* This should use a recursive delete see Q142491 or SHDeleteKey */
861 if(RegDeleteKeyW(hkeyPrinters
, lpNameW
) == ERROR_SUCCESS
) {
862 SetLastError(ERROR_PRINTER_NOT_FOUND
); /* ?? */
863 RegCloseKey(hkeyPrinters
);
867 ClosePrinter(hPrinter
);
871 /*****************************************************************************
872 * SetPrinterA [WINSPOOL.211]
874 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
877 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
881 /*****************************************************************************
882 * SetJobA [WINSPOOL.209]
884 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
885 LPBYTE pJob
, DWORD Command
)
887 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
892 /*****************************************************************************
893 * SetJobW [WINSPOOL.210]
895 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
896 LPBYTE pJob
, DWORD Command
)
898 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
903 /*****************************************************************************
904 * GetFormA [WINSPOOL.181]
906 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
907 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
909 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
910 Level
,pForm
,cbBuf
,pcbNeeded
);
914 /*****************************************************************************
915 * GetFormW [WINSPOOL.182]
917 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
918 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
920 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
921 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
925 /*****************************************************************************
926 * SetFormA [WINSPOOL.207]
928 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
931 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
935 /*****************************************************************************
936 * SetFormW [WINSPOOL.208]
938 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
941 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
945 /*****************************************************************************
946 * ReadPrinter [WINSPOOL.202]
948 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
949 LPDWORD pNoBytesRead
)
951 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
955 /*****************************************************************************
956 * ResetPrinterA [WINSPOOL.203]
958 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
960 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
964 /*****************************************************************************
965 * ResetPrinterW [WINSPOOL.204]
967 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
969 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
973 /*****************************************************************************
974 * WINSPOOL_GetDWORDFromReg
976 * Return DWORD associated with ValueName from hkey.
978 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
980 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
983 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
985 if(ret
!= ERROR_SUCCESS
) {
986 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
989 if(type
!= REG_DWORD
) {
990 ERR("Got type %ld\n", type
);
996 /*****************************************************************************
997 * WINSPOOL_GetStringFromReg
999 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1000 * String is stored either as unicode or ascii.
1001 * Bit of a hack here to get the ValueName if we want ascii.
1003 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1004 DWORD buflen
, DWORD
*needed
,
1007 DWORD sz
= buflen
, type
;
1011 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1013 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1014 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1015 HeapFree(GetProcessHeap(),0,ValueNameA
);
1017 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1018 WARN("Got ret = %ld\n", ret
);
1026 /*****************************************************************************
1027 * WINSPOOL_GetDevModeFromReg
1029 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1030 * DevMode is stored either as unicode or ascii.
1032 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1034 DWORD buflen
, DWORD
*needed
,
1037 DWORD sz
= buflen
, type
;
1040 if (ptr
) memset(ptr
, 0, sizeof(DEVMODEA
));
1041 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1042 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1043 if (sz
< sizeof(DEVMODEA
))
1045 ERR("corrupted registry for %s\n", debugstr_w(ValueName
));
1046 sz
= sizeof(DEVMODEA
);
1048 /* ensures that dmSize is not erratically bogus if registry is invalid */
1049 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1050 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1052 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1054 DEVMODEW
*dmW
= DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA
*)ptr
);
1055 memcpy(ptr
, dmW
, sz
);
1056 HeapFree(GetProcessHeap(),0,dmW
);
1063 /*********************************************************************
1064 * WINSPOOL_GetPrinter_2
1066 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1067 * The strings are either stored as unicode or ascii.
1069 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1070 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1073 DWORD size
, left
= cbBuf
;
1074 BOOL space
= (cbBuf
> 0);
1079 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1081 if(space
&& size
<= left
) {
1082 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1089 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1091 if(space
&& size
<= left
) {
1092 pi2
->pShareName
= (LPWSTR
)ptr
;
1099 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1101 if(space
&& size
<= left
) {
1102 pi2
->pPortName
= (LPWSTR
)ptr
;
1109 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1111 if(space
&& size
<= left
) {
1112 pi2
->pDriverName
= (LPWSTR
)ptr
;
1119 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1121 if(space
&& size
<= left
) {
1122 pi2
->pComment
= (LPWSTR
)ptr
;
1129 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1131 if(space
&& size
<= left
) {
1132 pi2
->pLocation
= (LPWSTR
)ptr
;
1139 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1141 if(space
&& size
<= left
) {
1142 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1149 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1151 if(space
&& size
<= left
) {
1152 pi2
->pSepFile
= (LPWSTR
)ptr
;
1159 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1161 if(space
&& size
<= left
) {
1162 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1169 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1171 if(space
&& size
<= left
) {
1172 pi2
->pDatatype
= (LPWSTR
)ptr
;
1179 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1181 if(space
&& size
<= left
) {
1182 pi2
->pParameters
= (LPWSTR
)ptr
;
1190 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1191 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1192 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1193 "Default Priority");
1194 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1195 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1198 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1199 memset(pi2
, 0, sizeof(*pi2
));
1204 /*********************************************************************
1205 * WINSPOOL_GetPrinter_4
1207 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1209 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1210 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1213 DWORD size
, left
= cbBuf
;
1214 BOOL space
= (cbBuf
> 0);
1219 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1221 if(space
&& size
<= left
) {
1222 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1230 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1233 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1234 memset(pi4
, 0, sizeof(*pi4
));
1239 /*********************************************************************
1240 * WINSPOOL_GetPrinter_5
1242 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1244 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1245 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1248 DWORD size
, left
= cbBuf
;
1249 BOOL space
= (cbBuf
> 0);
1254 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1256 if(space
&& size
<= left
) {
1257 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1264 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1266 if(space
&& size
<= left
) {
1267 pi5
->pPortName
= (LPWSTR
)ptr
;
1275 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1276 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1278 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1282 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1283 memset(pi5
, 0, sizeof(*pi5
));
1288 /*****************************************************************************
1289 * WINSPOOL_GetPrinter
1291 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1292 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1293 * just a collection of pointers to strings.
1295 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1296 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1298 OPENEDPRINTER
*lpOpenedPrinter
;
1299 DWORD size
, needed
= 0;
1301 HKEY hkeyPrinter
, hkeyPrinters
;
1304 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1306 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1307 if(!lpOpenedPrinter
) {
1308 SetLastError(ERROR_INVALID_HANDLE
);
1311 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1313 ERR("Can't create Printers key\n");
1316 if(RegOpenKeyW(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1318 ERR("Can't find opened printer %s in registry\n",
1319 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1320 RegCloseKey(hkeyPrinters
);
1321 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1328 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
1330 size
= sizeof(PRINTER_INFO_2W
);
1332 ptr
= pPrinter
+ size
;
1334 memset(pPrinter
, 0, size
);
1339 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
1347 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
1349 size
= sizeof(PRINTER_INFO_4W
);
1351 ptr
= pPrinter
+ size
;
1353 memset(pPrinter
, 0, size
);
1358 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
1367 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
1369 size
= sizeof(PRINTER_INFO_5W
);
1371 ptr
= pPrinter
+ size
;
1373 memset(pPrinter
, 0, size
);
1379 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
1386 FIXME("Unimplemented level %ld\n", Level
);
1387 SetLastError(ERROR_INVALID_LEVEL
);
1388 RegCloseKey(hkeyPrinters
);
1389 RegCloseKey(hkeyPrinter
);
1393 RegCloseKey(hkeyPrinter
);
1394 RegCloseKey(hkeyPrinters
);
1396 TRACE("returing %d needed = %ld\n", ret
, needed
);
1397 if(pcbNeeded
) *pcbNeeded
= needed
;
1399 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1403 /*****************************************************************************
1404 * GetPrinterW [WINSPOOL.194]
1406 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1407 DWORD cbBuf
, LPDWORD pcbNeeded
)
1409 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1413 /*****************************************************************************
1414 * GetPrinterA [WINSPOOL.187]
1416 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1417 DWORD cbBuf
, LPDWORD pcbNeeded
)
1419 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1423 /*****************************************************************************
1424 * WINSPOOL_EnumPrinters
1426 * Implementation of EnumPrintersA|W
1428 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
1429 DWORD dwLevel
, LPBYTE lpbPrinters
,
1430 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1431 LPDWORD lpdwReturned
, BOOL unicode
)
1434 HKEY hkeyPrinters
, hkeyPrinter
;
1435 WCHAR PrinterName
[255];
1436 DWORD needed
= 0, number
= 0;
1437 DWORD used
, i
, left
;
1441 memset(lpbPrinters
, 0, cbBuf
);
1445 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
1446 FIXME("dwType = %08lx\n", dwType
);
1447 SetLastError(ERROR_INVALID_FLAGS
);
1451 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1453 ERR("Can't create Printers key\n");
1457 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
1458 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
1459 RegCloseKey(hkeyPrinters
);
1460 ERR("Can't query Printers key\n");
1463 TRACE("Found %ld printers\n", number
);
1467 RegCloseKey(hkeyPrinters
);
1469 *lpdwReturned
= number
;
1473 used
= number
* sizeof(PRINTER_INFO_2W
);
1476 used
= number
* sizeof(PRINTER_INFO_4W
);
1479 used
= number
* sizeof(PRINTER_INFO_5W
);
1483 SetLastError(ERROR_INVALID_LEVEL
);
1484 RegCloseKey(hkeyPrinters
);
1487 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
1489 for(i
= 0; i
< number
; i
++) {
1490 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
1492 ERR("Can't enum key number %ld\n", i
);
1493 RegCloseKey(hkeyPrinters
);
1496 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
1497 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
1499 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
1500 RegCloseKey(hkeyPrinters
);
1505 buf
= lpbPrinters
+ used
;
1506 left
= cbBuf
- used
;
1514 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
1515 left
, &needed
, unicode
);
1517 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
1520 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
1521 left
, &needed
, unicode
);
1523 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
1526 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
1527 left
, &needed
, unicode
);
1529 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
1532 ERR("Shouldn't be here!\n");
1533 RegCloseKey(hkeyPrinter
);
1534 RegCloseKey(hkeyPrinters
);
1537 RegCloseKey(hkeyPrinter
);
1539 RegCloseKey(hkeyPrinters
);
1546 memset(lpbPrinters
, 0, cbBuf
);
1547 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1551 *lpdwReturned
= number
;
1552 SetLastError(ERROR_SUCCESS
);
1557 /******************************************************************
1558 * EnumPrintersW [WINSPOOL.175]
1560 * Enumerates the available printers, print servers and print
1561 * providers, depending on the specified flags, name and level.
1565 * If level is set to 1:
1566 * Not implemented yet!
1567 * Returns TRUE with an empty list.
1569 * If level is set to 2:
1570 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1571 * Returns an array of PRINTER_INFO_2 data structures in the
1572 * lpbPrinters buffer. Note that according to MSDN also an
1573 * OpenPrinter should be performed on every remote printer.
1575 * If level is set to 4 (officially WinNT only):
1576 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1577 * Fast: Only the registry is queried to retrieve printer names,
1578 * no connection to the driver is made.
1579 * Returns an array of PRINTER_INFO_4 data structures in the
1580 * lpbPrinters buffer.
1582 * If level is set to 5 (officially WinNT4/Win9x only):
1583 * Fast: Only the registry is queried to retrieve printer names,
1584 * no connection to the driver is made.
1585 * Returns an array of PRINTER_INFO_5 data structures in the
1586 * lpbPrinters buffer.
1588 * If level set to 3 or 6+:
1589 * returns zero (faillure!)
1591 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
1595 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1596 * - Only levels 2, 4 and 5 are implemented at the moment.
1597 * - 16-bit printer drivers are not enumerated.
1598 * - Returned amount of bytes used/needed does not match the real Windoze
1599 * implementation (as in this implementation, all strings are part
1600 * of the buffer, whereas Win32 keeps them somewhere else)
1601 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1604 * - In a regular Wine installation, no registry settings for printers
1605 * exist, which makes this function return an empty list.
1607 BOOL WINAPI
EnumPrintersW(
1608 DWORD dwType
, /* Types of print objects to enumerate */
1609 LPWSTR lpszName
, /* name of objects to enumerate */
1610 DWORD dwLevel
, /* type of printer info structure */
1611 LPBYTE lpbPrinters
, /* buffer which receives info */
1612 DWORD cbBuf
, /* max size of buffer in bytes */
1613 LPDWORD lpdwNeeded
, /* pointer to var: # bytes used/needed */
1614 LPDWORD lpdwReturned
/* number of entries returned */
1617 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
1618 lpdwNeeded
, lpdwReturned
, TRUE
);
1621 /******************************************************************
1622 * EnumPrintersA [WINSPOOL.174]
1625 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
1626 DWORD dwLevel
, LPBYTE lpbPrinters
,
1627 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1628 LPDWORD lpdwReturned
)
1631 LPWSTR lpszNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpszName
);
1633 ret
= WINSPOOL_EnumPrinters(dwType
, lpszNameW
, dwLevel
, lpbPrinters
, cbBuf
,
1634 lpdwNeeded
, lpdwReturned
, FALSE
);
1635 HeapFree(GetProcessHeap(),0,lpszNameW
);
1640 /*****************************************************************************
1641 * WINSPOOL_GetPrinterDriver
1643 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
1644 DWORD Level
, LPBYTE pDriverInfo
,
1645 DWORD cbBuf
, LPDWORD pcbNeeded
,
1648 OPENEDPRINTER
*lpOpenedPrinter
;
1649 WCHAR DriverName
[100];
1650 DWORD ret
, type
, size
, dw
, needed
= 0;
1652 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
1654 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
1655 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1657 ZeroMemory(pDriverInfo
, cbBuf
);
1659 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1660 if(!lpOpenedPrinter
) {
1661 SetLastError(ERROR_INVALID_HANDLE
);
1665 FIXME("pEnvironment = %s\n", debugstr_w(pEnvironment
));
1666 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1669 if(Level
< 1 || Level
> 3) {
1670 SetLastError(ERROR_INVALID_LEVEL
);
1673 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1675 ERR("Can't create Printers key\n");
1678 if(RegOpenKeyW(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1680 ERR("Can't find opened printer %s in registry\n",
1681 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1682 RegCloseKey(hkeyPrinters
);
1683 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1686 size
= sizeof(DriverName
);
1687 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
1688 (LPBYTE
)DriverName
, &size
);
1689 RegCloseKey(hkeyPrinter
);
1690 RegCloseKey(hkeyPrinters
);
1691 if(ret
!= ERROR_SUCCESS
) {
1692 ERR("Can't get DriverName for printer %s\n",
1693 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1696 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
1698 ERR("Can't create Drivers key\n");
1701 if(RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
)
1703 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName
));
1704 RegCloseKey(hkeyDrivers
);
1705 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
1711 size
= sizeof(DRIVER_INFO_1W
);
1714 size
= sizeof(DRIVER_INFO_2W
);
1717 size
= sizeof(DRIVER_INFO_3W
);
1720 ERR("Invalid level\n");
1725 ptr
= pDriverInfo
+ size
;
1732 size
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
1734 size
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0, NULL
,
1740 strcpyW((LPWSTR
)ptr
, DriverName
);
1742 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, ptr
, size
, NULL
,
1745 ((DRIVER_INFO_1W
*)pDriverInfo
)->pName
= (LPWSTR
)ptr
;
1747 ((DRIVER_INFO_2W
*)pDriverInfo
)->pName
= (LPWSTR
)ptr
;
1753 DRIVER_INFO_2W
*di2
= (DRIVER_INFO_2W
*)pDriverInfo
;
1756 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
,
1759 WARN("Can't get Version\n");
1764 pEnvironment
= DefaultEnvironmentW
;
1766 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
1768 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
1773 strcpyW((LPWSTR
)ptr
, pEnvironment
);
1775 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, ptr
, size
,
1777 di2
->pEnvironment
= (LPWSTR
)ptr
;
1783 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, ptr
, cbBuf
, &size
,
1785 if(cbBuf
&& size
<= cbBuf
) {
1786 di2
->pDriverPath
= (LPWSTR
)ptr
;
1792 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, ptr
, cbBuf
, &size
,
1794 if(cbBuf
&& size
<= cbBuf
) {
1795 di2
->pDataFile
= (LPWSTR
)ptr
;
1801 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, ptr
,
1802 cbBuf
, &size
, unicode
)) {
1803 if(cbBuf
&& size
<= cbBuf
) {
1804 di2
->pConfigFile
= (LPWSTR
)ptr
;
1812 DRIVER_INFO_3W
*di3
= (DRIVER_INFO_3W
*)pDriverInfo
;
1814 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, ptr
, cbBuf
, &size
,
1816 if(cbBuf
&& size
<= cbBuf
) {
1817 di3
->pHelpFile
= (LPWSTR
)ptr
;
1823 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, ptr
, cbBuf
,
1825 if(cbBuf
&& size
<= cbBuf
) {
1826 di3
->pDependentFiles
= (LPWSTR
)ptr
;
1832 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, ptr
, cbBuf
, &size
,
1834 if(cbBuf
&& size
<= cbBuf
) {
1835 di3
->pMonitorName
= (LPWSTR
)ptr
;
1841 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, ptr
, cbBuf
, &size
,
1843 if(cbBuf
&& size
<= cbBuf
) {
1844 di3
->pDefaultDataType
= (LPWSTR
)ptr
;
1851 RegCloseKey(hkeyDriver
);
1852 RegCloseKey(hkeyDrivers
);
1854 if(pcbNeeded
) *pcbNeeded
= needed
;
1855 if(cbBuf
) return TRUE
;
1856 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1860 /*****************************************************************************
1861 * GetPrinterDriverA [WINSPOOL.190]
1863 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
1864 DWORD Level
, LPBYTE pDriverInfo
,
1865 DWORD cbBuf
, LPDWORD pcbNeeded
)
1868 LPWSTR pEnvW
= HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment
);
1869 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pEnvW
, Level
, pDriverInfo
,
1870 cbBuf
, pcbNeeded
, FALSE
);
1871 HeapFree(GetProcessHeap(),0,pEnvW
);
1874 /*****************************************************************************
1875 * GetPrinterDriverW [WINSPOOL.193]
1877 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
1878 DWORD Level
, LPBYTE pDriverInfo
,
1879 DWORD cbBuf
, LPDWORD pcbNeeded
)
1881 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
1882 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
1885 /*****************************************************************************
1886 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1888 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
1889 DWORD Level
, LPBYTE pDriverDirectory
,
1890 DWORD cbBuf
, LPDWORD pcbNeeded
)
1894 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName
, pEnvironment
, Level
,
1895 pDriverDirectory
, cbBuf
, pcbNeeded
);
1897 FIXME("pName = `%s' - unsupported\n", pName
);
1898 SetLastError(ERROR_INVALID_PARAMETER
);
1901 if(pEnvironment
!= NULL
) {
1902 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment
);
1903 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1906 if(Level
!= 1) /* win95 ignores this so we just carry on */
1907 WARN("Level = %ld - assuming 1\n", Level
);
1909 /* FIXME should read from registry */
1910 needed
= GetSystemDirectoryA(pDriverDirectory
, cbBuf
);
1913 *pcbNeeded
= needed
;
1914 if(needed
> cbBuf
) {
1915 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1922 /*****************************************************************************
1923 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1925 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
1926 DWORD Level
, LPBYTE pDriverDirectory
,
1927 DWORD cbBuf
, LPDWORD pcbNeeded
)
1929 LPSTR pNameA
= NULL
, pEnvironmentA
= NULL
;
1933 pNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pName
);
1935 pEnvironmentA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
);
1936 ret
= GetPrinterDriverDirectoryA( pNameA
, pEnvironmentA
, Level
,
1937 pDriverDirectory
, cbBuf
, pcbNeeded
);
1939 HeapFree( GetProcessHeap(), 0, pNameA
);
1941 HeapFree( GetProcessHeap(), 0, pEnvironment
);
1946 /*****************************************************************************
1947 * AddPrinterDriverA [WINSPOOL.120]
1949 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
1952 HKEY hkeyDrivers
, hkeyName
;
1954 TRACE("(%s,%ld,%p)\n",pName
,level
,pDriverInfo
);
1956 if(level
!= 2 && level
!= 3) {
1957 SetLastError(ERROR_INVALID_LEVEL
);
1961 FIXME("pName= `%s' - unsupported\n", pName
);
1962 SetLastError(ERROR_INVALID_PARAMETER
);
1966 WARN("pDriverInfo == NULL");
1967 SetLastError(ERROR_INVALID_PARAMETER
);
1972 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
1974 memset(&di3
, 0, sizeof(di3
));
1975 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
1978 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
1980 SetLastError(ERROR_INVALID_PARAMETER
);
1983 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
1984 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
1985 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
1986 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
1988 if(di3
.pEnvironment
) {
1989 FIXME("pEnvironment = `%s'\n", di3
.pEnvironment
);
1990 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1993 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
1995 ERR("Can't create Drivers key\n");
1999 if(level
== 2) { /* apparently can't overwrite with level2 */
2000 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2001 RegCloseKey(hkeyName
);
2002 RegCloseKey(hkeyDrivers
);
2003 WARN("Trying to create existing printer driver `%s'\n", di3
.pName
);
2004 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2008 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2009 RegCloseKey(hkeyDrivers
);
2010 ERR("Can't create Name key\n");
2013 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2015 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2016 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2017 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2019 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2020 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2021 di3
.pDependentFiles
, 0);
2022 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2023 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2024 RegCloseKey(hkeyName
);
2025 RegCloseKey(hkeyDrivers
);
2029 /*****************************************************************************
2030 * AddPrinterDriverW [WINSPOOL.121]
2032 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2035 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2041 /*****************************************************************************
2042 * PrinterProperties [WINSPOOL.201]
2044 * Displays a dialog to set the properties of the printer.
2047 * nonzero on succes or zero on faillure
2050 * implemented as stub only
2052 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* handle to parent window */
2053 HANDLE hPrinter
/* handle to printer object */
2055 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
2056 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2060 /*****************************************************************************
2061 * EnumJobsA [WINSPOOL.162]
2064 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2065 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2069 if(pcbNeeded
) *pcbNeeded
= 0;
2070 if(pcReturned
) *pcReturned
= 0;
2075 /*****************************************************************************
2076 * EnumJobsW [WINSPOOL.163]
2079 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2080 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2084 if(pcbNeeded
) *pcbNeeded
= 0;
2085 if(pcReturned
) *pcReturned
= 0;