4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
7 * Copyright 1999, 2000 Huw D M Davies
19 #include "wine/windef16.h"
20 #include "wine/unicode.h"
21 #include "debugtools.h"
26 DEFAULT_DEBUG_CHANNEL(winspool
);
28 typedef struct _OPENEDPRINTER
30 LPWSTR lpsPrinterName
;
32 } OPENEDPRINTER
, *LPOPENEDPRINTER
;
34 /* The OpenedPrinter Table dynamic array */
35 static HDPA pOpenedPrinterDPA
= NULL
;
37 extern HDPA (WINAPI
* WINSPOOL_DPA_CreateEx
) (INT
, HANDLE
);
38 extern LPVOID (WINAPI
* WINSPOOL_DPA_GetPtr
) (const HDPA
, INT
);
39 extern INT (WINAPI
* WINSPOOL_DPA_InsertPtr
) (const HDPA
, INT
, LPVOID
);
41 static DWORD (WINAPI
*GDI_CallDeviceCapabilities16
)( LPCSTR lpszDevice
, LPCSTR lpszPort
,
42 WORD fwCapability
, LPSTR lpszOutput
,
44 static INT (WINAPI
*GDI_CallExtDeviceMode16
)( HWND hwnd
, LPDEVMODEA lpdmOutput
,
45 LPSTR lpszDevice
, LPSTR lpszPort
,
46 LPDEVMODEA lpdmInput
, LPSTR lpszProfile
,
49 static char Printers
[] =
50 "System\\CurrentControlSet\\control\\Print\\Printers\\";
51 static char Drivers
[] =
52 "System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
54 static WCHAR DefaultEnvironmentW
[] = {'W','i','n','e',0};
56 static WCHAR Configuration_FileW
[] = {'C','o','n','f','i','g','u','r','a','t',
57 'i','o','n',' ','F','i','l','e',0};
58 static WCHAR DatatypeW
[] = {'D','a','t','a','t','y','p','e',0};
59 static WCHAR Data_FileW
[] = {'D','a','t','a',' ','F','i','l','e',0};
60 static WCHAR Default_DevModeW
[] = {'D','e','f','a','u','l','t',' ','D','e','v',
62 static WCHAR Dependent_FilesW
[] = {'D','e','p','e','n','d','e','n','t',' ','F',
64 static WCHAR DescriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
65 static WCHAR DriverW
[] = {'D','r','i','v','e','r',0};
66 static WCHAR Help_FileW
[] = {'H','e','l','p',' ','F','i','l','e',0};
67 static WCHAR LocationW
[] = {'L','o','c','a','t','i','o','n',0};
68 static WCHAR MonitorW
[] = {'M','o','n','i','t','o','r',0};
69 static WCHAR NameW
[] = {'N','a','m','e',0};
70 static WCHAR ParametersW
[] = {'P','a','r','a','m','e','t','e','r','s',0};
71 static WCHAR PortW
[] = {'P','o','r','t',0};
72 static WCHAR Print_ProcessorW
[] = {'P','r','i','n','t',' ','P','r','o','c','e',
74 static WCHAR Printer_DriverW
[] = {'P','r','i','n','t','e','r',' ','D','r','i',
76 static WCHAR Separator_FileW
[] = {'S','e','p','a','r','a','t','o','r',' ','F',
78 static WCHAR Share_NameW
[] = {'S','h','a','r','e',' ','N','a','m','e',0};
79 static WCHAR WinPrintW
[] = {'W','i','n','P','r','i','n','t',0};
81 /******************************************************************
82 * WINSPOOL_GetOpenedPrinterEntry
83 * Get the first place empty in the opened printer table
85 static LPOPENEDPRINTER
WINSPOOL_GetOpenedPrinterEntry()
88 LPOPENEDPRINTER pOpenedPrinter
;
91 * Create the opened printers' handle dynamic array.
93 if (!pOpenedPrinterDPA
)
95 pOpenedPrinterDPA
= WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
96 for (i
= 0; i
< 10; i
++)
98 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
100 sizeof(OPENEDPRINTER
));
101 pOpenedPrinter
->hPrinter
= -1;
102 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
107 * Search for a handle not yet allocated.
109 for (i
= 0; i
< pOpenedPrinterDPA
->nItemCount
; i
++)
111 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, i
);
113 if (pOpenedPrinter
->hPrinter
== -1)
115 pOpenedPrinter
->hPrinter
= i
+ 1;
116 return pOpenedPrinter
;
121 * Didn't find one, insert new element in the array.
123 if (i
== pOpenedPrinterDPA
->nItemCount
)
125 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
127 sizeof(OPENEDPRINTER
));
128 pOpenedPrinter
->hPrinter
= i
+ 1;
129 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
130 return pOpenedPrinter
;
136 /******************************************************************
137 * WINSPOOL_GetOpenedPrinter
138 * Get the pointer to the opened printer referred by the handle
140 static LPOPENEDPRINTER
WINSPOOL_GetOpenedPrinter(int printerHandle
)
142 LPOPENEDPRINTER pOpenedPrinter
;
144 if(!pOpenedPrinterDPA
) return NULL
;
145 if((printerHandle
<=0) ||
146 (printerHandle
> (pOpenedPrinterDPA
->nItemCount
- 1)))
149 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, printerHandle
-1);
151 return pOpenedPrinter
;
154 /***********************************************************
157 static LPDEVMODEW
DEVMODEcpyAtoW(DEVMODEW
*dmW
, const DEVMODEA
*dmA
)
160 ptrdiff_t off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
163 Formname
= (dmA
->dmSize
> off_formname
);
164 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
165 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmDeviceName
, -1, dmW
->dmDeviceName
,
168 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
169 dmA
->dmSize
- CCHDEVICENAME
);
171 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
,
172 off_formname
- CCHDEVICENAME
);
173 MultiByteToWideChar(CP_ACP
, 0, dmA
->dmFormName
, -1, dmW
->dmFormName
,
175 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA
->dmSize
-
176 (off_formname
+ CCHFORMNAME
));
179 memcpy((char *)dmW
+ dmW
->dmSize
, (char *)dmA
+ dmA
->dmSize
,
184 /***********************************************************
186 * Creates a unicode copy of supplied devmode on heap
188 static LPDEVMODEW
DEVMODEdupAtoW(HANDLE heap
, const DEVMODEA
*dmA
)
193 ptrdiff_t off_formname
;
196 if(!dmA
) return NULL
;
198 off_formname
= (char *)dmA
->dmFormName
- (char *)dmA
;
199 Formname
= (dmA
->dmSize
> off_formname
);
200 size
= dmA
->dmSize
+ CCHDEVICENAME
+ (Formname
? CCHFORMNAME
: 0);
201 dmW
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmA
->dmDriverExtra
);
202 return DEVMODEcpyAtoW(dmW
, dmA
);
205 /***********************************************************
207 * Creates an ascii copy of supplied devmode on heap
209 static LPDEVMODEA
DEVMODEdupWtoA(HANDLE heap
, const DEVMODEW
*dmW
)
214 ptrdiff_t off_formname
= (char *)dmW
->dmFormName
- (char *)dmW
;
216 if(!dmW
) return NULL
;
217 Formname
= (dmW
->dmSize
> off_formname
);
218 size
= dmW
->dmSize
- CCHDEVICENAME
- (Formname
? CCHFORMNAME
: 0);
219 dmA
= HeapAlloc(heap
, HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
220 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmDeviceName
, -1, dmA
->dmDeviceName
,
221 CCHDEVICENAME
, NULL
, NULL
);
223 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
224 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
));
226 memcpy(&dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
227 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
));
228 WideCharToMultiByte(CP_ACP
, 0, dmW
->dmFormName
, -1, dmA
->dmFormName
,
229 CCHFORMNAME
, NULL
, NULL
);
230 memcpy(&dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
231 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)));
234 memcpy((char *)dmA
+ dmA
->dmSize
, (char *)dmW
+ dmW
->dmSize
,
239 /***********************************************************
241 * Creates a unicode copy of PRINTER_INFO_2A on heap
243 static LPPRINTER_INFO_2W
PRINTER_INFO_2AtoW(HANDLE heap
, LPPRINTER_INFO_2A piA
)
245 LPPRINTER_INFO_2W piW
;
246 if(!piA
) return NULL
;
247 piW
= HeapAlloc(heap
, 0, sizeof(*piW
));
248 memcpy(piW
, piA
, sizeof(*piW
)); /* copy everything first */
249 piW
->pServerName
= HEAP_strdupAtoW(heap
, 0, piA
->pServerName
);
250 piW
->pPrinterName
= HEAP_strdupAtoW(heap
, 0, piA
->pPrinterName
);
251 piW
->pShareName
= HEAP_strdupAtoW(heap
, 0, piA
->pShareName
);
252 piW
->pPortName
= HEAP_strdupAtoW(heap
, 0, piA
->pPortName
);
253 piW
->pDriverName
= HEAP_strdupAtoW(heap
, 0, piA
->pDriverName
);
254 piW
->pComment
= HEAP_strdupAtoW(heap
, 0, piA
->pComment
);
255 piW
->pLocation
= HEAP_strdupAtoW(heap
, 0, piA
->pLocation
);
256 piW
->pDevMode
= DEVMODEdupAtoW(heap
, piA
->pDevMode
);
257 piW
->pSepFile
= HEAP_strdupAtoW(heap
, 0, piA
->pSepFile
);
258 piW
->pPrintProcessor
= HEAP_strdupAtoW(heap
, 0, piA
->pPrintProcessor
);
259 piW
->pDatatype
= HEAP_strdupAtoW(heap
, 0, piA
->pDatatype
);
260 piW
->pParameters
= HEAP_strdupAtoW(heap
, 0, piA
->pParameters
);
264 /***********************************************************
265 * FREE_PRINTER_INFO_2W
266 * Free PRINTER_INFO_2W and all strings
268 static void FREE_PRINTER_INFO_2W(HANDLE heap
, LPPRINTER_INFO_2W piW
)
272 HeapFree(heap
,0,piW
->pServerName
);
273 HeapFree(heap
,0,piW
->pPrinterName
);
274 HeapFree(heap
,0,piW
->pShareName
);
275 HeapFree(heap
,0,piW
->pPortName
);
276 HeapFree(heap
,0,piW
->pDriverName
);
277 HeapFree(heap
,0,piW
->pComment
);
278 HeapFree(heap
,0,piW
->pLocation
);
279 HeapFree(heap
,0,piW
->pDevMode
);
280 HeapFree(heap
,0,piW
->pSepFile
);
281 HeapFree(heap
,0,piW
->pPrintProcessor
);
282 HeapFree(heap
,0,piW
->pDatatype
);
283 HeapFree(heap
,0,piW
->pParameters
);
284 HeapFree(heap
,0,piW
);
288 /******************************************************************
289 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
292 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDevice
,LPCSTR pPort
, WORD cap
,
293 LPSTR pOutput
, LPDEVMODEA lpdm
)
297 if (!GDI_CallDeviceCapabilities16
)
299 GDI_CallDeviceCapabilities16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
301 if (!GDI_CallDeviceCapabilities16
) return -1;
303 ret
= GDI_CallDeviceCapabilities16(pDevice
, pPort
, cap
, pOutput
, lpdm
);
305 /* If DC_PAPERSIZE map POINT16s to POINTs */
306 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
307 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
308 POINT
*pt
= (POINT
*)pOutput
;
310 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
311 for(i
= 0; i
< ret
; i
++, pt
++)
316 HeapFree( GetProcessHeap(), 0, tmp
);
322 /*****************************************************************************
323 * DeviceCapabilitiesW [WINSPOOL.152]
325 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
328 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
329 WORD fwCapability
, LPWSTR pOutput
,
330 const DEVMODEW
*pDevMode
)
332 LPDEVMODEA dmA
= DEVMODEdupWtoA(GetProcessHeap(), pDevMode
);
333 LPSTR pDeviceA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDevice
);
334 LPSTR pPortA
= HEAP_strdupWtoA(GetProcessHeap(),0,pPort
);
337 if(pOutput
&& (fwCapability
== DC_BINNAMES
||
338 fwCapability
== DC_FILEDEPENDENCIES
||
339 fwCapability
== DC_PAPERNAMES
)) {
340 /* These need A -> W translation */
343 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, NULL
,
347 switch(fwCapability
) {
352 case DC_FILEDEPENDENCIES
:
356 pOutputA
= HeapAlloc(GetProcessHeap(), 0, size
* ret
);
357 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
, pOutputA
,
359 for(i
= 0; i
< ret
; i
++)
360 MultiByteToWideChar(CP_ACP
, 0, pOutputA
+ (i
* size
), -1,
361 pOutput
+ (i
* size
), size
);
362 HeapFree(GetProcessHeap(), 0, pOutputA
);
364 ret
= DeviceCapabilitiesA(pDeviceA
, pPortA
, fwCapability
,
365 (LPSTR
)pOutput
, dmA
);
367 HeapFree(GetProcessHeap(),0,pPortA
);
368 HeapFree(GetProcessHeap(),0,pDeviceA
);
369 HeapFree(GetProcessHeap(),0,dmA
);
373 /******************************************************************
374 * DocumentPropertiesA [WINSPOOL.155]
377 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
378 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
379 LPDEVMODEA pDevModeInput
,DWORD fMode
)
381 LPOPENEDPRINTER lpOpenedPrinter
;
382 LPSTR lpName
= pDeviceName
;
385 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
386 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
391 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
392 if(!lpOpenedPrinter
) {
393 SetLastError(ERROR_INVALID_HANDLE
);
396 lpNameW
= lpOpenedPrinter
->lpsPrinterName
;
397 lpName
= HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW
);
400 if (!GDI_CallExtDeviceMode16
)
402 GDI_CallExtDeviceMode16
= (void*)GetProcAddress( GetModuleHandleA("gdi32"),
404 if (!GDI_CallExtDeviceMode16
) return -1;
406 ret
= GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, "LPT1:",
407 pDevModeInput
, NULL
, fMode
);
410 HeapFree(GetProcessHeap(),0,lpName
);
415 /*****************************************************************************
416 * DocumentPropertiesW
418 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
420 LPDEVMODEW pDevModeOutput
,
421 LPDEVMODEW pDevModeInput
, DWORD fMode
)
424 LPSTR pDeviceNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName
);
425 LPDEVMODEA pDevModeInputA
= DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput
);
426 LPDEVMODEA pDevModeOutputA
= NULL
;
429 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
430 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
433 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, NULL
, NULL
, 0);
434 if(ret
< 0) return ret
;
435 pDevModeOutputA
= HeapAlloc(GetProcessHeap(), 0, ret
);
437 ret
= DocumentPropertiesA(hWnd
, hPrinter
, pDeviceNameA
, pDevModeOutputA
,
438 pDevModeInputA
, fMode
);
440 DEVMODEcpyAtoW(pDevModeOutput
, pDevModeOutputA
);
441 HeapFree(GetProcessHeap(),0,pDevModeOutputA
);
443 if(fMode
== 0 && ret
> 0)
444 ret
+= (CCHDEVICENAME
+ CCHFORMNAME
);
445 HeapFree(GetProcessHeap(),0,pDevModeInputA
);
446 HeapFree(GetProcessHeap(),0,pDeviceNameA
);
450 /******************************************************************
451 * OpenPrinterA [WINSPOOL.196]
454 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
455 LPPRINTER_DEFAULTSA pDefault
)
457 LPWSTR lpPrinterNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName
);
458 PRINTER_DEFAULTSW DefaultW
, *pDefaultW
= NULL
;
462 DefaultW
.pDatatype
= HEAP_strdupAtoW(GetProcessHeap(), 0,
463 pDefault
->pDatatype
);
464 DefaultW
.pDevMode
= DEVMODEdupAtoW(GetProcessHeap(),
466 DefaultW
.DesiredAccess
= pDefault
->DesiredAccess
;
467 pDefaultW
= &DefaultW
;
469 ret
= OpenPrinterW(lpPrinterNameW
, phPrinter
, pDefaultW
);
471 HeapFree(GetProcessHeap(), 0, DefaultW
.pDatatype
);
472 HeapFree(GetProcessHeap(), 0, DefaultW
.pDevMode
);
474 HeapFree(GetProcessHeap(), 0, lpPrinterNameW
);
478 /******************************************************************
479 * OpenPrinterW [WINSPOOL.197]
482 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
483 LPPRINTER_DEFAULTSW pDefault
)
485 LPOPENEDPRINTER lpOpenedPrinter
;
486 HKEY hkeyPrinters
, hkeyPrinter
;
488 if (!lpPrinterName
) {
489 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault
);
490 SetLastError(ERROR_INVALID_PARAMETER
);
494 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName
),
497 /* Check Printer exists */
498 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
500 ERR("Can't create Printers key\n");
501 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
505 if(RegOpenKeyW(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
507 WARN("Can't find printer %s in registry\n", debugstr_w(lpPrinterName
));
508 RegCloseKey(hkeyPrinters
);
509 SetLastError(ERROR_INVALID_PARAMETER
);
512 RegCloseKey(hkeyPrinter
);
513 RegCloseKey(hkeyPrinters
);
515 if(!phPrinter
) /* This seems to be what win95 does anyway */
518 /* Get a place in the opened printer buffer*/
519 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterEntry();
520 if(!lpOpenedPrinter
) {
521 ERR("Can't allocate printer slot\n");
522 SetLastError(ERROR_OUTOFMEMORY
);
526 /* Get the name of the printer */
527 lpOpenedPrinter
->lpsPrinterName
= HeapAlloc( GetProcessHeap(), 0,
528 (strlenW(lpPrinterName
)+1)*sizeof(WCHAR
) );
529 strcpyW( lpOpenedPrinter
->lpsPrinterName
, lpPrinterName
);
531 /* Get the unique handle of the printer*/
532 *phPrinter
= lpOpenedPrinter
->hPrinter
;
534 if (pDefault
!= NULL
)
535 FIXME("Not handling pDefault\n");
540 /******************************************************************
541 * AddMonitorA [WINSPOOL.107]
544 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
546 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
547 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
551 /******************************************************************
552 * DeletePrinterDriverA [WINSPOOL.146]
556 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
558 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
559 debugstr_a(pDriverName
));
560 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
565 /******************************************************************
566 * DeleteMonitorA [WINSPOOL.135]
570 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
572 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
573 debugstr_a(pMonitorName
));
574 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
579 /******************************************************************
580 * DeletePortA [WINSPOOL.137]
584 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
586 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
587 debugstr_a(pPortName
));
588 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
592 /******************************************************************************
593 * SetPrinterW [WINSPOOL.214]
603 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
607 /******************************************************************************
608 * WritePrinter [WINSPOOL.223]
618 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
622 /*****************************************************************************
623 * AddFormA [WINSPOOL.103]
625 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
627 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
631 /*****************************************************************************
632 * AddFormW [WINSPOOL.104]
634 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
636 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
640 /*****************************************************************************
641 * AddJobA [WINSPOOL.105]
643 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
644 DWORD cbBuf
, LPDWORD pcbNeeded
)
646 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
651 /*****************************************************************************
652 * AddJobW [WINSPOOL.106]
654 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
657 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
662 /*****************************************************************************
663 * WINSPOOL_OpenDriverReg [internal]
665 * opens the registry for the printer drivers depending on the given input
666 * variable pEnvironment
669 * the opened hkey on success
672 static HKEY
WINSPOOL_OpenDriverReg( LPVOID pEnvironment
, BOOL unicode
)
674 LPSTR lpKey
, p
= NULL
;
677 (unicode
) ? debugstr_w(pEnvironment
) : debugstr_a(pEnvironment
));
680 p
= (unicode
) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
) :
684 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
686 if(!GetVersionExA( &ver
))
689 switch (ver
.dwPlatformId
) {
690 case VER_PLATFORM_WIN32s
:
692 case VER_PLATFORM_WIN32_NT
:
693 p
= "Windows NT x86";
699 TRACE("set environment to %s\n", p
);
702 lpKey
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
703 strlen(p
) + strlen(Drivers
));
704 sprintf( lpKey
, Drivers
, p
);
706 TRACE("%s\n", lpKey
);
708 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, lpKey
, &retval
) !=
712 if(pEnvironment
&& unicode
)
713 HeapFree( GetProcessHeap(), 0, p
);
714 HeapFree( GetProcessHeap(), 0, lpKey
);
719 /*****************************************************************************
720 * AddPrinterW [WINSPOOL.122]
722 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
724 PRINTER_INFO_2W
*pi
= (PRINTER_INFO_2W
*) pPrinter
;
728 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
731 TRACE("(%s,%ld,%p)\n", debugstr_w(pName
), Level
, pPrinter
);
734 FIXME("pName = %s - unsupported\n", debugstr_w(pName
));
735 SetLastError(ERROR_INVALID_PARAMETER
);
739 WARN("Level = %ld\n", Level
);
740 SetLastError(ERROR_INVALID_LEVEL
);
744 SetLastError(ERROR_INVALID_PARAMETER
);
747 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
749 ERR("Can't create Printers key\n");
752 if(RegOpenKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) ==
754 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
755 RegCloseKey(hkeyPrinter
);
756 RegCloseKey(hkeyPrinters
);
759 hkeyDrivers
= WINSPOOL_OpenDriverReg( NULL
, TRUE
);
761 ERR("Can't create Drivers key\n");
762 RegCloseKey(hkeyPrinters
);
765 if(RegOpenKeyW(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
767 WARN("Can't find driver %s\n", debugstr_w(pi
->pDriverName
));
768 RegCloseKey(hkeyPrinters
);
769 RegCloseKey(hkeyDrivers
);
770 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
773 RegCloseKey(hkeyDriver
);
774 RegCloseKey(hkeyDrivers
);
776 if(lstrcmpiW(pi
->pPrintProcessor
, WinPrintW
)) { /* FIXME */
777 WARN("Can't find processor %s\n", debugstr_w(pi
->pPrintProcessor
));
778 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
779 RegCloseKey(hkeyPrinters
);
783 /* See if we can load the driver. We may need the devmode structure anyway
785 size
= DocumentPropertiesW(0, -1, pi
->pPrinterName
, NULL
, NULL
, 0);
787 WARN("DocumentProperties fails\n");
788 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
794 dmW
= HeapAlloc(GetProcessHeap(), 0, size
);
795 DocumentPropertiesW(0, -1, pi
->pPrinterName
, dmW
, NULL
, DM_OUT_BUFFER
);
798 if(RegCreateKeyW(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
800 WARN("Can't create printer %s\n", debugstr_w(pi
->pPrinterName
));
801 SetLastError(ERROR_INVALID_PRINTER_NAME
);
802 RegCloseKey(hkeyPrinters
);
804 HeapFree(GetProcessHeap(), 0, dmW
);
807 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
808 (LPBYTE
)&pi
->Attributes
, sizeof(DWORD
));
809 RegSetValueExW(hkeyPrinter
, DatatypeW
, 0, REG_SZ
, (LPBYTE
)pi
->pDatatype
,
812 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
813 and we support these drivers. NT writes DEVMODEW so somehow
814 we'll need to distinguish between these when we support NT
816 dmA
= DEVMODEdupWtoA(GetProcessHeap(), dmW
);
817 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
, (LPBYTE
)dmA
,
818 dmA
->dmSize
+ dmA
->dmDriverExtra
);
819 HeapFree(GetProcessHeap(), 0, dmA
);
821 HeapFree(GetProcessHeap(), 0, dmW
);
822 RegSetValueExW(hkeyPrinter
, DescriptionW
, 0, REG_SZ
, (LPBYTE
)pi
->pComment
,
824 RegSetValueExW(hkeyPrinter
, LocationW
, 0, REG_SZ
, (LPBYTE
)pi
->pLocation
,
826 RegSetValueExW(hkeyPrinter
, NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pPrinterName
, 0);
827 RegSetValueExW(hkeyPrinter
, ParametersW
, 0, REG_SZ
,
828 (LPBYTE
)pi
->pParameters
, 0);
829 RegSetValueExW(hkeyPrinter
, PortW
, 0, REG_SZ
, (LPBYTE
)pi
->pPortName
, 0);
830 RegSetValueExW(hkeyPrinter
, Print_ProcessorW
, 0, REG_SZ
,
831 (LPBYTE
)pi
->pPrintProcessor
, 0);
832 RegSetValueExW(hkeyPrinter
, Printer_DriverW
, 0, REG_SZ
,
833 (LPBYTE
)pi
->pDriverName
, 0);
834 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
835 (LPBYTE
)&pi
->Priority
, sizeof(DWORD
));
836 RegSetValueExW(hkeyPrinter
, Separator_FileW
, 0, REG_SZ
,
837 (LPBYTE
)pi
->pSepFile
, 0);
838 RegSetValueExW(hkeyPrinter
, Share_NameW
, 0, REG_SZ
, (LPBYTE
)pi
->pShareName
,
840 RegSetValueExA(hkeyPrinter
, "StartTime", 0, REG_DWORD
,
841 (LPBYTE
)&pi
->StartTime
, sizeof(DWORD
));
842 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
843 (LPBYTE
)&pi
->Status
, sizeof(DWORD
));
844 RegSetValueExA(hkeyPrinter
, "UntilTime", 0, REG_DWORD
,
845 (LPBYTE
)&pi
->UntilTime
, sizeof(DWORD
));
847 RegCloseKey(hkeyPrinter
);
848 RegCloseKey(hkeyPrinters
);
849 if(!OpenPrinterW(pi
->pPrinterName
, &retval
, NULL
)) {
850 ERR("OpenPrinter failing\n");
856 /*****************************************************************************
857 * AddPrinterA [WINSPOOL.117]
859 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
862 PRINTER_INFO_2W
*piW
;
863 PRINTER_INFO_2A
*piA
= (PRINTER_INFO_2A
*)pPrinter
;
866 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName
), Level
, pPrinter
);
868 WARN("Level = %ld\n", Level
);
869 SetLastError(ERROR_INVALID_LEVEL
);
872 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
873 piW
= PRINTER_INFO_2AtoW(GetProcessHeap(), piA
);
875 ret
= AddPrinterW(pNameW
, Level
, (LPBYTE
)piW
);
877 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW
);
878 HeapFree(GetProcessHeap(),0,pNameW
);
883 /*****************************************************************************
884 * ClosePrinter [WINSPOOL.126]
886 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
888 LPOPENEDPRINTER lpOpenedPrinter
;
890 TRACE("Handle %d\n", hPrinter
);
892 if (!pOpenedPrinterDPA
)
895 if ((hPrinter
!= -1) && (hPrinter
< (pOpenedPrinterDPA
->nItemCount
- 1)))
897 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
898 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter
->lpsPrinterName
);
899 lpOpenedPrinter
->lpsPrinterName
= NULL
;
900 lpOpenedPrinter
->hPrinter
= -1;
907 /*****************************************************************************
908 * DeleteFormA [WINSPOOL.133]
910 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
912 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
916 /*****************************************************************************
917 * DeleteFormW [WINSPOOL.134]
919 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
921 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
925 /*****************************************************************************
926 * DeletePrinter [WINSPOOL.143]
928 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
933 LPOPENEDPRINTER lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
934 if(!lpOpenedPrinter
) {
935 SetLastError(ERROR_INVALID_HANDLE
);
938 lpNameW
= lpOpenedPrinter
->lpsPrinterName
;
939 if(RegOpenKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
941 ERR("Can't open Printers key\n");
945 /* This should use a recursive delete see Q142491 or SHDeleteKey */
946 if(RegDeleteKeyW(hkeyPrinters
, lpNameW
) == ERROR_SUCCESS
) {
947 SetLastError(ERROR_PRINTER_NOT_FOUND
); /* ?? */
948 RegCloseKey(hkeyPrinters
);
952 ClosePrinter(hPrinter
);
956 /*****************************************************************************
957 * SetPrinterA [WINSPOOL.211]
959 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
962 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
966 /*****************************************************************************
967 * SetJobA [WINSPOOL.209]
969 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
970 LPBYTE pJob
, DWORD Command
)
972 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
977 /*****************************************************************************
978 * SetJobW [WINSPOOL.210]
980 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
981 LPBYTE pJob
, DWORD Command
)
983 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
988 /*****************************************************************************
989 * GetFormA [WINSPOOL.181]
991 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
992 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
994 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
995 Level
,pForm
,cbBuf
,pcbNeeded
);
999 /*****************************************************************************
1000 * GetFormW [WINSPOOL.182]
1002 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1003 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1005 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1006 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1010 /*****************************************************************************
1011 * SetFormA [WINSPOOL.207]
1013 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1016 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1020 /*****************************************************************************
1021 * SetFormW [WINSPOOL.208]
1023 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1026 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1030 /*****************************************************************************
1031 * ReadPrinter [WINSPOOL.202]
1033 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1034 LPDWORD pNoBytesRead
)
1036 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1040 /*****************************************************************************
1041 * ResetPrinterA [WINSPOOL.203]
1043 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1045 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1049 /*****************************************************************************
1050 * ResetPrinterW [WINSPOOL.204]
1052 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1054 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1058 /*****************************************************************************
1059 * WINSPOOL_GetDWORDFromReg
1061 * Return DWORD associated with ValueName from hkey.
1063 static DWORD
WINSPOOL_GetDWORDFromReg(HKEY hkey
, LPCSTR ValueName
)
1065 DWORD sz
= sizeof(DWORD
), type
, value
= 0;
1068 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, (LPBYTE
)&value
, &sz
);
1070 if(ret
!= ERROR_SUCCESS
) {
1071 WARN("Got ret = %ld on name %s\n", ret
, ValueName
);
1074 if(type
!= REG_DWORD
) {
1075 ERR("Got type %ld\n", type
);
1081 /*****************************************************************************
1082 * WINSPOOL_GetStringFromReg
1084 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1085 * String is stored either as unicode or ascii.
1086 * Bit of a hack here to get the ValueName if we want ascii.
1088 static BOOL
WINSPOOL_GetStringFromReg(HKEY hkey
, LPCWSTR ValueName
, LPBYTE ptr
,
1089 DWORD buflen
, DWORD
*needed
,
1092 DWORD sz
= buflen
, type
;
1096 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1098 LPSTR ValueNameA
= HEAP_strdupWtoA(GetProcessHeap(),0,ValueName
);
1099 ret
= RegQueryValueExA(hkey
, ValueNameA
, 0, &type
, ptr
, &sz
);
1100 HeapFree(GetProcessHeap(),0,ValueNameA
);
1102 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1103 WARN("Got ret = %ld\n", ret
);
1111 /*****************************************************************************
1112 * WINSPOOL_GetDevModeFromReg
1114 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1115 * DevMode is stored either as unicode or ascii.
1117 static BOOL
WINSPOOL_GetDevModeFromReg(HKEY hkey
, LPCWSTR ValueName
,
1119 DWORD buflen
, DWORD
*needed
,
1122 DWORD sz
= buflen
, type
;
1125 if (ptr
) memset(ptr
, 0, sizeof(DEVMODEA
));
1126 ret
= RegQueryValueExW(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1127 if ((ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)) sz
= 0;
1128 if (sz
< sizeof(DEVMODEA
))
1130 ERR("corrupted registry for %s\n", debugstr_w(ValueName
));
1131 sz
= sizeof(DEVMODEA
);
1133 /* ensures that dmSize is not erratically bogus if registry is invalid */
1134 if (ptr
&& ((DEVMODEA
*)ptr
)->dmSize
< sizeof(DEVMODEA
))
1135 ((DEVMODEA
*)ptr
)->dmSize
= sizeof(DEVMODEA
);
1137 sz
+= (CCHDEVICENAME
+ CCHFORMNAME
);
1139 DEVMODEW
*dmW
= DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA
*)ptr
);
1140 memcpy(ptr
, dmW
, sz
);
1141 HeapFree(GetProcessHeap(),0,dmW
);
1148 /*********************************************************************
1149 * WINSPOOL_GetPrinter_2
1151 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1152 * The strings are either stored as unicode or ascii.
1154 static BOOL
WINSPOOL_GetPrinter_2(HKEY hkeyPrinter
, PRINTER_INFO_2W
*pi2
,
1155 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1158 DWORD size
, left
= cbBuf
;
1159 BOOL space
= (cbBuf
> 0);
1164 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1166 if(space
&& size
<= left
) {
1167 pi2
->pPrinterName
= (LPWSTR
)ptr
;
1174 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Share_NameW
, ptr
, left
, &size
,
1176 if(space
&& size
<= left
) {
1177 pi2
->pShareName
= (LPWSTR
)ptr
;
1184 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1186 if(space
&& size
<= left
) {
1187 pi2
->pPortName
= (LPWSTR
)ptr
;
1194 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Printer_DriverW
, ptr
, left
,
1196 if(space
&& size
<= left
) {
1197 pi2
->pDriverName
= (LPWSTR
)ptr
;
1204 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DescriptionW
, ptr
, left
, &size
,
1206 if(space
&& size
<= left
) {
1207 pi2
->pComment
= (LPWSTR
)ptr
;
1214 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, LocationW
, ptr
, left
, &size
,
1216 if(space
&& size
<= left
) {
1217 pi2
->pLocation
= (LPWSTR
)ptr
;
1224 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter
, Default_DevModeW
, ptr
, left
,
1226 if(space
&& size
<= left
) {
1227 pi2
->pDevMode
= (LPDEVMODEW
)ptr
;
1234 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Separator_FileW
, ptr
, left
,
1236 if(space
&& size
<= left
) {
1237 pi2
->pSepFile
= (LPWSTR
)ptr
;
1244 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, Print_ProcessorW
, ptr
, left
,
1246 if(space
&& size
<= left
) {
1247 pi2
->pPrintProcessor
= (LPWSTR
)ptr
;
1254 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, DatatypeW
, ptr
, left
,
1256 if(space
&& size
<= left
) {
1257 pi2
->pDatatype
= (LPWSTR
)ptr
;
1264 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, ParametersW
, ptr
, left
,
1266 if(space
&& size
<= left
) {
1267 pi2
->pParameters
= (LPWSTR
)ptr
;
1275 pi2
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1276 pi2
->Priority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Priority");
1277 pi2
->DefaultPriority
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1278 "Default Priority");
1279 pi2
->StartTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "StartTime");
1280 pi2
->UntilTime
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "UntilTime");
1283 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1284 memset(pi2
, 0, sizeof(*pi2
));
1289 /*********************************************************************
1290 * WINSPOOL_GetPrinter_4
1292 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1294 static BOOL
WINSPOOL_GetPrinter_4(HKEY hkeyPrinter
, PRINTER_INFO_4W
*pi4
,
1295 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1298 DWORD size
, left
= cbBuf
;
1299 BOOL space
= (cbBuf
> 0);
1304 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1306 if(space
&& size
<= left
) {
1307 pi4
->pPrinterName
= (LPWSTR
)ptr
;
1315 pi4
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1318 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1319 memset(pi4
, 0, sizeof(*pi4
));
1324 /*********************************************************************
1325 * WINSPOOL_GetPrinter_5
1327 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1329 static BOOL
WINSPOOL_GetPrinter_5(HKEY hkeyPrinter
, PRINTER_INFO_5W
*pi5
,
1330 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1333 DWORD size
, left
= cbBuf
;
1334 BOOL space
= (cbBuf
> 0);
1339 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, NameW
, ptr
, left
, &size
,
1341 if(space
&& size
<= left
) {
1342 pi5
->pPrinterName
= (LPWSTR
)ptr
;
1349 if(WINSPOOL_GetStringFromReg(hkeyPrinter
, PortW
, ptr
, left
, &size
,
1351 if(space
&& size
<= left
) {
1352 pi5
->pPortName
= (LPWSTR
)ptr
;
1360 pi5
->Attributes
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
, "Attributes");
1361 pi5
->DeviceNotSelectedTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1363 pi5
->TransmissionRetryTimeout
= WINSPOOL_GetDWORDFromReg(hkeyPrinter
,
1367 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1368 memset(pi5
, 0, sizeof(*pi5
));
1373 /*****************************************************************************
1374 * WINSPOOL_GetPrinter
1376 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1377 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1378 * just a collection of pointers to strings.
1380 static BOOL
WINSPOOL_GetPrinter(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1381 DWORD cbBuf
, LPDWORD pcbNeeded
, BOOL unicode
)
1383 OPENEDPRINTER
*lpOpenedPrinter
;
1384 DWORD size
, needed
= 0;
1386 HKEY hkeyPrinter
, hkeyPrinters
;
1389 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1391 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1392 if(!lpOpenedPrinter
) {
1393 SetLastError(ERROR_INVALID_HANDLE
);
1396 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1398 ERR("Can't create Printers key\n");
1401 if(RegOpenKeyW(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1403 ERR("Can't find opened printer %s in registry\n",
1404 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1405 RegCloseKey(hkeyPrinters
);
1406 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1413 PRINTER_INFO_2W
*pi2
= (PRINTER_INFO_2W
*)pPrinter
;
1415 size
= sizeof(PRINTER_INFO_2W
);
1417 ptr
= pPrinter
+ size
;
1419 memset(pPrinter
, 0, size
);
1424 ret
= WINSPOOL_GetPrinter_2(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
,
1432 PRINTER_INFO_4W
*pi4
= (PRINTER_INFO_4W
*)pPrinter
;
1434 size
= sizeof(PRINTER_INFO_4W
);
1436 ptr
= pPrinter
+ size
;
1438 memset(pPrinter
, 0, size
);
1443 ret
= WINSPOOL_GetPrinter_4(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
,
1452 PRINTER_INFO_5W
*pi5
= (PRINTER_INFO_5W
*)pPrinter
;
1454 size
= sizeof(PRINTER_INFO_5W
);
1456 ptr
= pPrinter
+ size
;
1458 memset(pPrinter
, 0, size
);
1464 ret
= WINSPOOL_GetPrinter_5(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
,
1471 FIXME("Unimplemented level %ld\n", Level
);
1472 SetLastError(ERROR_INVALID_LEVEL
);
1473 RegCloseKey(hkeyPrinters
);
1474 RegCloseKey(hkeyPrinter
);
1478 RegCloseKey(hkeyPrinter
);
1479 RegCloseKey(hkeyPrinters
);
1481 TRACE("returing %d needed = %ld\n", ret
, needed
);
1482 if(pcbNeeded
) *pcbNeeded
= needed
;
1484 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1488 /*****************************************************************************
1489 * GetPrinterW [WINSPOOL.194]
1491 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1492 DWORD cbBuf
, LPDWORD pcbNeeded
)
1494 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1498 /*****************************************************************************
1499 * GetPrinterA [WINSPOOL.187]
1501 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1502 DWORD cbBuf
, LPDWORD pcbNeeded
)
1504 return WINSPOOL_GetPrinter(hPrinter
, Level
, pPrinter
, cbBuf
, pcbNeeded
,
1508 /*****************************************************************************
1509 * WINSPOOL_EnumPrinters
1511 * Implementation of EnumPrintersA|W
1513 static BOOL
WINSPOOL_EnumPrinters(DWORD dwType
, LPWSTR lpszName
,
1514 DWORD dwLevel
, LPBYTE lpbPrinters
,
1515 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1516 LPDWORD lpdwReturned
, BOOL unicode
)
1519 HKEY hkeyPrinters
, hkeyPrinter
;
1520 WCHAR PrinterName
[255];
1521 DWORD needed
= 0, number
= 0;
1522 DWORD used
, i
, left
;
1526 memset(lpbPrinters
, 0, cbBuf
);
1532 /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
1533 if(dwType
== PRINTER_ENUM_DEFAULT
)
1536 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
))) {
1537 FIXME("dwType = %08lx\n", dwType
);
1538 SetLastError(ERROR_INVALID_FLAGS
);
1542 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1544 ERR("Can't create Printers key\n");
1548 if(RegQueryInfoKeyA(hkeyPrinters
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
1549 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
1550 RegCloseKey(hkeyPrinters
);
1551 ERR("Can't query Printers key\n");
1554 TRACE("Found %ld printers\n", number
);
1558 RegCloseKey(hkeyPrinters
);
1560 *lpdwReturned
= number
;
1564 used
= number
* sizeof(PRINTER_INFO_2W
);
1567 used
= number
* sizeof(PRINTER_INFO_4W
);
1570 used
= number
* sizeof(PRINTER_INFO_5W
);
1574 SetLastError(ERROR_INVALID_LEVEL
);
1575 RegCloseKey(hkeyPrinters
);
1578 pi
= (used
<= cbBuf
) ? lpbPrinters
: NULL
;
1580 for(i
= 0; i
< number
; i
++) {
1581 if(RegEnumKeyW(hkeyPrinters
, i
, PrinterName
, sizeof(PrinterName
)) !=
1583 ERR("Can't enum key number %ld\n", i
);
1584 RegCloseKey(hkeyPrinters
);
1587 TRACE("Printer %ld is %s\n", i
, debugstr_w(PrinterName
));
1588 if(RegOpenKeyW(hkeyPrinters
, PrinterName
, &hkeyPrinter
) !=
1590 ERR("Can't open key %s\n", debugstr_w(PrinterName
));
1591 RegCloseKey(hkeyPrinters
);
1596 buf
= lpbPrinters
+ used
;
1597 left
= cbBuf
- used
;
1605 WINSPOOL_GetPrinter_2(hkeyPrinter
, (PRINTER_INFO_2W
*)pi
, buf
,
1606 left
, &needed
, unicode
);
1608 if(pi
) pi
+= sizeof(PRINTER_INFO_2W
);
1611 WINSPOOL_GetPrinter_4(hkeyPrinter
, (PRINTER_INFO_4W
*)pi
, buf
,
1612 left
, &needed
, unicode
);
1614 if(pi
) pi
+= sizeof(PRINTER_INFO_4W
);
1617 WINSPOOL_GetPrinter_5(hkeyPrinter
, (PRINTER_INFO_5W
*)pi
, buf
,
1618 left
, &needed
, unicode
);
1620 if(pi
) pi
+= sizeof(PRINTER_INFO_5W
);
1623 ERR("Shouldn't be here!\n");
1624 RegCloseKey(hkeyPrinter
);
1625 RegCloseKey(hkeyPrinters
);
1628 RegCloseKey(hkeyPrinter
);
1630 RegCloseKey(hkeyPrinters
);
1637 memset(lpbPrinters
, 0, cbBuf
);
1638 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1642 *lpdwReturned
= number
;
1643 SetLastError(ERROR_SUCCESS
);
1648 /******************************************************************
1649 * EnumPrintersW [WINSPOOL.175]
1651 * Enumerates the available printers, print servers and print
1652 * providers, depending on the specified flags, name and level.
1656 * If level is set to 1:
1657 * Not implemented yet!
1658 * Returns TRUE with an empty list.
1660 * If level is set to 2:
1661 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1662 * Returns an array of PRINTER_INFO_2 data structures in the
1663 * lpbPrinters buffer. Note that according to MSDN also an
1664 * OpenPrinter should be performed on every remote printer.
1666 * If level is set to 4 (officially WinNT only):
1667 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1668 * Fast: Only the registry is queried to retrieve printer names,
1669 * no connection to the driver is made.
1670 * Returns an array of PRINTER_INFO_4 data structures in the
1671 * lpbPrinters buffer.
1673 * If level is set to 5 (officially WinNT4/Win9x only):
1674 * Fast: Only the registry is queried to retrieve printer names,
1675 * no connection to the driver is made.
1676 * Returns an array of PRINTER_INFO_5 data structures in the
1677 * lpbPrinters buffer.
1679 * If level set to 3 or 6+:
1680 * returns zero (faillure!)
1682 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
1686 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1687 * - Only levels 2, 4 and 5 are implemented at the moment.
1688 * - 16-bit printer drivers are not enumerated.
1689 * - Returned amount of bytes used/needed does not match the real Windoze
1690 * implementation (as in this implementation, all strings are part
1691 * of the buffer, whereas Win32 keeps them somewhere else)
1692 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1695 * - In a regular Wine installation, no registry settings for printers
1696 * exist, which makes this function return an empty list.
1698 BOOL WINAPI
EnumPrintersW(
1699 DWORD dwType
, /* [in] Types of print objects to enumerate */
1700 LPWSTR lpszName
, /* [in] name of objects to enumerate */
1701 DWORD dwLevel
, /* [in] type of printer info structure */
1702 LPBYTE lpbPrinters
, /* [out] buffer which receives info */
1703 DWORD cbBuf
, /* [in] max size of buffer in bytes */
1704 LPDWORD lpdwNeeded
, /* [out] pointer to var: # bytes used/needed */
1705 LPDWORD lpdwReturned
/* [out] number of entries returned */
1708 return WINSPOOL_EnumPrinters(dwType
, lpszName
, dwLevel
, lpbPrinters
, cbBuf
,
1709 lpdwNeeded
, lpdwReturned
, TRUE
);
1712 /******************************************************************
1713 * EnumPrintersA [WINSPOOL.174]
1716 BOOL WINAPI
EnumPrintersA(DWORD dwType
, LPSTR lpszName
,
1717 DWORD dwLevel
, LPBYTE lpbPrinters
,
1718 DWORD cbBuf
, LPDWORD lpdwNeeded
,
1719 LPDWORD lpdwReturned
)
1722 LPWSTR lpszNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpszName
);
1724 ret
= WINSPOOL_EnumPrinters(dwType
, lpszNameW
, dwLevel
, lpbPrinters
, cbBuf
,
1725 lpdwNeeded
, lpdwReturned
, FALSE
);
1726 HeapFree(GetProcessHeap(),0,lpszNameW
);
1730 /*****************************************************************************
1731 * WINSPOOL_GetDriverInfoFromReg [internal]
1733 * Enters the information from the registry into the DRIVER_INFO struct
1736 * zero if the printer driver does not exist in the registry
1737 * (only if Level > 1) otherwise nonzero
1739 static BOOL
WINSPOOL_GetDriverInfoFromReg(
1742 LPWSTR pEnvironment
,
1744 LPBYTE ptr
, /* DRIVER_INFO */
1745 LPBYTE pDriverStrings
, /* strings buffer */
1746 DWORD cbBuf
, /* size of string buffer */
1747 LPDWORD pcbNeeded
, /* space needed for str. */
1748 BOOL unicode
) /* type of strings */
1749 { DWORD dw
, size
, tmp
, type
;
1751 LPBYTE strPtr
= pDriverStrings
;
1753 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
1754 debugstr_w(DriverName
), debugstr_w(pEnvironment
),
1755 Level
, ptr
, pDriverStrings
, cbBuf
, unicode
);
1758 *pcbNeeded
= (lstrlenW(DriverName
) + 1) * sizeof(WCHAR
);
1759 if (*pcbNeeded
<= cbBuf
)
1760 strcpyW((LPWSTR
)strPtr
, DriverName
);
1762 *pcbNeeded
= WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, NULL
, 0,
1764 if(*pcbNeeded
<= cbBuf
)
1765 WideCharToMultiByte(CP_ACP
, 0, DriverName
, -1, strPtr
, *pcbNeeded
,
1770 ((PDRIVER_INFO_1W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1774 ((PDRIVER_INFO_3W
) ptr
)->pName
= (LPWSTR
) strPtr
;
1775 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1778 if(RegOpenKeyW(hkeyDrivers
, DriverName
, &hkeyDriver
) != ERROR_SUCCESS
) {
1779 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName
));
1780 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
1785 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
, &size
) !=
1787 WARN("Can't get Version\n");
1789 ((PDRIVER_INFO_3A
) ptr
)->cVersion
= dw
;
1792 pEnvironment
= DefaultEnvironmentW
;
1794 size
= (lstrlenW(pEnvironment
) + 1) * sizeof(WCHAR
);
1796 size
= WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0,
1799 if(*pcbNeeded
<= cbBuf
) {
1801 strcpyW((LPWSTR
)strPtr
, pEnvironment
);
1803 WideCharToMultiByte(CP_ACP
, 0, pEnvironment
, -1, strPtr
, size
,
1806 ((PDRIVER_INFO_3W
) ptr
)->pEnvironment
= (LPWSTR
)strPtr
;
1807 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1810 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, 0, &size
,
1813 if(*pcbNeeded
<= cbBuf
)
1814 WINSPOOL_GetStringFromReg(hkeyDriver
, DriverW
, strPtr
, size
, &tmp
,
1817 ((PDRIVER_INFO_3W
) ptr
)->pDriverPath
= (LPWSTR
)strPtr
;
1818 strPtr
= (pDriverStrings
) ? (pDriverStrings
+ (*pcbNeeded
)) : NULL
;
1821 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, 0, &size
,
1824 if(*pcbNeeded
<= cbBuf
)
1825 WINSPOOL_GetStringFromReg(hkeyDriver
, Data_FileW
, strPtr
, size
,
1828 ((PDRIVER_INFO_3W
) ptr
)->pDataFile
= (LPWSTR
)strPtr
;
1829 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1832 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1833 0, &size
, unicode
)) {
1835 if(*pcbNeeded
<= cbBuf
)
1836 WINSPOOL_GetStringFromReg(hkeyDriver
, Configuration_FileW
, strPtr
,
1837 size
, &tmp
, unicode
);
1839 ((PDRIVER_INFO_3W
) ptr
)->pConfigFile
= (LPWSTR
)strPtr
;
1840 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1844 RegCloseKey(hkeyDriver
);
1845 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1849 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
, 0, &size
,
1852 if(*pcbNeeded
<= cbBuf
)
1853 WINSPOOL_GetStringFromReg(hkeyDriver
, Help_FileW
, strPtr
,
1854 size
, &tmp
, unicode
);
1856 ((PDRIVER_INFO_3W
) ptr
)->pHelpFile
= (LPWSTR
)strPtr
;
1857 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1860 if(WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
, 0,
1863 if(*pcbNeeded
<= cbBuf
)
1864 WINSPOOL_GetStringFromReg(hkeyDriver
, Dependent_FilesW
, strPtr
,
1865 size
, &tmp
, unicode
);
1867 ((PDRIVER_INFO_3W
) ptr
)->pDependentFiles
= (LPWSTR
)strPtr
;
1868 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1871 if(WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
, 0, &size
,
1874 if(*pcbNeeded
<= cbBuf
)
1875 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1876 size
, &tmp
, unicode
);
1878 ((PDRIVER_INFO_3W
) ptr
)->pMonitorName
= (LPWSTR
)strPtr
;
1879 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1882 if(WINSPOOL_GetStringFromReg(hkeyDriver
, DatatypeW
, strPtr
, 0, &size
,
1885 if(*pcbNeeded
<= cbBuf
)
1886 WINSPOOL_GetStringFromReg(hkeyDriver
, MonitorW
, strPtr
,
1887 size
, &tmp
, unicode
);
1889 ((PDRIVER_INFO_3W
) ptr
)->pDefaultDataType
= (LPWSTR
)strPtr
;
1890 strPtr
= (pDriverStrings
) ? pDriverStrings
+ (*pcbNeeded
) : NULL
;
1893 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1894 RegCloseKey(hkeyDriver
);
1898 /*****************************************************************************
1899 * WINSPOOL_GetPrinterDriver
1901 static BOOL
WINSPOOL_GetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
,
1902 DWORD Level
, LPBYTE pDriverInfo
,
1903 DWORD cbBuf
, LPDWORD pcbNeeded
,
1906 OPENEDPRINTER
*lpOpenedPrinter
;
1907 WCHAR DriverName
[100];
1908 DWORD ret
, type
, size
, needed
= 0;
1910 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDrivers
;
1912 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter
,debugstr_w(pEnvironment
),
1913 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1915 ZeroMemory(pDriverInfo
, cbBuf
);
1917 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinter(hPrinter
);
1918 if(!lpOpenedPrinter
) {
1919 SetLastError(ERROR_INVALID_HANDLE
);
1922 if(Level
< 1 || Level
> 3) {
1923 SetLastError(ERROR_INVALID_LEVEL
);
1926 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1928 ERR("Can't create Printers key\n");
1931 if(RegOpenKeyW(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1933 ERR("Can't find opened printer %s in registry\n",
1934 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1935 RegCloseKey(hkeyPrinters
);
1936 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1939 size
= sizeof(DriverName
);
1940 ret
= RegQueryValueExW(hkeyPrinter
, Printer_DriverW
, 0, &type
,
1941 (LPBYTE
)DriverName
, &size
);
1942 RegCloseKey(hkeyPrinter
);
1943 RegCloseKey(hkeyPrinters
);
1944 if(ret
!= ERROR_SUCCESS
) {
1945 ERR("Can't get DriverName for printer %s\n",
1946 debugstr_w(lpOpenedPrinter
->lpsPrinterName
));
1950 hkeyDrivers
= WINSPOOL_OpenDriverReg( pEnvironment
, TRUE
);
1952 ERR("Can't create Drivers key\n");
1958 size
= sizeof(DRIVER_INFO_1W
);
1961 size
= sizeof(DRIVER_INFO_2W
);
1964 size
= sizeof(DRIVER_INFO_3W
);
1967 ERR("Invalid level\n");
1972 ptr
= pDriverInfo
+ size
;
1974 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverName
,
1975 pEnvironment
, Level
, pDriverInfo
,
1976 (cbBuf
< size
) ? NULL
: ptr
,
1977 (cbBuf
< size
) ? 0 : cbBuf
- size
,
1978 &needed
, unicode
)) {
1979 RegCloseKey(hkeyDrivers
);
1983 RegCloseKey(hkeyDrivers
);
1985 if(pcbNeeded
) *pcbNeeded
= size
+ needed
;
1986 TRACE("buffer space %ld required %ld\n", cbBuf
, *pcbNeeded
);
1987 if(cbBuf
>= needed
) return TRUE
;
1988 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1992 /*****************************************************************************
1993 * GetPrinterDriverA [WINSPOOL.190]
1995 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
1996 DWORD Level
, LPBYTE pDriverInfo
,
1997 DWORD cbBuf
, LPDWORD pcbNeeded
)
2000 LPWSTR pEnvW
= HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment
);
2001 ret
= WINSPOOL_GetPrinterDriver(hPrinter
, pEnvW
, Level
, pDriverInfo
,
2002 cbBuf
, pcbNeeded
, FALSE
);
2003 HeapFree(GetProcessHeap(),0,pEnvW
);
2006 /*****************************************************************************
2007 * GetPrinterDriverW [WINSPOOL.193]
2009 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
2010 DWORD Level
, LPBYTE pDriverInfo
,
2011 DWORD cbBuf
, LPDWORD pcbNeeded
)
2013 return WINSPOOL_GetPrinterDriver(hPrinter
, pEnvironment
, Level
,
2014 pDriverInfo
, cbBuf
, pcbNeeded
, TRUE
);
2017 /*****************************************************************************
2018 * GetPrinterDriverDirectoryA [WINSPOOL.191]
2020 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
2021 DWORD Level
, LPBYTE pDriverDirectory
,
2022 DWORD cbBuf
, LPDWORD pcbNeeded
)
2026 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName
, pEnvironment
, Level
,
2027 pDriverDirectory
, cbBuf
, pcbNeeded
);
2029 FIXME("pName = `%s' - unsupported\n", pName
);
2030 SetLastError(ERROR_INVALID_PARAMETER
);
2033 if(pEnvironment
!= NULL
) {
2034 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment
);
2035 SetLastError(ERROR_INVALID_ENVIRONMENT
);
2038 if(Level
!= 1) /* win95 ignores this so we just carry on */
2039 WARN("Level = %ld - assuming 1\n", Level
);
2041 /* FIXME should read from registry */
2042 needed
= GetSystemDirectoryA(pDriverDirectory
, cbBuf
);
2045 *pcbNeeded
= needed
;
2046 if(needed
> cbBuf
) {
2047 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2054 /*****************************************************************************
2055 * GetPrinterDriverDirectoryW [WINSPOOL.192]
2057 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
2058 DWORD Level
, LPBYTE pDriverDirectory
,
2059 DWORD cbBuf
, LPDWORD pcbNeeded
)
2061 LPSTR pNameA
= NULL
, pEnvironmentA
= NULL
;
2065 pNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pName
);
2067 pEnvironmentA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
);
2068 ret
= GetPrinterDriverDirectoryA( pNameA
, pEnvironmentA
, Level
,
2069 pDriverDirectory
, cbBuf
, pcbNeeded
);
2071 HeapFree( GetProcessHeap(), 0, pNameA
);
2073 HeapFree( GetProcessHeap(), 0, pEnvironmentA
);
2078 /*****************************************************************************
2079 * AddPrinterDriverA [WINSPOOL.120]
2081 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
2084 HKEY hkeyDrivers
, hkeyName
;
2086 TRACE("(%s,%ld,%p)\n",pName
,level
,pDriverInfo
);
2088 if(level
!= 2 && level
!= 3) {
2089 SetLastError(ERROR_INVALID_LEVEL
);
2093 FIXME("pName= `%s' - unsupported\n", pName
);
2094 SetLastError(ERROR_INVALID_PARAMETER
);
2098 WARN("pDriverInfo == NULL");
2099 SetLastError(ERROR_INVALID_PARAMETER
);
2104 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
2106 memset(&di3
, 0, sizeof(di3
));
2107 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
2110 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
2112 SetLastError(ERROR_INVALID_PARAMETER
);
2115 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
2116 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
2117 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
2118 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
2120 hkeyDrivers
= WINSPOOL_OpenDriverReg(di3
.pEnvironment
, FALSE
);
2123 ERR("Can't create Drivers key\n");
2127 if(level
== 2) { /* apparently can't overwrite with level2 */
2128 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
2129 RegCloseKey(hkeyName
);
2130 RegCloseKey(hkeyDrivers
);
2131 WARN("Trying to create existing printer driver `%s'\n", di3
.pName
);
2132 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
2136 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
2137 RegCloseKey(hkeyDrivers
);
2138 ERR("Can't create Name key\n");
2141 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
2143 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
2144 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
2145 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
2147 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
2148 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
2149 di3
.pDependentFiles
, 0);
2150 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
2151 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
2152 RegCloseKey(hkeyName
);
2153 RegCloseKey(hkeyDrivers
);
2157 /*****************************************************************************
2158 * AddPrinterDriverW [WINSPOOL.121]
2160 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
2163 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
2169 /*****************************************************************************
2170 * PrinterProperties [WINSPOOL.201]
2172 * Displays a dialog to set the properties of the printer.
2175 * nonzero on succes or zero on faillure
2178 * implemented as stub only
2180 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* [in] handle to parent window */
2181 HANDLE hPrinter
/* [in] handle to printer object */
2183 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
2184 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2188 /*****************************************************************************
2189 * EnumJobsA [WINSPOOL.162]
2192 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2193 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2197 if(pcbNeeded
) *pcbNeeded
= 0;
2198 if(pcReturned
) *pcReturned
= 0;
2203 /*****************************************************************************
2204 * EnumJobsW [WINSPOOL.163]
2207 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
2208 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
2212 if(pcbNeeded
) *pcbNeeded
= 0;
2213 if(pcReturned
) *pcReturned
= 0;
2217 /*****************************************************************************
2218 * WINSPOOL_EnumPrinterDrivers [internal]
2220 * Delivers information about all installed printer drivers installed on
2221 * localhost or a given server
2224 * nonzero on succes or zero on failure, if the buffer for the returned
2225 * information is too small the function will return an error
2228 * - only implemented for localhost, foreign hosts will return an error
2230 static BOOL
WINSPOOL_EnumPrinterDrivers(LPWSTR pName
, LPWSTR pEnvironment
,
2231 DWORD Level
, LPBYTE pDriverInfo
,
2232 DWORD cbBuf
, LPDWORD pcbNeeded
,
2233 LPDWORD pcReturned
, BOOL unicode
)
2236 DWORD i
, needed
, number
= 0, size
= 0;
2237 WCHAR DriverNameW
[255];
2240 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2241 debugstr_w(pName
), debugstr_w(pEnvironment
),
2242 Level
, pDriverInfo
, cbBuf
, unicode
);
2244 /* check for local drivers */
2246 ERR("remote drivers unsupported! Current remote host is %s\n",
2251 /* check input parameter */
2252 if((Level
< 1) || (Level
> 3)) {
2253 ERR("unsupported level %ld \n", Level
);
2257 /* initialize return values */
2259 memset( pDriverInfo
, 0, cbBuf
);
2263 hkeyDrivers
= WINSPOOL_OpenDriverReg(pEnvironment
, TRUE
);
2265 ERR("Can't open Drivers key\n");
2269 if(RegQueryInfoKeyA(hkeyDrivers
, NULL
, NULL
, NULL
, &number
, NULL
, NULL
,
2270 NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) {
2271 RegCloseKey(hkeyDrivers
);
2272 ERR("Can't query Drivers key\n");
2275 TRACE("Found %ld Drivers\n", number
);
2277 /* get size of single struct
2278 * unicode and ascii structure have the same size
2282 size
= sizeof(DRIVER_INFO_1A
);
2285 size
= sizeof(DRIVER_INFO_2A
);
2288 size
= sizeof(DRIVER_INFO_3A
);
2292 /* calculate required buffer size */
2293 *pcbNeeded
= size
* number
;
2295 for( i
= 0, ptr
= (pDriverInfo
&& (cbBuf
>= size
)) ? pDriverInfo
: NULL
;
2297 i
++, ptr
= (ptr
&& (cbBuf
>= size
* i
)) ? ptr
+ size
: NULL
) {
2298 if(RegEnumKeyW(hkeyDrivers
, i
, DriverNameW
, sizeof(DriverNameW
))
2300 ERR("Can't enum key number %ld\n", i
);
2301 RegCloseKey(hkeyDrivers
);
2304 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers
, DriverNameW
,
2305 pEnvironment
, Level
, ptr
,
2306 (cbBuf
< *pcbNeeded
) ? NULL
: pDriverInfo
+ *pcbNeeded
,
2307 (cbBuf
< *pcbNeeded
) ? 0 : cbBuf
- *pcbNeeded
,
2308 &needed
, unicode
)) {
2309 RegCloseKey(hkeyDrivers
);
2312 (*pcbNeeded
) += needed
;
2315 RegCloseKey(hkeyDrivers
);
2317 if(cbBuf
< *pcbNeeded
){
2318 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2325 /*****************************************************************************
2326 * EnumPrinterDriversW [WINSPOOL.173]
2328 * see function EnumPrinterDrivers for RETURNS, BUGS
2330 BOOL WINAPI
EnumPrinterDriversW(LPWSTR pName
, LPWSTR pEnvironment
, DWORD Level
,
2331 LPBYTE pDriverInfo
, DWORD cbBuf
,
2332 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2334 return WINSPOOL_EnumPrinterDrivers(pName
, pEnvironment
, Level
, pDriverInfo
,
2335 cbBuf
, pcbNeeded
, pcReturned
, TRUE
);
2338 /*****************************************************************************
2339 * EnumPrinterDriversA [WINSPOOL.172]
2341 * see function EnumPrinterDrivers for RETURNS, BUGS
2343 BOOL WINAPI
EnumPrinterDriversA(LPSTR pName
, LPSTR pEnvironment
, DWORD Level
,
2344 LPBYTE pDriverInfo
, DWORD cbBuf
,
2345 LPDWORD pcbNeeded
, LPDWORD pcReturned
)
2347 WCHAR
*pNameW
= NULL
, *pEnvironmentW
= NULL
;
2350 pNameW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pName
);
2352 pEnvironmentW
= HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment
);
2354 ret
= WINSPOOL_EnumPrinterDrivers(pNameW
, pEnvironmentW
, Level
, pDriverInfo
,
2355 cbBuf
, pcbNeeded
, pcReturned
, FALSE
);
2357 HeapFree(GetProcessHeap(), 0, pNameW
);
2359 HeapFree(GetProcessHeap(), 0, pEnvironmentW
);
2365 /******************************************************************************
2366 * EnumPortsA (WINSPOOL.166)
2368 BOOL WINAPI
EnumPortsA(LPSTR name
,DWORD level
,LPBYTE ports
,DWORD bufsize
,
2369 LPDWORD bufneeded
,LPDWORD bufreturned
)
2371 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name
,level
,ports
,bufsize
,bufneeded
,bufreturned
);