4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
16 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(winspool
)
20 CRITICAL_SECTION PRINT32_RegistryBlocker
;
22 #define NUM_PRINTER_MAX 10
24 typedef struct _OPENEDPRINTERA
28 LPPRINTER_DEFAULTSA lpDefault
;
29 } OPENEDPRINTERA
, *LPOPENEDPRINTERA
;
32 /* Initialize the structure OpenedPrinter Table */
33 static OPENEDPRINTERA OpenedPrinterTableA
[NUM_PRINTER_MAX
] =
47 static char Printers
[] = "System\\CurrentControlSet\\Control\\Print\\Printers\\";
50 /******************************************************************
51 * WINSPOOL_GetOpenedPrinterEntryA
52 * Get the first place empty in the opened printer table
54 static LPOPENEDPRINTERA
WINSPOOL_GetOpenedPrinterEntryA()
57 for( i
=0; i
< NUM_PRINTER_MAX
; i
++)
58 if (OpenedPrinterTableA
[i
].hPrinter
== -1)
60 OpenedPrinterTableA
[i
].hPrinter
= i
+ 1;
61 return &OpenedPrinterTableA
[i
];
66 /******************************************************************
67 * WINSPOOL_GetOpenedPrinterA
68 * Get the pointer to the opened printer referred by the handle
70 static LPOPENEDPRINTERA
WINSPOOL_GetOpenedPrinterA(int printerHandle
)
72 if((printerHandle
<=0) || (printerHandle
> (NUM_PRINTER_MAX
+ 1)))
74 return &OpenedPrinterTableA
[printerHandle
-1];
77 /******************************************************************
78 * DeviceCapabilities32A [WINSPOOL.151]
81 INT WINAPI
DeviceCapabilitiesA(LPCSTR pDeivce
,LPCSTR pPort
, WORD cap
,
82 LPSTR pOutput
, LPDEVMODEA lpdm
)
84 return GDI_CallDeviceCapabilities16(pDeivce
, pPort
, cap
, pOutput
, lpdm
);
89 /*****************************************************************************
90 * DeviceCapabilities32W
92 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
93 WORD fwCapability
, LPWSTR pOutput
,
94 const DEVMODEW
*pDevMode
)
96 FIXME("(%p,%p,%d,%p,%p): stub\n",
97 pDevice
, pPort
, fwCapability
, pOutput
, pDevMode
);
101 /******************************************************************
102 * DocumentProperties32A [WINSPOOL.155]
105 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
106 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
107 LPDEVMODEA pDevModeInput
,DWORD fMode
)
109 LPOPENEDPRINTERA lpOpenedPrinter
;
110 LPSTR lpName
= pDeviceName
;
112 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
113 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
117 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
118 if(!lpOpenedPrinter
) {
119 SetLastError(ERROR_INVALID_HANDLE
);
122 lpName
= lpOpenedPrinter
->lpsPrinterName
;
125 return GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, NULL
,
126 pDevModeInput
, NULL
, fMode
);
131 /*****************************************************************************
132 * DocumentProperties32W
134 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
136 LPDEVMODEW pDevModeOutput
,
137 LPDEVMODEW pDevModeInput
, DWORD fMode
)
139 FIXME("(%d,%d,%s,%p,%p,%ld): stub\n",
140 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
146 /******************************************************************
147 * OpenPrinter32A [WINSPOOL.196]
150 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
151 LPPRINTER_DEFAULTSA pDefault
)
153 /* Not implemented: use the DesiredAccess of pDefault to set
154 the access rights to the printer */
156 LPOPENEDPRINTERA lpOpenedPrinter
;
158 TRACE("(printerName: %s, pDefault %p\n", lpPrinterName
, pDefault
);
160 /* Get a place in the opened printer buffer*/
161 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterEntryA();
163 if((lpOpenedPrinter
!= NULL
) && (lpPrinterName
!=NULL
) &&
166 /* Get the name of the printer */
167 lpOpenedPrinter
->lpsPrinterName
=
168 HeapAlloc(GetProcessHeap(), 0, lstrlenA(lpPrinterName
));
169 lstrcpyA(lpOpenedPrinter
->lpsPrinterName
, lpPrinterName
);
171 /* Get the unique handle of the printer*/
172 *phPrinter
= lpOpenedPrinter
->hPrinter
;
174 if (pDefault
!= NULL
)
176 /* Allocate enough memory for the lpDefault structure */
177 lpOpenedPrinter
->lpDefault
=
178 HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA
));
179 lpOpenedPrinter
->lpDefault
->pDevMode
=
180 HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA
));
181 lpOpenedPrinter
->lpDefault
->pDatatype
=
182 HeapAlloc(GetProcessHeap(), 0, lstrlenA(pDefault
->pDatatype
));
184 /*Copy the information from incoming parameter*/
185 memcpy(lpOpenedPrinter
->lpDefault
->pDevMode
, pDefault
->pDevMode
,
187 lstrcpyA(lpOpenedPrinter
->lpDefault
->pDatatype
,
188 pDefault
->pDatatype
);
189 lpOpenedPrinter
->lpDefault
->DesiredAccess
=
190 pDefault
->DesiredAccess
;
196 if(lpOpenedPrinter
== NULL
)
197 FIXME("Reach the OpenedPrinterTable maximum, augment this max.\n");
201 /******************************************************************
202 * OpenPrinter32W [WINSPOOL.197]
205 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
206 LPPRINTER_DEFAULTSW pDefault
)
208 FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName
), phPrinter
,
210 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
217 /******************************************************************
218 * ENUMPRINTERS_GetDWORDFromRegistryA internal
220 * Reads a DWORD from registry KeyName
223 * value on OK or NULL on error
225 DWORD
ENUMPRINTERS_GetDWORDFromRegistryA(
226 HKEY hPrinterSettings
, /* handle to registry key */
227 LPSTR KeyName
/* name key to retrieve string from*/
234 if (RegQueryValueExA(hPrinterSettings
, KeyName
, NULL
, &DataType
,
235 Data
, &DataSize
)!=ERROR_SUCCESS
)
236 FIXME("Query of register didn't succeed?\n");
237 if (DataType
== REG_DWORD_LITTLE_ENDIAN
)
238 Result
= Data
[0] + (Data
[1]<<8) + (Data
[2]<<16) + (Data
[3]<<24);
239 if (DataType
== REG_DWORD_BIG_ENDIAN
)
240 Result
= Data
[3] + (Data
[2]<<8) + (Data
[1]<<16) + (Data
[0]<<24);
245 /******************************************************************
246 * ENUMPRINTERS_AddStringFromRegistryA internal
248 * Reads a string from registry KeyName and writes it at
249 * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
252 * FALSE if there is still space left in the buffer.
254 BOOL
ENUMPRINTERS_AddStringFromRegistryA(
255 HKEY hPrinterSettings
, /* handle to registry key */
256 LPSTR KeyName
, /* name key to retrieve string from*/
257 LPSTR
* Dest
, /* pointer to write string addres to */
258 LPBYTE lpbPrinters
, /* buffer which receives info*/
259 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
260 DWORD dwBufSize
, /* max size of buffer in bytes */
261 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
265 LPSTR Data
= (LPSTR
) malloc(DataSize
*sizeof(char));
267 while(RegQueryValueExA(hPrinterSettings
, KeyName
, NULL
, &DataType
,
268 Data
, &DataSize
)==ERROR_MORE_DATA
)
270 Data
= (LPSTR
) realloc(Data
, DataSize
+2);
273 if (DataType
== REG_SZ
)
275 if (bCalcSpaceOnly
==FALSE
)
276 *Dest
= &lpbPrinters
[*dwNextStringPos
];
277 *dwNextStringPos
+= DataSize
+1;
278 if (*dwNextStringPos
> dwBufSize
)
280 if (bCalcSpaceOnly
==FALSE
)
282 if (DataSize
==0) /* DataSize = 0 means empty string, even though*/
283 *Dest
[0]=0; /* the data itself needs not to be empty */
289 WARN("Expected string setting, got something else from registry");
293 return(bCalcSpaceOnly
);
298 /******************************************************************
299 * ENUMPRINTERS_AddInfo2A internal
301 * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos]
302 * for printer PrinterNameKey.
303 * Note that there is no check whether the information really fits!
306 * FALSE if there is still space left in the buffer.
309 * This function should not only read the registry but also ask the driver
312 BOOL
ENUMPRINTERS_AddInfo2A(
313 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
314 LPBYTE lpbPrinters
, /* buffer which receives info*/
315 DWORD dwNextStructPos
, /* pos in buffer for struct */
316 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
317 DWORD dwBufSize
, /* max size of buffer in bytes */
318 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
320 HKEY hPrinterSettings
;
323 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
324 strlen(lpszPrinterName
)+2);
325 LPPRINTER_INFO_2A lpPInfo2
= (LPPRINTER_INFO_2A
) &lpbPrinters
[dwNextStructPos
];
327 /* open the registry to find the attributes, etc of the printer */
328 if (lpszPrinterSettings
!=NULL
)
330 strcpy(lpszPrinterSettings
,Printers
);
331 strcat(lpszPrinterSettings
,lpszPrinterName
);
333 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
334 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
336 WARN("The registry did not contain my printer anymore?\n");
340 if (bCalcSpaceOnly
==FALSE
)
341 lpPInfo2
->pServerName
= NULL
;
342 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
343 "Name", &(lpPInfo2
->pPrinterName
),
344 lpbPrinters
, dwNextStringPos
,
345 dwBufSize
, bCalcSpaceOnly
);
346 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
347 "Share Name", &(lpPInfo2
->pShareName
),
348 lpbPrinters
, dwNextStringPos
,
349 dwBufSize
, bCalcSpaceOnly
);
350 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
351 "Port", &(lpPInfo2
->pPortName
),
352 lpbPrinters
, dwNextStringPos
,
353 dwBufSize
, bCalcSpaceOnly
);
354 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
355 "Printer Driver", &(lpPInfo2
->pDriverName
),
356 lpbPrinters
, dwNextStringPos
,
357 dwBufSize
, bCalcSpaceOnly
);
358 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
359 "Description", &(lpPInfo2
->pComment
),
360 lpbPrinters
, dwNextStringPos
,
361 dwBufSize
, bCalcSpaceOnly
);
362 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
363 "Location", &(lpPInfo2
->pLocation
),
364 lpbPrinters
, dwNextStringPos
,
365 dwBufSize
, bCalcSpaceOnly
);
367 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
368 "Separator File", &(lpPInfo2
->pSepFile
),
369 lpbPrinters
, dwNextStringPos
,
370 dwBufSize
, bCalcSpaceOnly
);
371 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
372 "Print Processor", &(lpPInfo2
->pPrintProcessor
),
373 lpbPrinters
, dwNextStringPos
,
374 dwBufSize
, bCalcSpaceOnly
);
375 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
376 "Datatype", &(lpPInfo2
->pDatatype
),
377 lpbPrinters
, dwNextStringPos
,
378 dwBufSize
, bCalcSpaceOnly
);
379 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
380 "Parameters", &(lpPInfo2
->pParameters
),
381 lpbPrinters
, dwNextStringPos
,
382 dwBufSize
, bCalcSpaceOnly
);
383 if (bCalcSpaceOnly
== FALSE
)
385 lpPInfo2
->pSecurityDescriptor
= NULL
; /* EnumPrinters doesn't return this*/
387 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
388 lpPInfo2
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
389 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
390 lpPInfo2
->Priority
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
392 lpPInfo2
->DefaultPriority
= ENUMPRINTERS_GetDWORDFromRegistryA(
393 hPrinterSettings
, "Default Priority");
394 lpPInfo2
->StartTime
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
396 lpPInfo2
->UntilTime
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
398 lpPInfo2
->Status
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
400 lpPInfo2
->cJobs
= 0; /* FIXME: according to MSDN, this does not
401 * reflect the TotalJobs Key ??? */
402 lpPInfo2
->AveragePPM
= 0; /* FIXME: according to MSDN, this does not
403 * reflect the TotalPages Key ??? */
405 /* and read the devModes structure... */
406 RegQueryValueExA(hPrinterSettings
, "pDevMode", NULL
, &DataType
,
407 NULL
, &DevSize
); /* should return ERROR_MORE_DATA */
408 lpPInfo2
->pDevMode
= (LPDEVMODEA
) &lpbPrinters
[*dwNextStringPos
];
409 *dwNextStringPos
+= DevSize
+ 1;
411 if (*dwNextStringPos
> dwBufSize
)
413 if (bCalcSpaceOnly
==FALSE
)
414 RegQueryValueExA(hPrinterSettings
, "pDevMode", NULL
, &DataType
,
415 (LPBYTE
)lpPInfo2
->pDevMode
, &DevSize
);
418 if (lpszPrinterSettings
)
419 free(lpszPrinterSettings
);
421 return(bCalcSpaceOnly
);
424 /******************************************************************
425 * ENUMPRINTERS_AddInfo4A internal
427 * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos]
428 * for printer PrinterNameKey.
429 * Note that there is no check whether the information really fits!
432 * FALSE if there is still space left in the buffer.
435 * This function should not exist in Win95 mode, but does anyway.
437 BOOL
ENUMPRINTERS_AddInfo4A(
438 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
439 LPBYTE lpbPrinters
, /* buffer which receives info*/
440 DWORD dwNextStructPos
, /* pos in buffer for struct */
441 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
442 DWORD dwBufSize
, /* max size of buffer in bytes */
443 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
445 HKEY hPrinterSettings
;
446 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
447 strlen(lpszPrinterName
)+2);
448 LPPRINTER_INFO_4A lpPInfo4
= (LPPRINTER_INFO_4A
) &lpbPrinters
[dwNextStructPos
];
450 /* open the registry to find the attributes of the printer */
451 if (lpszPrinterSettings
!=NULL
)
453 strcpy(lpszPrinterSettings
,Printers
);
454 strcat(lpszPrinterSettings
,lpszPrinterName
);
456 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
457 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
459 WARN("The registry did not contain my printer anymore?\n");
463 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
464 "Name", &(lpPInfo4
->pPrinterName
),
465 lpbPrinters
, dwNextStringPos
,
466 dwBufSize
, bCalcSpaceOnly
);
467 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
468 if (bCalcSpaceOnly
==FALSE
)
469 lpPInfo4
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
470 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
472 if (lpszPrinterSettings
)
473 free(lpszPrinterSettings
);
475 return(bCalcSpaceOnly
);
478 /******************************************************************
479 * ENUMPRINTERS_AddInfo5A internal
481 * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos]
482 * for printer PrinterNameKey.
483 * Settings are read from the registry.
484 * Note that there is no check whether the information really fits!
486 * FALSE if there is still space left in the buffer.
488 BOOL
ENUMPRINTERS_AddInfo5A(
489 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
490 LPBYTE lpbPrinters
, /* buffer which receives info*/
491 DWORD dwNextStructPos
, /* pos in buffer for struct */
492 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
493 DWORD dwBufSize
, /* max size of buffer in bytes */
494 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
496 HKEY hPrinterSettings
;
497 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
498 strlen(lpszPrinterName
)+2);
499 LPPRINTER_INFO_5A lpPInfo5
= (LPPRINTER_INFO_5A
) &lpbPrinters
[dwNextStructPos
];
501 /* open the registry to find the attributes, etc of the printer */
502 if (lpszPrinterSettings
!=NULL
)
504 strcpy(lpszPrinterSettings
,Printers
);
505 strcat(lpszPrinterSettings
,lpszPrinterName
);
507 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
508 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
510 WARN("The registry did not contain my printer anymore?\n");
514 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
515 "Name", &(lpPInfo5
->pPrinterName
),
516 lpbPrinters
, dwNextStringPos
,
517 dwBufSize
, bCalcSpaceOnly
);
518 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
519 "Port", &(lpPInfo5
->pPortName
), lpbPrinters
,
520 dwNextStringPos
, dwBufSize
, bCalcSpaceOnly
);
521 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
522 if (bCalcSpaceOnly
== FALSE
)
524 lpPInfo5
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
525 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
526 lpPInfo5
->DeviceNotSelectedTimeOut
527 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
529 lpPInfo5
->TransmissionRetryTimeout
530 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
535 if (lpszPrinterSettings
)
536 free(lpszPrinterSettings
);
538 return(bCalcSpaceOnly
);
542 /******************************************************************
543 * EnumPrintersA [WINSPOOL.174]
545 * Enumerates the available printers, print servers and print
546 * providers, depending on the specified flags, name and level.
550 * If level is set to 1:
551 * Not implemented yet!
552 * Returns TRUE with an empty list.
554 * If level is set to 2:
555 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
556 * Returns an array of PRINTER_INFO_2 data structures in the
557 * lpbPrinters buffer. Note that according to MSDN also an
558 * OpenPrinter should be performed on every remote printer.
560 * If level is set to 4 (officially WinNT only):
561 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
562 * Fast: Only the registry is queried to retrieve printer names,
563 * no connection to the driver is made.
564 * Returns an array of PRINTER_INFO_4 data structures in the
565 * lpbPrinters buffer.
567 * If level is set to 5 (officially WinNT4/Win9x only):
568 * Fast: Only the registry is queried to retrieve printer names,
569 * no connection to the driver is made.
570 * Returns an array of PRINTER_INFO_5 data structures in the
571 * lpbPrinters buffer.
573 * If level set to 3 or 6+:
574 * returns zero (faillure!)
576 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
580 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
581 * - Only levels 2, 4 and 5 are implemented at the moment.
582 * - 16-bit printer drivers are not enumerated.
583 * - Returned amount of bytes used/needed does not match the real Windoze
584 * implementation (as in this implementation, all strings are part
585 * of the buffer, whereas Win32 keeps them somewhere else)
586 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
589 * - In a regular Wine installation, no registry settings for printers
590 * exist, which makes this function return an empty list.
592 BOOL WINAPI
EnumPrintersA(
593 DWORD dwType
, /* Types of print objects to enumerate */
594 LPSTR lpszName
, /* name of objects to enumerate */
595 DWORD dwLevel
, /* type of printer info structure */
596 LPBYTE lpbPrinters
,/* buffer which receives info*/
597 DWORD cbBuf
, /* max size of buffer in bytes */
598 LPDWORD lpdwNeeded
,/* pointer to var: # bytes used/needed */
599 LPDWORD lpdwReturned
/* number of entries returned */
602 HKEY hPrinterListKey
;
604 char PrinterName
[255];
605 DWORD PrinterNameLength
=255;
607 DWORD dwNextStringPos
; /* position of next space for a string in the buffer*/
608 DWORD dwStructPrinterInfoSize
; /* size of a Printer_Info_X structure */
609 BOOL bCalcSpaceOnly
=FALSE
;/* if TRUE: don't store data, just calculate space*/
613 /* test whether we're requested to really fill in. If so,
614 * zero out the data area, and initialise some returns to zero,
615 * to prevent problems
617 if (lpbPrinters
==NULL
|| cbBuf
==0)
622 for (i
=0; i
<cbBuf
; i
++)
628 /* check for valid Flags */
629 if (dwType
!= PRINTER_ENUM_LOCAL
&& dwType
!= PRINTER_ENUM_NAME
)
631 SetLastError(ERROR_INVALID_FLAGS
);
643 SetLastError(ERROR_INVALID_PARAMETER
);
647 /* Enter critical section to prevent AddPrinters() et al. to
648 * modify whilst we're reading in the registry
650 InitializeCriticalSection(&PRINT32_RegistryBlocker
);
651 EnterCriticalSection(&PRINT32_RegistryBlocker
);
653 /* get a pointer to a list of all printer names in the registry */
654 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, Printers
, 0, KEY_READ
,
655 &hPrinterListKey
) !=ERROR_SUCCESS
)
657 /* Oh no! An empty list of printers!
658 * (which is a valid configuration anyway)
660 TRACE("No entries in the Printers part of the registry\n");
663 /* count the number of entries and check if it fits in the buffer
665 while(RegEnumKeyExA(hPrinterListKey
, dwIndex
, PrinterName
, &PrinterNameLength
,
666 NULL
, NULL
, NULL
, &FileTime
)==ERROR_SUCCESS
)
668 PrinterNameLength
=255;
671 *lpdwReturned
= dwIndex
;
675 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_1A
);
678 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_2A
);
681 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_4A
);
684 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_5A
);
687 dwStructPrinterInfoSize
= 0;
690 if (dwIndex
*dwStructPrinterInfoSize
+1 > cbBuf
)
691 bCalcSpaceOnly
= TRUE
;
693 /* the strings which contain e.g. PrinterName, PortName, etc,
694 * are also stored in lpbPrinters, but after the regular structs.
695 * dwNextStringPos will always point to the next free place for a
698 dwNextStringPos
=(dwIndex
+1)*dwStructPrinterInfoSize
;
700 /* check each entry: if OK, add to list in corresponding INFO .
702 for(dwIndex
=0; dwIndex
< *lpdwReturned
; dwIndex
++)
704 PrinterNameLength
=255;
705 if (RegEnumKeyExA(hPrinterListKey
, dwIndex
, PrinterName
, &PrinterNameLength
,
706 NULL
, NULL
, NULL
, &FileTime
)!=ERROR_SUCCESS
)
707 break; /* exit for loop*/
709 /* check whether this printer is allowed in the list
710 * by comparing name to lpszName
712 if (dwType
== PRINTER_ENUM_NAME
)
713 if (strcmp(PrinterName
,lpszName
)!=0)
719 /* FIXME: unimplemented */
722 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo2A(PrinterName
, lpbPrinters
,
723 dwIndex
*dwStructPrinterInfoSize
,
724 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
727 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo4A(PrinterName
, lpbPrinters
,
728 dwIndex
*dwStructPrinterInfoSize
,
729 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
732 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo5A(PrinterName
, lpbPrinters
,
733 dwIndex
*dwStructPrinterInfoSize
,
734 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
738 RegCloseKey(hPrinterListKey
);
739 *lpdwNeeded
= dwNextStringPos
;
741 if (bCalcSpaceOnly
==TRUE
)
743 if (lpbPrinters
!=NULL
)
746 for (i
=0; i
<cbBuf
; i
++)
751 LeaveCriticalSection(&PRINT32_RegistryBlocker
);
755 /******************************************************************
756 * EnumPrinters32W [WINSPOOL.175]
759 BOOL WINAPI
EnumPrintersW(DWORD dwType
, LPWSTR lpszName
,
760 DWORD dwLevel
, LPBYTE lpbPrinters
,
761 DWORD cbBuf
, LPDWORD lpdwNeeded
,
762 LPDWORD lpdwReturned
)
764 FIXME("Nearly empty stub\n");
770 /******************************************************************
771 * AddMonitor32A [WINSPOOL.107]
774 BOOL WINAPI
AddMonitorA(LPCSTR pName
, DWORD Level
, LPBYTE pMonitors
)
776 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
777 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
781 /******************************************************************
782 * DeletePrinterDriver32A [WINSPOOL.146]
786 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
788 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
789 debugstr_a(pDriverName
));
790 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
795 /******************************************************************
796 * DeleteMonitor32A [WINSPOOL.135]
800 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
802 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
803 debugstr_a(pMonitorName
));
804 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
809 /******************************************************************
810 * DeletePort32A [WINSPOOL.137]
814 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
816 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
817 debugstr_a(pPortName
));
818 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
822 /******************************************************************************
823 * SetPrinter32W [WINSPOOL.214]
833 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
837 /******************************************************************************
838 * WritePrinter32 [WINSPOOL.223]
848 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
852 /*****************************************************************************
853 * AddForm32A [WINSPOOL.103]
855 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
857 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
861 /*****************************************************************************
862 * AddForm32W [WINSPOOL.104]
864 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
866 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
870 /*****************************************************************************
871 * AddJob32A [WINSPOOL.105]
873 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
874 DWORD cbBuf
, LPDWORD pcbNeeded
)
876 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
881 /*****************************************************************************
882 * AddJob32W [WINSPOOL.106]
884 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
887 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
892 /*****************************************************************************
893 * AddPrinter32A [WINSPOOL.117]
895 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
897 FIXME("(%s,%ld,%p): stub\n", pName
, Level
, pPrinter
);
901 /*****************************************************************************
902 * AddPrinter32W [WINSPOOL.122]
904 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
906 FIXME("(%p,%ld,%p): stub\n", pName
, Level
, pPrinter
);
911 /*****************************************************************************
912 * ClosePrinter32 [WINSPOOL.126]
914 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
916 LPOPENEDPRINTERA lpOpenedPrinter
;
918 if ((hPrinter
!= -1) && (hPrinter
< NUM_PRINTER_MAX
+ 1))
920 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
921 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter
->lpsPrinterName
);
922 lpOpenedPrinter
->lpsPrinterName
= NULL
;
924 /* Free the memory of lpDefault if it has been initialized*/
925 if(lpOpenedPrinter
->lpDefault
!= NULL
)
927 HeapFree(GetProcessHeap(), 0,
928 lpOpenedPrinter
->lpDefault
->pDevMode
);
929 HeapFree(GetProcessHeap(), 0,
930 lpOpenedPrinter
->lpDefault
->pDatatype
);
931 HeapFree(GetProcessHeap(), 0,
932 lpOpenedPrinter
->lpDefault
);
933 lpOpenedPrinter
->lpDefault
= NULL
;
936 lpOpenedPrinter
->hPrinter
= -1;
943 /*****************************************************************************
944 * DeleteForm32A [WINSPOOL.133]
946 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
948 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
952 /*****************************************************************************
953 * DeleteForm32W [WINSPOOL.134]
955 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
957 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
961 /*****************************************************************************
962 * DeletePrinter32 [WINSPOOL.143]
964 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
966 FIXME("(%d): stub\n", hPrinter
);
970 /*****************************************************************************
971 * SetPrinter32A [WINSPOOL.211]
973 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
976 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
980 /*****************************************************************************
981 * SetJob32A [WINSPOOL.209]
983 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
984 LPBYTE pJob
, DWORD Command
)
986 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
991 /*****************************************************************************
992 * SetJob32W [WINSPOOL.210]
994 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
995 LPBYTE pJob
, DWORD Command
)
997 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1002 /*****************************************************************************
1003 * GetForm32A [WINSPOOL.181]
1005 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1006 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1008 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1009 Level
,pForm
,cbBuf
,pcbNeeded
);
1013 /*****************************************************************************
1014 * GetForm32W [WINSPOOL.182]
1016 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1017 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1019 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1020 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1024 /*****************************************************************************
1025 * SetForm32A [WINSPOOL.207]
1027 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1030 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1034 /*****************************************************************************
1035 * SetForm32W [WINSPOOL.208]
1037 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1040 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1044 /*****************************************************************************
1045 * ReadPrinter32 [WINSPOOL.202]
1047 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1048 LPDWORD pNoBytesRead
)
1050 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1054 /*****************************************************************************
1055 * ResetPrinter32A [WINSPOOL.203]
1057 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1059 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1063 /*****************************************************************************
1064 * ResetPrinter32W [WINSPOOL.204]
1066 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1068 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1072 /*****************************************************************************
1073 * GetPrinter32A [WINSPOOL.187]
1075 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1076 DWORD cbBuf
, LPDWORD pcbNeeded
)
1078 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pPrinter
,
1081 *pcbNeeded
= sizeof(PRINTER_INFO_2A
);
1083 if(cbBuf
< *pcbNeeded
) {
1084 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1087 memset(pPrinter
, 0, cbBuf
);
1092 /*****************************************************************************
1093 * GetPrinter32W [WINSPOOL.194]
1095 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1096 DWORD cbBuf
, LPDWORD pcbNeeded
)
1098 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pPrinter
,
1103 /*****************************************************************************
1104 * GetPrinterDriver32A [WINSPOOL.190]
1106 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
1107 DWORD Level
, LPBYTE pDriverInfo
,
1108 DWORD cbBuf
, LPDWORD pcbNeeded
)
1110 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pEnvironment
,
1111 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1115 /*****************************************************************************
1116 * GetPrinterDriver32W [WINSPOOL.193]
1118 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
1119 DWORD Level
, LPBYTE pDriverInfo
,
1120 DWORD cbBuf
, LPDWORD pcbNeeded
)
1122 FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter
,pEnvironment
,
1123 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1126 /*****************************************************************************
1127 * AddPrinterDriver32A [WINSPOOL.120]
1129 BOOL WINAPI
AddPrinterDriverA(LPSTR printerName
,DWORD level
,
1132 FIXME("(%s,%ld,%p): stub\n",printerName
,level
,pDriverInfo
);
1135 /*****************************************************************************
1136 * AddPrinterDriver32W [WINSPOOL.121]
1138 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
1141 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
1147 /*****************************************************************************
1148 * PrinterProperties [WINSPOOL.201]
1150 * Displays a dialog to set the properties of the printer.
1153 * nonzero on succes or zero on faillure
1156 * implemented as stub only
1158 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* handle to parent window */
1159 HANDLE hPrinter
/* handle to printer object */
1161 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
1162 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);