4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
16 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(winspool
)
22 CRITICAL_SECTION PRINT32_RegistryBlocker
;
24 typedef struct _OPENEDPRINTERA
28 LPPRINTER_DEFAULTSA lpDefault
;
29 } OPENEDPRINTERA
, *LPOPENEDPRINTERA
;
31 /* The OpenedPrinter Table dynamic array */
32 static HDPA pOpenedPrinterDPA
= NULL
;
34 extern HDPA (WINAPI
* WINSPOOL_DPA_CreateEx
) (INT
, HANDLE
);
35 extern LPVOID (WINAPI
* WINSPOOL_DPA_GetPtr
) (const HDPA
, INT
);
36 extern INT (WINAPI
* WINSPOOL_DPA_InsertPtr
) (const HDPA
, INT
, LPVOID
);
38 static char Printers
[] =
39 "System\\CurrentControlSet\\control\\Print\\Printers\\";
40 static char Drivers
[] =
41 "System\\CurrentControlSet\\control\\Print\\Environments\\Wine\\Drivers\\";
43 /******************************************************************
44 * WINSPOOL_GetOpenedPrinterEntryA
45 * Get the first place empty in the opened printer table
47 static LPOPENEDPRINTERA
WINSPOOL_GetOpenedPrinterEntryA()
50 LPOPENEDPRINTERA pOpenedPrinter
;
53 * Create the opened printers' handle dynamic array.
55 if (!pOpenedPrinterDPA
)
57 pOpenedPrinterDPA
= WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
58 for (i
= 0; i
< 10; i
++)
60 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
62 sizeof(OPENEDPRINTERA
));
63 pOpenedPrinter
->hPrinter
= -1;
64 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
69 * Search for a handle not yet allocated.
71 for (i
= 0; i
< pOpenedPrinterDPA
->nItemCount
; i
++)
73 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, i
);
75 if (pOpenedPrinter
->hPrinter
== -1)
77 pOpenedPrinter
->hPrinter
= i
+ 1;
78 return pOpenedPrinter
;
83 * Didn't find one, insert new element in the array.
85 if (i
== pOpenedPrinterDPA
->nItemCount
)
87 pOpenedPrinter
= HeapAlloc(GetProcessHeap(),
89 sizeof(OPENEDPRINTERA
));
90 pOpenedPrinter
->hPrinter
= i
+ 1;
91 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA
, i
, pOpenedPrinter
);
92 return pOpenedPrinter
;
98 /******************************************************************
99 * WINSPOOL_GetOpenedPrinterA
100 * Get the pointer to the opened printer referred by the handle
102 static LPOPENEDPRINTERA
WINSPOOL_GetOpenedPrinterA(int printerHandle
)
104 LPOPENEDPRINTERA pOpenedPrinter
;
106 if(!pOpenedPrinterDPA
) return NULL
;
107 if((printerHandle
<=0) ||
108 (printerHandle
> (pOpenedPrinterDPA
->nItemCount
- 1)))
111 pOpenedPrinter
= WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA
, printerHandle
-1);
113 return pOpenedPrinter
;
116 /******************************************************************
117 * DeviceCapabilities32A [WINSPOOL.151]
120 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDeivce
,LPCSTR pPort
, WORD cap
,
121 LPSTR pOutput
, LPDEVMODEA lpdm
)
124 ret
= GDI_CallDeviceCapabilities16(pDeivce
, pPort
, cap
, pOutput
, lpdm
);
126 /* If DC_PAPERSIZE map POINT16s to POINTs */
127 if(ret
!= -1 && cap
== DC_PAPERSIZE
&& pOutput
) {
128 POINT16
*tmp
= HeapAlloc( GetProcessHeap(), 0, ret
* sizeof(POINT16
) );
130 memcpy(tmp
, pOutput
, ret
* sizeof(POINT16
));
131 for(i
= 0; i
< ret
; i
++)
132 CONV_POINT16TO32(tmp
+ i
, (POINT
*)pOutput
+ i
);
133 HeapFree( GetProcessHeap(), 0, tmp
);
139 /*****************************************************************************
140 * DeviceCapabilities32W
142 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
143 WORD fwCapability
, LPWSTR pOutput
,
144 const DEVMODEW
*pDevMode
)
146 FIXME("(%p,%p,%d,%p,%p): stub\n",
147 pDevice
, pPort
, fwCapability
, pOutput
, pDevMode
);
151 /******************************************************************
152 * DocumentProperties32A [WINSPOOL.155]
155 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
156 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
157 LPDEVMODEA pDevModeInput
,DWORD fMode
)
159 LPOPENEDPRINTERA lpOpenedPrinter
;
160 LPSTR lpName
= pDeviceName
;
162 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
163 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
167 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
168 if(!lpOpenedPrinter
) {
169 SetLastError(ERROR_INVALID_HANDLE
);
172 lpName
= lpOpenedPrinter
->lpsPrinterName
;
175 return GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, NULL
,
176 pDevModeInput
, NULL
, fMode
);
181 /*****************************************************************************
182 * DocumentProperties32W
184 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
186 LPDEVMODEW pDevModeOutput
,
187 LPDEVMODEW pDevModeInput
, DWORD fMode
)
189 FIXME("(%d,%d,%s,%p,%p,%ld): stub\n",
190 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
196 /******************************************************************
197 * OpenPrinter32A [WINSPOOL.196]
200 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
201 LPPRINTER_DEFAULTSA pDefault
)
203 /* Not implemented: use the DesiredAccess of pDefault to set
204 the access rights to the printer */
206 LPOPENEDPRINTERA lpOpenedPrinter
;
207 HKEY hkeyPrinters
, hkeyPrinter
;
209 TRACE("(printerName: %s, pDefault %p\n", lpPrinterName
, pDefault
);
211 /* Check Printer exists */
212 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
214 ERR("Can't create Printers key\n");
215 SetLastError(ERROR_FILE_NOT_FOUND
); /* ?? */
219 if(RegOpenKeyA(hkeyPrinters
, lpPrinterName
, &hkeyPrinter
)
221 WARN("Can't find printer `%s' in registry\n", lpPrinterName
);
222 RegCloseKey(hkeyPrinters
);
223 SetLastError(ERROR_INVALID_PARAMETER
);
226 RegCloseKey(hkeyPrinter
);
227 RegCloseKey(hkeyPrinters
);
229 if(!phPrinter
) /* This seems to be what win95 does anyway */
232 /* Get a place in the opened printer buffer*/
233 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterEntryA();
234 if(!lpOpenedPrinter
) {
235 ERR("Can't allocate printer slot\n");
236 SetLastError(ERROR_OUTOFMEMORY
);
240 /* Get the name of the printer */
241 lpOpenedPrinter
->lpsPrinterName
=
242 HEAP_strdupA( GetProcessHeap(), 0, lpPrinterName
);
244 /* Get the unique handle of the printer*/
245 *phPrinter
= lpOpenedPrinter
->hPrinter
;
247 if (pDefault
!= NULL
) {
248 lpOpenedPrinter
->lpDefault
=
249 HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA
));
250 lpOpenedPrinter
->lpDefault
->pDevMode
=
251 HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA
));
252 memcpy(lpOpenedPrinter
->lpDefault
->pDevMode
, pDefault
->pDevMode
,
254 lpOpenedPrinter
->lpDefault
->pDatatype
=
255 HEAP_strdupA( GetProcessHeap(), 0, pDefault
->pDatatype
);
256 lpOpenedPrinter
->lpDefault
->DesiredAccess
=
257 pDefault
->DesiredAccess
;
264 /******************************************************************
265 * OpenPrinter32W [WINSPOOL.197]
268 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
269 LPPRINTER_DEFAULTSW pDefault
)
271 FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName
), phPrinter
,
273 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
280 /******************************************************************
281 * ENUMPRINTERS_GetDWORDFromRegistryA internal
283 * Reads a DWORD from registry KeyName
286 * value on OK or NULL on error
288 DWORD
ENUMPRINTERS_GetDWORDFromRegistryA(
289 HKEY hPrinterSettings
, /* handle to registry key */
290 LPSTR KeyName
/* name key to retrieve string from*/
297 if (RegQueryValueExA(hPrinterSettings
, KeyName
, NULL
, &DataType
,
298 Data
, &DataSize
)!=ERROR_SUCCESS
)
299 FIXME("Query of register '%s' didn't succeed?\n", KeyName
);
300 if (DataType
== REG_DWORD_LITTLE_ENDIAN
)
301 Result
= Data
[0] + (Data
[1]<<8) + (Data
[2]<<16) + (Data
[3]<<24);
302 if (DataType
== REG_DWORD_BIG_ENDIAN
)
303 Result
= Data
[3] + (Data
[2]<<8) + (Data
[1]<<16) + (Data
[0]<<24);
308 /******************************************************************
309 * ENUMPRINTERS_AddStringFromRegistryA internal
311 * Reads a string from registry KeyName and writes it at
312 * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
315 * FALSE if there is still space left in the buffer.
317 BOOL
ENUMPRINTERS_AddStringFromRegistryA(
318 HKEY hPrinterSettings
, /* handle to registry key */
319 LPSTR KeyName
, /* name key to retrieve string from*/
320 LPSTR
* Dest
, /* pointer to write string addres to */
321 LPBYTE lpbPrinters
, /* buffer which receives info*/
322 LPDWORD dwNextStringPos
,/* pos in buffer for next string */
323 DWORD dwBufSize
, /* max size of buffer in bytes */
324 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
328 LPSTR Data
= (LPSTR
) malloc(DataSize
*sizeof(char));
330 TRACE("Reading '%s'\n", KeyName
);
331 while((ret
= RegQueryValueExA(hPrinterSettings
, KeyName
, NULL
, &DataType
,
332 Data
, &DataSize
))==ERROR_MORE_DATA
)
334 Data
= (LPSTR
) realloc(Data
, DataSize
+2);
336 if (ret
!= ERROR_SUCCESS
) {
340 else if (DataType
== REG_SZ
)
342 if (bCalcSpaceOnly
==FALSE
)
343 *Dest
= &lpbPrinters
[*dwNextStringPos
];
344 *dwNextStringPos
+= DataSize
+1;
345 if (*dwNextStringPos
> dwBufSize
)
347 if (bCalcSpaceOnly
==FALSE
)
349 if (DataSize
==0) /* DataSize = 0 means empty string, even though*/
350 *Dest
[0]=0; /* the data itself needs not to be empty */
356 WARN("Expected string setting, got %lx\n", DataType
);
360 return(bCalcSpaceOnly
);
365 /******************************************************************
366 * ENUMPRINTERS_AddInfo2A internal
368 * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos]
369 * for printer PrinterNameKey.
370 * Note that there is no check whether the information really fits!
373 * FALSE if there is still space left in the buffer.
376 * This function should not only read the registry but also ask the driver
379 BOOL
ENUMPRINTERS_AddInfo2A(
380 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
381 LPBYTE lpbPrinters
, /* buffer which receives info*/
382 DWORD dwNextStructPos
, /* pos in buffer for struct */
383 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
384 DWORD dwBufSize
, /* max size of buffer in bytes */
385 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
387 HKEY hPrinterSettings
;
390 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
391 strlen(lpszPrinterName
)+2);
392 LPPRINTER_INFO_2A lpPInfo2
= (LPPRINTER_INFO_2A
) &lpbPrinters
[dwNextStructPos
];
394 /* open the registry to find the attributes, etc of the printer */
395 if (lpszPrinterSettings
!=NULL
)
397 strcpy(lpszPrinterSettings
,Printers
);
398 strcat(lpszPrinterSettings
,lpszPrinterName
);
400 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
401 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
403 WARN("The registry did not contain my printer anymore?\n");
407 if (bCalcSpaceOnly
==FALSE
)
408 lpPInfo2
->pServerName
= NULL
;
409 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
410 "Name", &(lpPInfo2
->pPrinterName
),
411 lpbPrinters
, dwNextStringPos
,
412 dwBufSize
, bCalcSpaceOnly
);
413 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
414 "Share Name", &(lpPInfo2
->pShareName
),
415 lpbPrinters
, dwNextStringPos
,
416 dwBufSize
, bCalcSpaceOnly
);
417 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
418 "Port", &(lpPInfo2
->pPortName
),
419 lpbPrinters
, dwNextStringPos
,
420 dwBufSize
, bCalcSpaceOnly
);
421 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
422 "Printer Driver", &(lpPInfo2
->pDriverName
),
423 lpbPrinters
, dwNextStringPos
,
424 dwBufSize
, bCalcSpaceOnly
);
425 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
426 "Description", &(lpPInfo2
->pComment
),
427 lpbPrinters
, dwNextStringPos
,
428 dwBufSize
, bCalcSpaceOnly
);
429 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
430 "Location", &(lpPInfo2
->pLocation
),
431 lpbPrinters
, dwNextStringPos
,
432 dwBufSize
, bCalcSpaceOnly
);
434 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
435 "Separator File", &(lpPInfo2
->pSepFile
),
436 lpbPrinters
, dwNextStringPos
,
437 dwBufSize
, bCalcSpaceOnly
);
438 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
439 "Print Processor", &(lpPInfo2
->pPrintProcessor
),
440 lpbPrinters
, dwNextStringPos
,
441 dwBufSize
, bCalcSpaceOnly
);
442 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
443 "Datatype", &(lpPInfo2
->pDatatype
),
444 lpbPrinters
, dwNextStringPos
,
445 dwBufSize
, bCalcSpaceOnly
);
446 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
447 "Parameters", &(lpPInfo2
->pParameters
),
448 lpbPrinters
, dwNextStringPos
,
449 dwBufSize
, bCalcSpaceOnly
);
450 if (bCalcSpaceOnly
== FALSE
)
452 lpPInfo2
->pSecurityDescriptor
= NULL
; /* EnumPrinters doesn't return this*/
454 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
455 lpPInfo2
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
456 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
457 lpPInfo2
->Priority
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
459 lpPInfo2
->DefaultPriority
= ENUMPRINTERS_GetDWORDFromRegistryA(
460 hPrinterSettings
, "Default Priority");
461 lpPInfo2
->StartTime
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
463 lpPInfo2
->UntilTime
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
465 lpPInfo2
->Status
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
467 lpPInfo2
->cJobs
= 0; /* FIXME: according to MSDN, this does not
468 * reflect the TotalJobs Key ??? */
469 lpPInfo2
->AveragePPM
= 0; /* FIXME: according to MSDN, this does not
470 * reflect the TotalPages Key ??? */
472 /* and read the devModes structure... */
473 RegQueryValueExA(hPrinterSettings
, "pDevMode", NULL
, &DataType
,
474 NULL
, &DevSize
); /* should return ERROR_MORE_DATA */
475 lpPInfo2
->pDevMode
= (LPDEVMODEA
) &lpbPrinters
[*dwNextStringPos
];
476 *dwNextStringPos
+= DevSize
+ 1;
478 if (*dwNextStringPos
> dwBufSize
)
480 if (bCalcSpaceOnly
==FALSE
)
481 RegQueryValueExA(hPrinterSettings
, "pDevMode", NULL
, &DataType
,
482 (LPBYTE
)lpPInfo2
->pDevMode
, &DevSize
);
485 if (lpszPrinterSettings
)
486 free(lpszPrinterSettings
);
488 return(bCalcSpaceOnly
);
491 /******************************************************************
492 * ENUMPRINTERS_AddInfo4A internal
494 * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos]
495 * for printer PrinterNameKey.
496 * Note that there is no check whether the information really fits!
499 * FALSE if there is still space left in the buffer.
502 * This function should not exist in Win95 mode, but does anyway.
504 BOOL
ENUMPRINTERS_AddInfo4A(
505 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
506 LPBYTE lpbPrinters
, /* buffer which receives info*/
507 DWORD dwNextStructPos
, /* pos in buffer for struct */
508 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
509 DWORD dwBufSize
, /* max size of buffer in bytes */
510 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
512 HKEY hPrinterSettings
;
513 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
514 strlen(lpszPrinterName
)+2);
515 LPPRINTER_INFO_4A lpPInfo4
= (LPPRINTER_INFO_4A
) &lpbPrinters
[dwNextStructPos
];
517 /* open the registry to find the attributes of the printer */
518 if (lpszPrinterSettings
!=NULL
)
520 strcpy(lpszPrinterSettings
,Printers
);
521 strcat(lpszPrinterSettings
,lpszPrinterName
);
523 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
524 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
526 WARN("The registry did not contain my printer anymore?\n");
530 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
531 "Name", &(lpPInfo4
->pPrinterName
),
532 lpbPrinters
, dwNextStringPos
,
533 dwBufSize
, bCalcSpaceOnly
);
534 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
535 if (bCalcSpaceOnly
==FALSE
)
536 lpPInfo4
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
537 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
539 if (lpszPrinterSettings
)
540 free(lpszPrinterSettings
);
542 return(bCalcSpaceOnly
);
545 /******************************************************************
546 * ENUMPRINTERS_AddInfo5A internal
548 * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos]
549 * for printer PrinterNameKey.
550 * Settings are read from the registry.
551 * Note that there is no check whether the information really fits!
553 * FALSE if there is still space left in the buffer.
555 BOOL
ENUMPRINTERS_AddInfo5A(
556 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
557 LPBYTE lpbPrinters
, /* buffer which receives info*/
558 DWORD dwNextStructPos
, /* pos in buffer for struct */
559 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
560 DWORD dwBufSize
, /* max size of buffer in bytes */
561 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
563 HKEY hPrinterSettings
;
564 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
565 strlen(lpszPrinterName
)+2);
566 LPPRINTER_INFO_5A lpPInfo5
= (LPPRINTER_INFO_5A
) &lpbPrinters
[dwNextStructPos
];
568 /* open the registry to find the attributes, etc of the printer */
569 if (lpszPrinterSettings
!=NULL
)
571 strcpy(lpszPrinterSettings
,Printers
);
572 strcat(lpszPrinterSettings
,lpszPrinterName
);
574 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
575 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
577 WARN("The registry did not contain my printer anymore?\n");
581 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
582 "Name", &(lpPInfo5
->pPrinterName
),
583 lpbPrinters
, dwNextStringPos
,
584 dwBufSize
, bCalcSpaceOnly
);
585 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
586 "Port", &(lpPInfo5
->pPortName
), lpbPrinters
,
587 dwNextStringPos
, dwBufSize
, bCalcSpaceOnly
);
588 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
589 if (bCalcSpaceOnly
== FALSE
)
591 lpPInfo5
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
592 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
593 lpPInfo5
->DeviceNotSelectedTimeOut
594 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
596 lpPInfo5
->TransmissionRetryTimeout
597 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
602 if (lpszPrinterSettings
)
603 free(lpszPrinterSettings
);
605 return(bCalcSpaceOnly
);
609 /******************************************************************
610 * EnumPrintersA [WINSPOOL.174]
612 * Enumerates the available printers, print servers and print
613 * providers, depending on the specified flags, name and level.
617 * If level is set to 1:
618 * Not implemented yet!
619 * Returns TRUE with an empty list.
621 * If level is set to 2:
622 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
623 * Returns an array of PRINTER_INFO_2 data structures in the
624 * lpbPrinters buffer. Note that according to MSDN also an
625 * OpenPrinter should be performed on every remote printer.
627 * If level is set to 4 (officially WinNT only):
628 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
629 * Fast: Only the registry is queried to retrieve printer names,
630 * no connection to the driver is made.
631 * Returns an array of PRINTER_INFO_4 data structures in the
632 * lpbPrinters buffer.
634 * If level is set to 5 (officially WinNT4/Win9x only):
635 * Fast: Only the registry is queried to retrieve printer names,
636 * no connection to the driver is made.
637 * Returns an array of PRINTER_INFO_5 data structures in the
638 * lpbPrinters buffer.
640 * If level set to 3 or 6+:
641 * returns zero (faillure!)
643 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
647 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
648 * - Only levels 2, 4 and 5 are implemented at the moment.
649 * - 16-bit printer drivers are not enumerated.
650 * - Returned amount of bytes used/needed does not match the real Windoze
651 * implementation (as in this implementation, all strings are part
652 * of the buffer, whereas Win32 keeps them somewhere else)
653 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
656 * - In a regular Wine installation, no registry settings for printers
657 * exist, which makes this function return an empty list.
659 BOOL WINAPI
EnumPrintersA(
660 DWORD dwType
, /* Types of print objects to enumerate */
661 LPSTR lpszName
, /* name of objects to enumerate */
662 DWORD dwLevel
, /* type of printer info structure */
663 LPBYTE lpbPrinters
, /* buffer which receives info */
664 DWORD cbBuf
, /* max size of buffer in bytes */
665 LPDWORD lpdwNeeded
, /* pointer to var: # bytes used/needed */
666 LPDWORD lpdwReturned
/* number of entries returned */
669 HKEY hPrinterListKey
;
671 char PrinterName
[255];
672 DWORD PrinterNameLength
=255;
674 DWORD dwNextStringPos
; /* position of next space for a string in the buffer*/
675 DWORD dwStructPrinterInfoSize
; /* size of a Printer_Info_X structure */
676 BOOL bCalcSpaceOnly
=FALSE
;/*if TRUE: don't store data, just calculate space*/
680 /* test whether we're requested to really fill in. If so,
681 * zero out the data area, and initialise some returns to zero,
682 * to prevent problems
684 if (lpbPrinters
==NULL
|| cbBuf
==0)
689 for (i
=0; i
<cbBuf
; i
++)
695 /* check for valid Flags */
696 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
)))
698 FIXME("dwType = %08lx\n", dwType
);
699 SetLastError(ERROR_INVALID_FLAGS
);
711 SetLastError(ERROR_INVALID_LEVEL
);
715 /* Enter critical section to prevent AddPrinters() et al. to
716 * modify whilst we're reading in the registry
718 InitializeCriticalSection(&PRINT32_RegistryBlocker
);
719 EnterCriticalSection(&PRINT32_RegistryBlocker
);
721 /* get a pointer to a list of all printer names in the registry */
722 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, Printers
, 0, KEY_READ
,
723 &hPrinterListKey
) !=ERROR_SUCCESS
)
725 /* Oh no! An empty list of printers!
726 * (which is a valid configuration anyway)
728 TRACE("No entries in the Printers part of the registry\n");
731 /* count the number of entries and check if it fits in the buffer
733 while(RegEnumKeyExA(hPrinterListKey
, dwIndex
, PrinterName
, &PrinterNameLength
,
734 NULL
, NULL
, NULL
, &FileTime
)==ERROR_SUCCESS
)
736 PrinterNameLength
=255;
739 *lpdwReturned
= dwIndex
;
743 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_1A
);
746 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_2A
);
749 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_4A
);
752 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_5A
);
755 dwStructPrinterInfoSize
= 0;
758 if (dwIndex
*dwStructPrinterInfoSize
+1 > cbBuf
)
759 bCalcSpaceOnly
= TRUE
;
761 /* the strings which contain e.g. PrinterName, PortName, etc,
762 * are also stored in lpbPrinters, but after the regular structs.
763 * dwNextStringPos will always point to the next free place for a
766 dwNextStringPos
=(dwIndex
+1)*dwStructPrinterInfoSize
;
768 /* check each entry: if OK, add to list in corresponding INFO .
770 for(dwIndex
=0; dwIndex
< *lpdwReturned
; dwIndex
++)
772 PrinterNameLength
=255;
773 if (RegEnumKeyExA(hPrinterListKey
, dwIndex
, PrinterName
, &PrinterNameLength
,
774 NULL
, NULL
, NULL
, &FileTime
)!=ERROR_SUCCESS
)
775 break; /* exit for loop*/
776 TRACE("Got printer '%s'\n", PrinterName
);
778 /* check whether this printer is allowed in the list
779 * by comparing name to lpszName
781 if (dwType
& PRINTER_ENUM_NAME
)
782 if (strcmp(PrinterName
,lpszName
)!=0)
788 /* FIXME: unimplemented */
791 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo2A(PrinterName
, lpbPrinters
,
792 dwIndex
*dwStructPrinterInfoSize
,
793 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
796 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo4A(PrinterName
, lpbPrinters
,
797 dwIndex
*dwStructPrinterInfoSize
,
798 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
801 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo5A(PrinterName
, lpbPrinters
,
802 dwIndex
*dwStructPrinterInfoSize
,
803 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
807 RegCloseKey(hPrinterListKey
);
808 LeaveCriticalSection(&PRINT32_RegistryBlocker
);
809 *lpdwNeeded
= dwNextStringPos
+ 10; /*Hack*/
811 if (bCalcSpaceOnly
==TRUE
)
813 if (lpbPrinters
!=NULL
)
816 for (i
=0; i
<cbBuf
; i
++)
820 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
826 /******************************************************************
827 * EnumPrinters32W [WINSPOOL.175]
830 BOOL WINAPI
EnumPrintersW(DWORD dwType
, LPWSTR lpszName
,
831 DWORD dwLevel
, LPBYTE lpbPrinters
,
832 DWORD cbBuf
, LPDWORD lpdwNeeded
,
833 LPDWORD lpdwReturned
)
835 FIXME("Nearly empty stub\n");
841 /******************************************************************
842 * AddMonitor32A [WINSPOOL.107]
845 BOOL WINAPI
AddMonitorA(LPSTR pName
, DWORD Level
, LPBYTE pMonitors
)
847 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
848 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
852 /******************************************************************
853 * DeletePrinterDriver32A [WINSPOOL.146]
857 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
859 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
860 debugstr_a(pDriverName
));
861 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
866 /******************************************************************
867 * DeleteMonitor32A [WINSPOOL.135]
871 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
873 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
874 debugstr_a(pMonitorName
));
875 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
880 /******************************************************************
881 * DeletePort32A [WINSPOOL.137]
885 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
887 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
888 debugstr_a(pPortName
));
889 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
893 /******************************************************************************
894 * SetPrinter32W [WINSPOOL.214]
904 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
908 /******************************************************************************
909 * WritePrinter32 [WINSPOOL.223]
919 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
923 /*****************************************************************************
924 * AddForm32A [WINSPOOL.103]
926 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
928 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
932 /*****************************************************************************
933 * AddForm32W [WINSPOOL.104]
935 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
937 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
941 /*****************************************************************************
942 * AddJob32A [WINSPOOL.105]
944 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
945 DWORD cbBuf
, LPDWORD pcbNeeded
)
947 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
952 /*****************************************************************************
953 * AddJob32W [WINSPOOL.106]
955 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
958 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
963 /*****************************************************************************
964 * AddPrinter32A [WINSPOOL.117]
966 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
968 PRINTER_INFO_2A
*pi
= (PRINTER_INFO_2A
*) pPrinter
;
971 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
973 TRACE("(%s,%ld,%p)\n", pName
, Level
, pPrinter
);
976 FIXME("pName = `%s' - unsupported\n", pName
);
977 SetLastError(ERROR_INVALID_PARAMETER
);
981 WARN("Level = %ld\n", Level
);
982 SetLastError(ERROR_INVALID_LEVEL
);
986 SetLastError(ERROR_INVALID_PARAMETER
);
989 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
991 ERR("Can't create Printers key\n");
994 if(RegOpenKeyA(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) ==
996 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
997 RegCloseKey(hkeyPrinter
);
998 RegCloseKey(hkeyPrinters
);
1001 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
1003 ERR("Can't create Drivers key\n");
1004 RegCloseKey(hkeyPrinters
);
1007 if(RegOpenKeyA(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
1009 WARN("Can't find driver `%s'\n", pi
->pDriverName
);
1010 RegCloseKey(hkeyPrinters
);
1011 RegCloseKey(hkeyDrivers
);
1012 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
1015 RegCloseKey(hkeyDriver
);
1016 RegCloseKey(hkeyDrivers
);
1017 if(strcasecmp(pi
->pPrintProcessor
, "WinPrint")) { /* FIXME */
1018 WARN("Can't find processor `%s'\n", pi
->pPrintProcessor
);
1019 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
1020 RegCloseKey(hkeyPrinters
);
1023 if(RegCreateKeyA(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
1025 WARN("Can't create printer `%s'\n", pi
->pPrinterName
);
1026 SetLastError(ERROR_INVALID_PRINTER_NAME
);
1027 RegCloseKey(hkeyPrinters
);
1030 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
1031 (LPSTR
)&pi
->Attributes
, sizeof(DWORD
));
1032 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
,
1033 (LPSTR
)&pi
->pDevMode
,
1034 pi
->pDevMode
? pi
->pDevMode
->dmSize
: 0);
1035 RegSetValueExA(hkeyPrinter
, "Description", 0, REG_SZ
, pi
->pComment
, 0);
1036 RegSetValueExA(hkeyPrinter
, "Location", 0, REG_SZ
, pi
->pLocation
, 0);
1037 RegSetValueExA(hkeyPrinter
, "Name", 0, REG_SZ
, pi
->pPrinterName
, 0);
1038 RegSetValueExA(hkeyPrinter
, "Parameters", 0, REG_SZ
, pi
->pParameters
, 0);
1039 RegSetValueExA(hkeyPrinter
, "Port", 0, REG_SZ
, pi
->pPortName
, 0);
1040 RegSetValueExA(hkeyPrinter
, "Print Processor", 0, REG_SZ
,
1041 pi
->pPrintProcessor
, 0);
1042 RegSetValueExA(hkeyPrinter
, "Printer Driver", 0, REG_SZ
, pi
->pDriverName
,
1044 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
1045 (LPSTR
)&pi
->Priority
, sizeof(DWORD
));
1046 RegSetValueExA(hkeyPrinter
, "Separator File", 0, REG_SZ
, pi
->pSepFile
, 0);
1047 RegSetValueExA(hkeyPrinter
, "Share Name", 0, REG_SZ
, pi
->pShareName
, 0);
1048 RegSetValueExA(hkeyPrinter
, "Start Time", 0, REG_DWORD
,
1049 (LPSTR
)&pi
->StartTime
, sizeof(DWORD
));
1050 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
1051 (LPSTR
)&pi
->Status
, sizeof(DWORD
));
1052 RegSetValueExA(hkeyPrinter
, "Until Time", 0, REG_DWORD
,
1053 (LPSTR
)&pi
->UntilTime
, sizeof(DWORD
));
1055 RegCloseKey(hkeyPrinter
);
1056 RegCloseKey(hkeyPrinters
);
1057 if(!OpenPrinterA(pi
->pPrinterName
, &retval
, NULL
)) {
1058 ERR("OpenPrinter failing\n");
1064 /*****************************************************************************
1065 * AddPrinter32W [WINSPOOL.122]
1067 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1069 FIXME("(%p,%ld,%p): stub\n", pName
, Level
, pPrinter
);
1074 /*****************************************************************************
1075 * ClosePrinter32 [WINSPOOL.126]
1077 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
1079 LPOPENEDPRINTERA lpOpenedPrinter
;
1081 TRACE("Handle %d\n", hPrinter
);
1083 if (!pOpenedPrinterDPA
)
1086 if ((hPrinter
!= -1) && (hPrinter
< (pOpenedPrinterDPA
->nItemCount
- 1)))
1088 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
1089 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter
->lpsPrinterName
);
1090 lpOpenedPrinter
->lpsPrinterName
= NULL
;
1092 /* Free the memory of lpDefault if it has been initialized*/
1093 if(lpOpenedPrinter
->lpDefault
!= NULL
)
1095 HeapFree(GetProcessHeap(), 0,
1096 lpOpenedPrinter
->lpDefault
->pDevMode
);
1097 HeapFree(GetProcessHeap(), 0,
1098 lpOpenedPrinter
->lpDefault
->pDatatype
);
1099 HeapFree(GetProcessHeap(), 0,
1100 lpOpenedPrinter
->lpDefault
);
1101 lpOpenedPrinter
->lpDefault
= NULL
;
1104 lpOpenedPrinter
->hPrinter
= -1;
1111 /*****************************************************************************
1112 * DeleteForm32A [WINSPOOL.133]
1114 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
1116 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
1120 /*****************************************************************************
1121 * DeleteForm32W [WINSPOOL.134]
1123 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
1125 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
1129 /*****************************************************************************
1130 * DeletePrinter32 [WINSPOOL.143]
1132 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
1134 FIXME("(%d): stub\n", hPrinter
);
1138 /*****************************************************************************
1139 * SetPrinter32A [WINSPOOL.211]
1141 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1144 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
1148 /*****************************************************************************
1149 * SetJob32A [WINSPOOL.209]
1151 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1152 LPBYTE pJob
, DWORD Command
)
1154 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1159 /*****************************************************************************
1160 * SetJob32W [WINSPOOL.210]
1162 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1163 LPBYTE pJob
, DWORD Command
)
1165 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1170 /*****************************************************************************
1171 * GetForm32A [WINSPOOL.181]
1173 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1174 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1176 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1177 Level
,pForm
,cbBuf
,pcbNeeded
);
1181 /*****************************************************************************
1182 * GetForm32W [WINSPOOL.182]
1184 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1185 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1187 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1188 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1192 /*****************************************************************************
1193 * SetForm32A [WINSPOOL.207]
1195 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1198 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1202 /*****************************************************************************
1203 * SetForm32W [WINSPOOL.208]
1205 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1208 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1212 /*****************************************************************************
1213 * ReadPrinter32 [WINSPOOL.202]
1215 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1216 LPDWORD pNoBytesRead
)
1218 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1222 /*****************************************************************************
1223 * ResetPrinter32A [WINSPOOL.203]
1225 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1227 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1231 /*****************************************************************************
1232 * ResetPrinter32W [WINSPOOL.204]
1234 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1236 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1241 /*****************************************************************************
1242 * WINSPOOL_GetStringFromRegA
1244 * Get ValueName from hkey storing result in str. buflen is space left in str
1246 static BOOL
WINSPOOL_GetStringFromRegA(HKEY hkey
, LPCSTR ValueName
, LPSTR ptr
,
1247 DWORD buflen
, DWORD
*needed
)
1249 DWORD sz
= buflen
, type
;
1252 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1254 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1255 ERR("Got ret = %ld\n", ret
);
1262 /*********************************************************************
1263 * WINSPOOL_GetPrinter_2A
1265 * Fills out a PRINTER_INFO_2A struct storing the strings in buf.
1267 static BOOL
WINSPOOL_GetPrinter_2A(HKEY hkeyPrinter
, PRINTER_INFO_2A
*pi2
,
1268 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1270 DWORD size
, left
= cbBuf
;
1271 BOOL space
= (cbBuf
> 0);
1276 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Name", ptr
, left
, &size
);
1277 if(space
&& size
<= left
) {
1278 pi2
->pPrinterName
= ptr
;
1285 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Port", ptr
, left
, &size
);
1286 if(space
&& size
<= left
) {
1287 pi2
->pPortName
= ptr
;
1294 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Printer Driver", ptr
, left
,
1296 if(space
&& size
<= left
) {
1297 pi2
->pDriverName
= ptr
;
1304 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Default DevMode", ptr
, left
,
1306 if(space
&& size
<= left
) {
1307 pi2
->pDevMode
= (LPDEVMODEA
)ptr
;
1314 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Print Processor", ptr
, left
,
1316 if(space
&& size
<= left
) {
1317 pi2
->pPrintProcessor
= ptr
;
1324 if(!space
&& pi2
) /* zero out pi2 if we can't completely fill buf */
1325 memset(pi2
, 0, sizeof(*pi2
));
1330 /*********************************************************************
1331 * WINSPOOL_GetPrinter_4A
1333 * Fills out a PRINTER_INFO_4A struct storing the strings in buf.
1335 static BOOL
WINSPOOL_GetPrinter_4A(HKEY hkeyPrinter
, PRINTER_INFO_4A
*pi4
,
1336 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1338 DWORD size
, left
= cbBuf
;
1339 BOOL space
= (cbBuf
> 0);
1344 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Name", ptr
, left
, &size
);
1345 if(space
&& size
<= left
) {
1346 pi4
->pPrinterName
= ptr
;
1354 if(!space
&& pi4
) /* zero out pi4 if we can't completely fill buf */
1355 memset(pi4
, 0, sizeof(*pi4
));
1360 /*********************************************************************
1361 * WINSPOOL_GetPrinter_5A
1363 * Fills out a PRINTER_INFO_5A struct storing the strings in buf.
1365 static BOOL
WINSPOOL_GetPrinter_5A(HKEY hkeyPrinter
, PRINTER_INFO_5A
*pi5
,
1366 LPBYTE buf
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1368 DWORD size
, left
= cbBuf
;
1369 BOOL space
= (cbBuf
> 0);
1374 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Name", ptr
, left
, &size
);
1375 if(space
&& size
<= left
) {
1376 pi5
->pPrinterName
= ptr
;
1383 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Port", ptr
, left
, &size
);
1384 if(space
&& size
<= left
) {
1385 pi5
->pPortName
= ptr
;
1392 if(!space
&& pi5
) /* zero out pi5 if we can't completely fill buf */
1393 memset(pi5
, 0, sizeof(*pi5
));
1398 /*****************************************************************************
1399 * GetPrinterA [WINSPOOL.187]
1401 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1402 DWORD cbBuf
, LPDWORD pcbNeeded
)
1404 OPENEDPRINTERA
*lpOpenedPrinter
;
1405 DWORD size
, needed
= 0;
1407 HKEY hkeyPrinter
, hkeyPrinters
;
1410 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1412 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
1413 if(!lpOpenedPrinter
) {
1414 SetLastError(ERROR_INVALID_HANDLE
);
1417 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1419 ERR("Can't create Printers key\n");
1422 if(RegOpenKeyA(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1424 ERR("Can't find opened printer `%s' in registry\n",
1425 lpOpenedPrinter
->lpsPrinterName
);
1426 RegCloseKey(hkeyPrinters
);
1427 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1434 PRINTER_INFO_2A
*pi2
= (PRINTER_INFO_2A
*)pPrinter
;
1436 size
= sizeof(PRINTER_INFO_2A
);
1438 ptr
= pPrinter
+ size
;
1440 memset(pPrinter
, 0, size
);
1445 ret
= WINSPOOL_GetPrinter_2A(hkeyPrinter
, pi2
, ptr
, cbBuf
, &needed
);
1452 PRINTER_INFO_4A
*pi4
= (PRINTER_INFO_4A
*)pPrinter
;
1454 size
= sizeof(PRINTER_INFO_4A
);
1456 ptr
= pPrinter
+ size
;
1458 memset(pPrinter
, 0, size
);
1463 ret
= WINSPOOL_GetPrinter_4A(hkeyPrinter
, pi4
, ptr
, cbBuf
, &needed
);
1471 PRINTER_INFO_5A
*pi5
= (PRINTER_INFO_5A
*)pPrinter
;
1473 size
= sizeof(PRINTER_INFO_5A
);
1475 ptr
= pPrinter
+ size
;
1477 memset(pPrinter
, 0, size
);
1483 ret
= WINSPOOL_GetPrinter_5A(hkeyPrinter
, pi5
, ptr
, cbBuf
, &needed
);
1489 FIXME("Unimplemented level %ld\n", Level
);
1490 SetLastError(ERROR_INVALID_LEVEL
);
1491 RegCloseKey(hkeyPrinters
);
1492 RegCloseKey(hkeyPrinter
);
1496 RegCloseKey(hkeyPrinter
);
1497 RegCloseKey(hkeyPrinters
);
1499 if(pcbNeeded
) *pcbNeeded
= needed
;
1501 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1506 /*****************************************************************************
1507 * GetPrinterW [WINSPOOL.194]
1509 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1510 DWORD cbBuf
, LPDWORD pcbNeeded
)
1512 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pPrinter
,
1518 /*****************************************************************************
1519 * GetPrinterDriver32A [WINSPOOL.190]
1521 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
1522 DWORD Level
, LPBYTE pDriverInfo
,
1523 DWORD cbBuf
, LPDWORD pcbNeeded
)
1525 OPENEDPRINTERA
*lpOpenedPrinter
;
1526 char DriverName
[100];
1527 DWORD ret
, type
, size
, dw
, needed
= 0;
1529 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
1531 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter
,pEnvironment
,
1532 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1534 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
1535 if(!lpOpenedPrinter
) {
1536 SetLastError(ERROR_INVALID_HANDLE
);
1540 FIXME("pEnvironment = `%s'\n", pEnvironment
);
1541 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1544 if(Level
< 1 || Level
> 3) {
1545 SetLastError(ERROR_INVALID_LEVEL
);
1548 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1550 ERR("Can't create Printers key\n");
1553 if(RegOpenKeyA(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1555 ERR("Can't find opened printer `%s' in registry\n",
1556 lpOpenedPrinter
->lpsPrinterName
);
1557 RegCloseKey(hkeyPrinters
);
1558 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1561 size
= sizeof(DriverName
);
1562 ret
= RegQueryValueExA(hkeyPrinter
, "Printer Driver", 0, &type
, DriverName
,
1564 RegCloseKey(hkeyPrinter
);
1565 RegCloseKey(hkeyPrinters
);
1566 if(ret
!= ERROR_SUCCESS
) {
1567 ERR("Can't get DriverName for printer `%s'\n",
1568 lpOpenedPrinter
->lpsPrinterName
);
1571 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
1573 ERR("Can't create Drivers key\n");
1576 if(RegOpenKeyA(hkeyDrivers
, DriverName
, &hkeyDriver
)
1578 ERR("Can't find driver `%s' in registry\n", DriverName
);
1579 RegCloseKey(hkeyDrivers
);
1580 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
1586 size
= sizeof(DRIVER_INFO_1A
);
1589 size
= sizeof(DRIVER_INFO_2A
);
1592 size
= sizeof(DRIVER_INFO_3A
);
1595 ERR("Invalid level\n");
1600 ptr
= pDriverInfo
+ size
;
1606 size
= strlen(DriverName
) + 1;
1609 strcpy(ptr
, DriverName
);
1611 ((DRIVER_INFO_1A
*)pDriverInfo
)->pName
= ptr
;
1613 ((DRIVER_INFO_2A
*)pDriverInfo
)->pName
= ptr
;
1619 DRIVER_INFO_2A
*di2
= (DRIVER_INFO_2A
*)pDriverInfo
;
1622 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
,
1625 WARN("Can't get Version\n");
1629 size
= strlen("Wine") + 1; /* FIXME */
1632 strcpy(ptr
, "Wine");
1633 di2
->pEnvironment
= ptr
;
1639 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Driver", ptr
, cbBuf
, &size
);
1640 if(cbBuf
&& size
<= cbBuf
) {
1641 di2
->pDriverPath
= ptr
;
1647 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Data File", ptr
, cbBuf
, &size
);
1648 if(cbBuf
&& size
<= cbBuf
) {
1649 di2
->pDataFile
= ptr
;
1655 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Configuration File", ptr
,
1657 if(cbBuf
&& size
<= cbBuf
) {
1658 di2
->pConfigFile
= ptr
;
1666 DRIVER_INFO_3A
*di3
= (DRIVER_INFO_3A
*)pDriverInfo
;
1668 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Help File", ptr
, cbBuf
, &size
);
1669 if(cbBuf
&& size
<= cbBuf
) {
1670 di3
->pHelpFile
= ptr
;
1676 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Dependent Files", ptr
, cbBuf
,
1678 if(cbBuf
&& size
<= cbBuf
) {
1679 di3
->pDependentFiles
= ptr
;
1685 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Monitor", ptr
, cbBuf
, &size
);
1686 if(cbBuf
&& size
<= cbBuf
) {
1687 di3
->pMonitorName
= ptr
;
1693 WINSPOOL_GetStringFromRegA(hkeyDriver
, "DataType", ptr
, cbBuf
, &size
);
1694 if(cbBuf
&& size
<= cbBuf
) {
1695 di3
->pDefaultDataType
= ptr
;
1701 RegCloseKey(hkeyDriver
);
1702 RegCloseKey(hkeyDrivers
);
1704 if(pcbNeeded
) *pcbNeeded
= needed
;
1705 if(cbBuf
) return TRUE
;
1706 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1710 /*****************************************************************************
1711 * GetPrinterDriver32W [WINSPOOL.193]
1713 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
1714 DWORD Level
, LPBYTE pDriverInfo
,
1715 DWORD cbBuf
, LPDWORD pcbNeeded
)
1717 FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter
,pEnvironment
,
1718 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1722 /*****************************************************************************
1723 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1725 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
1726 DWORD Level
, LPBYTE pDriverDirectory
,
1727 DWORD cbBuf
, LPDWORD pcbNeeded
)
1731 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName
, pEnvironment
, Level
,
1732 pDriverDirectory
, cbBuf
, pcbNeeded
);
1734 FIXME("pName = `%s' - unsupported\n", pName
);
1735 SetLastError(ERROR_INVALID_PARAMETER
);
1738 if(pEnvironment
!= NULL
) {
1739 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment
);
1740 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1743 if(Level
!= 1) /* win95 ignores this so we just carry on */
1744 WARN("Level = %ld - assuming 1\n", Level
);
1746 /* FIXME should read from registry */
1747 needed
= GetSystemDirectoryA(pDriverDirectory
, cbBuf
);
1750 *pcbNeeded
= needed
;
1751 if(needed
> cbBuf
) {
1752 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1759 /*****************************************************************************
1760 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1762 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
1763 DWORD Level
, LPBYTE pDriverDirectory
,
1764 DWORD cbBuf
, LPDWORD pcbNeeded
)
1766 LPSTR pNameA
= NULL
, pEnvironmentA
= NULL
;
1770 pNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pName
);
1772 pEnvironmentA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
);
1773 ret
= GetPrinterDriverDirectoryA( pNameA
, pEnvironmentA
, Level
,
1774 pDriverDirectory
, cbBuf
, pcbNeeded
);
1776 HeapFree( GetProcessHeap(), 0, pNameA
);
1778 HeapFree( GetProcessHeap(), 0, pEnvironment
);
1783 /*****************************************************************************
1784 * AddPrinterDriver32A [WINSPOOL.120]
1786 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
1789 HKEY hkeyDrivers
, hkeyName
;
1791 TRACE("(%s,%ld,%p)\n",pName
,level
,pDriverInfo
);
1793 if(level
!= 2 && level
!= 3) {
1794 SetLastError(ERROR_INVALID_LEVEL
);
1798 FIXME("pName= `%s' - unsupported\n", pName
);
1799 SetLastError(ERROR_INVALID_PARAMETER
);
1803 WARN("pDriverInfo == NULL");
1804 SetLastError(ERROR_INVALID_PARAMETER
);
1809 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
1811 memset(&di3
, 0, sizeof(di3
));
1812 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
1815 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
1817 SetLastError(ERROR_INVALID_PARAMETER
);
1820 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
1821 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
1822 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
1823 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
1825 if(di3
.pEnvironment
) {
1826 FIXME("pEnvironment = `%s'\n", di3
.pEnvironment
);
1827 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1830 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
1832 ERR("Can't create Drivers key\n");
1836 if(level
== 2) { /* apparently can't overwrite with level2 */
1837 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
1838 RegCloseKey(hkeyName
);
1839 RegCloseKey(hkeyDrivers
);
1840 WARN("Trying to create existing printer driver `%s'\n", di3
.pName
);
1841 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
1845 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
1846 RegCloseKey(hkeyDrivers
);
1847 ERR("Can't create Name key\n");
1850 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
1852 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
1853 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
1854 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
1856 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
1857 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
1858 di3
.pDependentFiles
, 0);
1859 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
1860 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
1861 RegCloseKey(hkeyName
);
1862 RegCloseKey(hkeyDrivers
);
1866 /*****************************************************************************
1867 * AddPrinterDriver32W [WINSPOOL.121]
1869 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
1872 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
1878 /*****************************************************************************
1879 * PrinterProperties [WINSPOOL.201]
1881 * Displays a dialog to set the properties of the printer.
1884 * nonzero on succes or zero on faillure
1887 * implemented as stub only
1889 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* handle to parent window */
1890 HANDLE hPrinter
/* handle to printer object */
1892 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
1893 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1897 /*****************************************************************************
1898 * EnumJobsA [WINSPOOL.162]
1901 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
1902 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1906 if(pcbNeeded
) *pcbNeeded
= 0;
1907 if(pcReturned
) *pcReturned
= 0;
1912 /*****************************************************************************
1913 * EnumJobsW [WINSPOOL.163]
1916 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
1917 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1921 if(pcbNeeded
) *pcbNeeded
= 0;
1922 if(pcReturned
) *pcReturned
= 0;